0

我试图让我的第一个触发器和函数工作,但我如何抛出异常并以正确的方式返回数据?

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"
4

3 回答 3

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";
于 2009-11-19T13:05:48.440 回答
0

不知道你想找出什么。您正在设法提出自己的例外情况,这很好。我希望任何错误处理都在调用此方法的代码中。

如果你想在过程中做一些事情,你需要一个 EXCEPTION 部分:

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

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

于 2009-11-19T13:12:21.827 回答
0

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

DECLARE
  [...]
  c boolean;
SELECT 
    COUNT(id) INTO c
  FROM 
    "SHIFTS" 
  WHERE 
  [...]
于 2009-11-19T13:12:57.957 回答