我有一個創建PostgreSQL觸發器,基本上重定向插入到子表中。一旦我插入記錄,我想中止請求以避免重複的數據。我所知道的唯一方法是在觸發器中返回NULL
。問題是我需要記錄被返回,所以我可以得到ID。如果我返回NULL
,我得到... NULL
。PostgreSQL觸發器不返回任何東西
任何想法如何我可以讓一個觸發器中止一個操作,同時還返回NULL
以外的東西?
我有一個創建PostgreSQL觸發器,基本上重定向插入到子表中。一旦我插入記錄,我想中止請求以避免重複的數據。我所知道的唯一方法是在觸發器中返回NULL
。問題是我需要記錄被返回,所以我可以得到ID。如果我返回NULL
,我得到... NULL
。PostgreSQL觸發器不返回任何東西
任何想法如何我可以讓一個觸發器中止一個操作,同時還返回NULL
以外的東西?
您的問題留有解釋空間。按照我的理解,您希望INSERT
命令的RETURNING
子句返回由序列生成的主鍵的值。
還有其他方法可以實現這一點。就像使用nextval()
從序列中預先獲得下一個id
並插入帶有拼寫出的id
的行。
或currval()
/lastval()
以獲得當前會話中的序列/任何序列的最近獲得的值。更多與此相關的回答:
PostgreSQL next value of the sequences?
您也可以使用RULE ... INSTEAD ..
來達到此目的。
但是,要回答你的問題 - 如果這是事實,你的問題:它可以通過使用兩個觸發器來完成。一個BEFORE
,一個AFTER INSERT
。 兩者都是按照每個定義的一次交易觸發的,因此您的第一個表中的幻像行對任何人(觸發器除外)都是不可見的。
演示:
CREATE TABLE x (
id serial PRIMARY KEY -- note the serial col.
,name text
);
CREATE TABLE y (
id integer PRIMARY KEY
,name text
);
CREATE OR REPLACE FUNCTION trg_x_insbef()
RETURNS trigger AS
$func$
BEGIN
INSERT INTO y SELECT (NEW).*; -- write to other table
RETURN NEW;
END
$func$ LANGUAGE plpgsql;
CREATE TRIGGER insbef
BEFORE INSERT ON x
FOR EACH ROW EXECUTE PROCEDURE trg_x_insbef();
CREATE OR REPLACE FUNCTION trg_x_insaft()
RETURNS trigger AS
$func$
BEGIN
DELETE FROM x WHERE id = NEW.id; -- delete row again.
RETURN NULL;
END
$func$ LANGUAGE plpgsql;
CREATE TRIGGER insaft
AFTER INSERT ON x
FOR EACH ROW EXECUTE PROCEDURE trg_x_insaft();
呼叫在PSQL:
db=# INSERT INTO x (name) values('phantom') RETURNING id;
id
----
1
(1 row)
INSERT 0 1
db=# SELECT * FROM x;
id | name
----+------
(0 rows)
db=# SELECT * FROM y;
id | name
----+---------
1 | phantom
(1 row)
謝謝!這是我想要的結果。我擔心的是性能,增加一行然後刪除它。我知道它不是什麼大熱門,只是看起來很雜亂。以其他方式做這件事是不可能的?謝謝您的幫助。 –
我確信還有其他方法,但這是你要求的。我暗示在我的答案中使用nextval()。你看到了嗎? (加上鍊接。)這就是我可以做到的。 nextval()方法的缺點是:又一次調用服務器。所以這取決於情況會更快。我的例子是一個解決方法,但應該是完全安全的使用。 –
所以你試圖建立對將數據插入Y和Z表X觸發器,防止任何被插入X,但返回一些ID? –
是的,我將數據分區爲繼承表。所以我不想在父表中有重複的行。我基本上希望這個過程是完全透明的。你處理父表,觸發器會在幕後做所有事情。從外面看沒有什麼變化。 –