PostgreSQL Trigger und Ausnahmen
-
21-09-2019 - |
Frage
Ich versuche, meinen ersten Trigger und Funktion zur Arbeit zu kommen, aber wie ich werfe Ausnahmen und Rückgabedaten richtig?
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"
Lösung
Sie haben einen Fehler hier bekommen:
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)
)
;
Eine solche in einem plpgsql Verfahren wählen hat SELECT INTO ... so sein:
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;
Und hier du hast das Semikolon am Ende der Leitung haben:
enter code here`RAISE EXCEPTION "Shift is locked";
Andere Tipps
Nicht sicher, was Sie versuchen, um herauszufinden. Sie verwalten Ihre eigenen Ausnahmen zu erhöhen, so dass das gut. Ich würde erwarten, dass jede Fehlerbehandlung im Code sein würde, die diese Methode hervorruft.
Wenn Sie etwas in dem Verfahren tun möchten, benötigen Sie einen AUSNAHME Abschnitt:
[<>] [DECLARE Erklärungen] START Aussagen AUSNAHME WHEN Bedingung [OR Bedingung ...] THEN handler_statements [WHEN Bedingung [OR Bedingung ...] THEN handler_statements ...] END;
Aber im Allgemeinen erwartet ich, würde Sie es in dem Aufruf-Code behandeln würden.
Sie haben SELECT INTO verwenden, um einen Wert von einer Abfrage
zurück zu bekommenDECLARE
[...]
c boolean;
SELECT
COUNT(id) INTO c
FROM
"SHIFTS"
WHERE
[...]