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;
SELECT passenger_checkANDinsert(
'john', 'levis', 'v39949455', 'British', '1990-07-23'
);
功能将插入正确的结果到数据库中,如果我更改名字到另一个功能。但如果我更改姓氏并保持与数据库数据相同的名字,它将不起作用。我想有东西在SELECT语句中错在何处的功能状态,但我找不到任何错误的..
答
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');
抱歉输入错误.. firstname是数据库乘客表中的一列。 – johnnily 2013-04-06 19:37:36
为什么使用函数而不是将passengerid设置为'SERIAL'并在表上添加唯一约束? – 2013-04-06 20:06:22
因为passengerid类型是INTEGER。出于某种原因,我不允许更改数据类型。 – johnnily 2013-04-06 20:09:43