Postgresql

Postgres - 在 Execute 內部使用時,IF 附近的語法錯誤

  • July 26, 2017

我正在使用更新後觸發器來辨識並記錄對“任務”表中的記錄所做的任何更改。列,新舊值都是動態的,所以每次都不一樣。

這是觸發器函式現在的樣子:

CREATE OR REPLACE FUNCTION fn_tasks_after_update()
RETURNS trigger
AS $BODY$ 
DECLARE 
   ri RECORD;
   col_name TEXT;
BEGIN 
   FOR ri IN
       SELECT column_name FROM information_schema.columns WHERE table_name = 'tasks'
   LOOP
       EXECUTE
           'IF $1.' || ri.column_name || ' <> $2.' || ri.column_name || ' THEN
               INSERT INTO tasks_log (task_id, type, "column", old_value, new_value) 
               VALUES ($1.id, $$update$$, $3, $1.' || ri.column_name || ', $2.' || ri.column_name || ');
           END IF;'
       USING NEW, OLD, ri.column_name;
   END LOOP;
   RETURN NEW;
END; $BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION fn_tasks_after_update()
OWNER TO postgres;

觸發器在添加 IF 之前工作,語法似乎與“INSERT INTO tasks_log”塊中的語法沒有任何不同。

這確實有效:

EXECUTE
   'INSERT INTO tasks_log (task_id, type, "column", old_value, new_value) 
   VALUES ($1.id, $$update$$, $3, $1.' || ri.column_name || ', $2.' || ri.column_name || ');'

這不起作用:

EXECUTE
   'IF $1.' || ri.column_name || ' <> $2.' || ri.column_name || ' THEN
       INSERT INTO tasks_log (task_id, type, "column", old_value, new_value) 
       VALUES ($1.id, $$update$$, $3, $1.' || ri.column_name || ', $2.' || ri.column_name || ');
   END IF;' 

出了什麼問題?

由於Abelisto評論,這是解決方案:

CREATE OR REPLACE FUNCTION fn_tasks_after_update()
RETURNS trigger
AS $BODY$ 
DECLARE 
   ri RECORD;
   is_changed BOOLEAN;
BEGIN 
   FOR ri IN
       SELECT column_name FROM information_schema.columns WHERE table_name = 'tasks'
   LOOP
       EXECUTE 'SELECT $1.' || ri.column_name || ' <> $2.' || ri.column_name
       USING NEW, OLD
       INTO is_changed;

       IF is_changed THEN
           EXECUTE
               'INSERT INTO tasks_log (task_id, type, "column", old_value, new_value) 
               VALUES ($1.id, $$update$$, $3, $1.' || ri.column_name || ', $2.' || ri.column_name || ');'
           USING NEW, OLD, ri.column_name;
       END IF;
   END LOOP;
   RETURN NEW;
END; $BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION fn_tasks_after_update()
OWNER TO postgres;

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