2013-04-06 41 views
0
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

回答

1
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 *將返回插入的行。
1
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