PostgreSQL函数无法检测选择条件

问题描述:

CREATE OR REPLACE FUNCTION heckANDinsert(
    first VARCHAR(20), surname VARCHAR(20), 
    No VARCHAR(30), nation VARCHAR(30), dob DATE 
) RETURNS SETOF passenger AS $$ 
DECLARE 

name VARCHAR(20); 
Sname VARCHAR(20); 
Pass VARCHAR(30); 
nation VARCHAR(30); 
birthdate DATE; 

BEGIN 

SELECT first, same,passportNo, nationality,dob 
INTO fname,sname, PassportN, nation, birthdate 
FROM passenger 
WHERE 
    firstname = $1 
    AND surname = $2 
    AND passportNo = $3 
    AND nationality = $4 
    AND dob = $5; 

IF NOT FOUND THEN 
    INSERT INTO passenger 
    SELECT MAX(passengerid)+1, $1,$2,$3,$4,$5 
    FROM passenger; 
ELSE 
    RAISE EXCEPTION 'passenger record already exists.'; 
END IF; 

END; 
$$ LANGUAGE plpgsql; 

我叫使用PostgreSQL函数无法检测选择条件

SELECT passenger_checkANDinsert( 
    'john', 'levis', 'v39949455', 'British', '1990-07-23' 
); 

功能将插入正确的结果到数据库中,如果我更改名字到另一个功能。但如果我更改姓氏并保持与数据库数据相同的名字,它将不起作用。我想有东西在SELECT语句中错在何处的功能状态,但我找不到任何错误的..

+0

抱歉输入错误.. firstname是数据库乘客表中的一列。 – johnnily 2013-04-06 19:37:36

+0

为什么使用函数而不是将passengerid设置为'SERIAL'并在表上添加唯一约束? – 2013-04-06 20:06:22

+0

因为passengerid类型是INTEGER。出于某种原因,我不允许更改数据类型。 – johnnily 2013-04-06 20:09:43

create or replace function passenger_checkandinsert(
    _firstname varchar(20), _surname varchar(20), 
    _passportno varchar(30), _nationality varchar(30), _dob date 
) returns setof passenger as $$ 

insert into passenger (
    passengerid, firstname, surname, passportNo, nationality, dob 
) 
select coalesce(max(passengerid)+1, 1), $1, $2, $3, $4, $5 
from passenger 
where not exists ( 
    select 1 
    from passenger 
    where 
     firstname = $1 
     and surname = $2 
     and passportno = $3 
     and nationality = $4 
     and dob = $5 
    ) 
returning * 
; 
$$ language sql; 
  • 变量使用列的名称可以是有问题的。只需预先加下划线即可。
  • 声明您要插入值的列。
  • 简单的SQL将尽你所需。
  • 不要做count来检查行是否存在,因为它会读取整个表。而是使用exists,因为它会停止在第一个找到的行中读取。
  • 注意合并来处理没有行的情况。
  • returning *将返回插入的行。

CREATE OR REPLACE FUNCTION passenger_checkANDinsert 

(firstname VARCHAR(20),surname VARCHAR(20), 

passportNo VARCHAR(30),nationality VARCHAR(30),dob DATE) 

RETURNS SETOF passenger AS 
$$ 

DECLARE 

_exists boolean;  

BEGIN 

SELECT count(*)>0 INTO _exists FROM passenger  
WHERE firstname = $1 AND surname = $2 AND passportNo = $3 AND nationality = $4 AND dob = $5; 

IF NOT _exists THEN 

    INSERT INTO passenger SELECT MAX(passengerid)+1, $1,$2,$3,$4,$5 FROM passenger; 

    ELSE 

    RAISE EXCEPTION 'passenger record already exists.'; 

    END IF; 

END; 

$$ 

    LANGUAGE plpgsql; 

我认为你正在做的不好用MAX(passengerid)+1,你为什么不使用数据类型bigserial?如果你这样做只是为了不失去这个领域的一段时间,你是不正确的。

也许你需要通过向列率添加到您的领域:

CREATE SEQUENCE passengerid_seq; 
ALTER TABLE passenger ALTER COLUMN passengerid SET DEFAULT NEXTVAL('passengerid_seq'); 
+0

因为passengerid的类型是INTEGER..i无法更改的。 – johnnily 2013-04-06 20:05:42

+0

@johnnily看看如何在不修改'passengerid'字段的数据类型的情况下添加序列 – Houari 2013-04-06 20:18:48

+1

+1指出使用'max()'是一个非常糟糕的主意。 – 2013-04-06 20:33:36