Postgresql

列名作為觸發器中呼叫的函式的參數(PostgreSQL)

  • October 28, 2021

我查看了所有類似的問題,但似乎我沒有足夠的知識將它們應用於我的問題。

看看下面的程式碼。底線是我有一個更新updated_at欄位的函式,該欄位會針對觸發觸發器的表進行更新。

CREATE TEMPORARY TABLE types(
   id SMALLINT GENERATED ALWAYS AS IDENTITY,
   type TEXT UNIQUE,
   updated_at TIMESTAMPTZ
);


CREATE OR REPLACE FUNCTION update_column()
RETURNS TRIGGER AS $$
BEGIN
   NEW.updated_at = now();
   RETURN NEW;
END;
$$ language 'plpgsql';


CREATE TRIGGER column_was_updated BEFORE INSERT OR UPDATE OF type
ON types FOR EACH ROW EXECUTE PROCEDURE
update_column();


INSERT INTO types (type)
VALUES ('type1'), ('type2');


SELECT * FROM types

我想做以下事情:從觸發器呼叫函式時,將列名作為參數傳遞給函式以替換文字列名updated_at,如下所示:

CREATE OR REPLACE FUNCTION update_column()
RETURNS TRIGGER AS $$
BEGIN
   NEW.column_name = now();
   RETURN NEW;
END;
$$ language 'plpgsql';


CREATE TRIGGER column_was_updated BEFORE INSERT OR UPDATE OF type
ON types FOR EACH ROW EXECUTE PROCEDURE
update_column('column_name');

我怎樣才能做到這一點?

PS 我使用 PostgreSQL v.14。

可以這樣做。這也很簡單:

-- trigger function
CREATE OR REPLACE FUNCTION update_column()
 RETURNS trigger
 LANGUAGE plpgsql AS
$func$
BEGIN
  NEW := json_populate_record(NEW, json_build_object(TG_ARGV[0], now()));
  RETURN NEW;
END
$func$;

-- trigger
CREATE TRIGGER column_was_updated
BEFORE INSERT OR UPDATE OF type ON types
FOR EACH ROW EXECUTE FUNCTION update_column('updated_at');

db<>在這裡擺弄

使用觸發函式的特殊變數TG_ARGV,並json_populate_record()動態設置欄位。看:

但這並不意味著您應該這樣做。通常,您要麼只使用一個DEFAULT

CREATE TABLE types (
 id smallint GENERATED ALWAYS AS IDENTITY
, type text UNIQUE
, updated_at timestamptz DEFAULT now()  -- here!
);

但是,它可以被輸入覆蓋,因此它比覆蓋任何輸入的觸發器弱。

或者你為每個觸發器編寫一個單獨的函式。就像你已經擁有的一樣。很簡單。意味著每個涉及的表都有一個單獨的觸發函式,但沒有動態元素執行速度更快。

上述“智能”解決方案的這些簡單選項之間幾乎沒有空間。

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