2009-11-19 61 views
0

我想让我的第一次触发器和函数工作,但我如何抛出异常并返回正确的数据?PostgreSQL触发器和例外

的PostgreSQL 8.4.1

CREATE TABLE "SHIFTS" (
    id integer NOT NULL, -- SERIAL 
    added timestamp without time zone DEFAULT now() NOT NULL, 
    starts timestamp without time zone NOT NULL, 
    ends timestamp without time zone NOT NULL, 
    employee_id integer, 
    modified timestamp without time zone, 
    status integer DEFAULT 1 NOT NULL, 
    billid integer, 
    CONSTRAINT "SHIFTS_check" CHECK ((starts < ends)) 
); 


-- Check if given shift time overlaps with existing data 
CREATE OR REPLACE FUNCTION 
    shift_overlaps (integer, timestamp, timestamp) 
RETURNS 
    boolean AS $$ 
DECLARE 
    _employeeid ALIAS FOR $1; 
    _start  ALIAS FOR $2; 
    _end  ALIAS FOR $3; 
BEGIN 
    SELECT 
    COUNT(id) AS c 
    FROM 
    "SHIFTS" 
    WHERE 
    employee_id = _employeeid AND 
    status = 1 AND 
    (
     (starts BETWEEN _start AND _end) 
     OR 
     (ends BETWEEN _start AND _end) 
    ) 
    ; 

    -- Return boolean 
    RETURN (c > 0); 
END; 
$$ 
LANGUAGE 
    plpgsql 
; 


CREATE OR REPLACE FUNCTION 
    check_shift() 
RETURNS trigger AS ' 
BEGIN 

    -- Bill ID is set, do not allow update 
    IF tg_op = "UPDATE" THEN 
    IF old.billid IS NOT NULL THEN 
     RAISE EXCEPTION "Shift is locked" 
    END IF; 
    END IF; 

    -- Check for overlap 
    IF tg_op = "INSERT" THEN 
    IF new.employee_id IS NOT NULL THEN 
     IF shift_overlaps(new.employee_id, new.starts, new.ends) THEN 
     RAISE EXCEPTION "Given time overlaps with shifts" 
     END IF; 
    END IF; 
    END IF; 

    -- Check for overlap 
    IF tg_op = "UPDATE" THEN 
    IF (new.employee_id IS NOT NULL) AND (new.status = 1) THEN 
     IF shift_overlaps(new.employee_id, new.starts, new.ends) THEN 
     RAISE EXCEPTION "Given time overlaps with shifts" 
     END IF; 
    END IF; 
    END IF; 

    RETURN new; 
END 
' 
LANGUAGE 
    plpgsql 
; 


-- Shift checker trigger 
CREATE TRIGGER 
    check_shifts 
BEFORE 
    INSERT OR UPDATE 
ON 
    "SHIFTS" 
FOR EACH ROW EXECUTE PROCEDURE 
    check_shift() 
; 

shift_overlaps():

SQL error: ERROR: query has no destination for result data 

check_shift():

SQL error: ERROR: unrecognized exception condition "Shift is locked" 

回答

3

你有一个错误的位置:

SELECT 
    COUNT(id) AS c 
    FROM 
    "SHIFTS" 
    WHERE 
    employee_id = _employeeid AND 
    status = 1 AND 
    (
     (starts BETWEEN _start AND _end) 
     OR 
     (ends BETWEEN _start AND _end) 
    ) 
    ; 

这样的PLPGSQL过程中的选择必须是SELECT INTO ...这样的:

DECLARE 
c INTEGER; 
BEGIN 
    SELECT 
    COUNT(id) 
    INTO c 
    FROM 
    "SHIFTS" 
    WHERE 
    employee_id = _employeeid AND 
    status = 1 AND 
    (
     (starts BETWEEN _start AND _end) 
     OR 
     (ends BETWEEN _start AND _end) 
    ) 
    ; 

    RETURN (c > 0); 

END; 

在这里,你必须有在该行的最后的分号:

enter code here`RAISE EXCEPTION "Shift is locked"; 
0

不知道你在找什么。你正在设法提出你自己的例外,所以这很好。我期望任何错误处理都会在唤起这种方法的代码中出现。

如果你想要做的程序里面的东西,你需要一个异常的部分:

[<>] [DECLARE 声明] BEGIN 声明 EXCEPTION WHEN条件[OR条件...] THEN handler_statements [WHEN condition [OR condition ...] THEN handler_statements ...] END;

但通常我会希望你会在调用代码中处理它。

0

你必须使用SELECT INTO获取查询返回的值

DECLARE 
    [...] 
    c boolean; 
SELECT 
    COUNT(id) INTO c 
    FROM 
    "SHIFTS" 
    WHERE 
    [...]