我知道這可能聽起來很奇怪,但有什麼辦法可以在表中的ROLLBACK事件上調用我的觸發器嗎?我正在通過postgresql觸發器文檔,只有CREATE,UPDATE,DELETE和INSERT表上的事件。postgresql中的ROLLBACK事件觸發器
我的要求是在事務ROLLBACK我的觸發器將從表中選擇last_id並重置表序列值= last_id + 1;總之我想在回滾時保留序列值。
任何類型的想法和反饋將受到讚賞的傢伙!
我知道這可能聽起來很奇怪,但有什麼辦法可以在表中的ROLLBACK事件上調用我的觸發器嗎?我正在通過postgresql觸發器文檔,只有CREATE,UPDATE,DELETE和INSERT表上的事件。postgresql中的ROLLBACK事件觸發器
我的要求是在事務ROLLBACK我的觸發器將從表中選擇last_id並重置表序列值= last_id + 1;總之我想在回滾時保留序列值。
任何類型的想法和反饋將受到讚賞的傢伙!
您無法爲此使用序列。您需要一個序列化點,全部插入必須去 - 否則「無縫」屬性不能保證。您還需要確保從該表中不會刪除任何行。
序列化還意味着只有一個事務可以將行插入到該表中 - 所有其他插入必須等到「先前」插入已被提交或回滾。
一個模式是如何實現的,就是擁有一個存儲「序列」數字的表格。讓我們假設我們需要這樣的發票號碼,由於法律原因,發票號碼必須是無間隙的。
因此,我們首先要創建表來保存「當前值」:
create table slow_sequence
(
seq_name varchar(100) not null primary key,
current_value integer not null default 0
);
-- create a "sequence" for invoices
insert into slow_sequence values ('invoice');
現在我們需要的是會產生下一個號碼的功能,但它保證沒有兩筆交易可以在獲得下一個數同時。
create or replace function next_number(p_seq_name text)
returns integer
as
$$
update slow_sequence
set current_value = current_value + 1
where seq_name = p_seq_name
returning current_value;
$$
language sql;
該函數將遞增計數器並返回遞增的值作爲結果。由於update
該序列的行現在被鎖定,並且沒有其他事務可以更新該值。如果調用事務回滾,那麼更新序列計數器。如果它被提交,則新值將被保留。
爲確保每事務使用該函數,應該創建一個觸發器。
創建問題的表:
create table invoice
(
invoice_number integer not null primary key,
customer_id integer not null,
due_date date not null
);
現在創建的觸發功能和觸發:現在
create or replace function f_invoice_trigger()
returns trigger
as
$$
begin
-- the number is assigned unconditionally so that this can't
-- be prevented by supplying a specific number
new.invoice_number := next_number('invoice');
return new;
end;
$$
language plpgsql;
create trigger invoice_trigger
before insert on invoice
for each row
execute procedure f_invoice_trigger();
如果一個交易做到這一點:
insert into invoice (customer_id, due_date)
values (42, date '2015-12-01');
的新號碼生成。 A 秒事務需要等到第一個插入提交或回滾。
正如我所說:這種解決方案是不可擴展的。一點也不。如果有大量的插入到表中,它會大量減慢你的應用程序。但是,您不能同時擁有:可擴展的和正確實現無間隙序列。
我也很確定有邊緣的情況下沒有被上面的代碼覆蓋。所以很可能你仍然可以縮小差距。
是的,我同意,我可能有多個插入,這是不可擴展的。有沒有什麼辦法可以在交易中獲得當前表名? 'pg_locks'具有名爲關係的列,但它提供了OID。我如何檢索交易中的當前表名? – Vish021
您可以從OID中強制轉換名稱,或者只是在pg_class中查找它。提示:您還希望爲模式名稱加入pg_namespace。 –
@ Vish021:無縫數字的*正確*解決方案**從不**可伸縮。它不能是 –
「*簡而言之,我想在回滾時保留序列值*」 - 爲什麼?這聽起來像是時間和資源的完全浪費。如果你真的**需要無間斷序列,這絕對不是一個解決方案。如果你真的需要無間斷的序列(例如出於合法的原因),而不是'序列'就不是**的正確工具。 –
我真的需要無縫序列 – Vish021
@a_horse_with_no_name或者有沒有什麼辦法在事務中獲取當前表名? – Vish021