Postgresql

觸發器無法訪問列循環

  • September 16, 2014

SSCCE:以下腳本:

$ cat test.sql 
CREATE TABLE public.foo (
loop INTEGER
);

CREATE OR REPLACE FUNCTION public.foo_fun(loop INTEGER) RETURNS BOOLEAN AS $$
   SELECT TRUE;
$$ LANGUAGE SQL;

CREATE OR REPLACE FUNCTION public.foo_tr_fun() RETURNS TRIGGER AS $$
DECLARE
   fRV BOOLEAN;
BEGIN
   SELECT public.foo_fun(NEW.loop) INTO fRV;
IF fRV THEN
   RETURN NEW;
ELSE
   RAISE EXCEPTION 'bar';
END IF;
END
$$ LANGUAGE plpgsql;

CREATE TRIGGER foo_tr AFTER INSERT OR UPDATE ON public.foo
FOR EACH ROW
EXECUTE PROCEDURE public.foo_tr_fun();

…我執行:

psql -v ON_ERROR_STOP=1 --quiet -X -U some-user -d some-db -f test.sql

foo…當我嘗試在(從)中插入一行時psql

$ psql -U some-user some-db
psql (9.1.14)
Type "help" for help.

RegTAP=> SELECT * FROM public.foo;
loop 
------
(0 rows)

RegTAP=> INSERT INTO public.foo(loop) VALUES(0);
ERROR:  record "new" has no field "loop"
LINE 1: SELECT public.foo_fun(NEW.loop)
                             ^
QUERY:  SELECT public.foo_fun(NEW.loop)
CONTEXT:  PL/pgSQL function "foo_tr_fun" line 5 at SQL statement
RegTAP=> 

事實證明,關鍵字 loop需要在 PL/pgSQL 中用雙引號引起來,否則解析器會感到困惑:

SELECT public.foo_fun(NEW.**"loop"**) INTO fRV;

Postgres 9.3 中的情況沒有改變:

帶引號的 SQL 擺弄(有效)。

不帶引號的 SQL 小提琴(不起作用)。

避免使用諸如loop標識符之類的典型關鍵字通常是個好主意。除了SQL 關鍵字之外,還有一些 plpgsql 關鍵字(例如用於過程元素或異常處理),但我不知道其他 plpgsql 關鍵字的完整列表。原始碼將是我最好的主意。

我在 2007 年發現了關於 pgsql-hackers 的相關討論。看來這個問題還沒有完全解決。

在這裡也沒有看到 Postgres 9.4 的任何變化……

引用自:https://dba.stackexchange.com/questions/76776