Postgresql 自引用表上的触发器

Postgresql 自引用表上的触发器,postgresql,postgresql-11,Postgresql,Postgresql 11,我有这样一个发票表: CREATE TABLE invoices ( idinvoice SERIAL PRIMARY KEY ,idclient INTEGER REFERENCES clients(idclient) -- other fields here ); WITH pre AS ( SELECT idinvoiceitem,10*ROW_NUMBER() OVER (ORDER BY sortorder,idinvoiceitem) AS rown

我有这样一个发票表:

CREATE TABLE invoices (
    idinvoice SERIAL PRIMARY KEY
    ,idclient INTEGER REFERENCES clients(idclient)
    -- other fields here
);
WITH pre AS (
    SELECT idinvoiceitem,10*ROW_NUMBER() OVER (ORDER BY sortorder,idinvoiceitem) AS rownum
    FROM invoiceitems
    WHERE idinvoice=xx
    ORDER BY sortorder,idinvoiceitem
)
UPDATE invoiceitems di
SET sortorder=rownum
FROM pre p
WHERE p.idinvoiceitem=di.idinvoiceitem;
和invoiceitems表:

我的问题是sortorder字段:每次插入或更新invoiceitem时,我都希望使用如下查询重新计算同一发票的所有项目的排序:

CREATE TABLE invoices (
    idinvoice SERIAL PRIMARY KEY
    ,idclient INTEGER REFERENCES clients(idclient)
    -- other fields here
);
WITH pre AS (
    SELECT idinvoiceitem,10*ROW_NUMBER() OVER (ORDER BY sortorder,idinvoiceitem) AS rownum
    FROM invoiceitems
    WHERE idinvoice=xx
    ORDER BY sortorder,idinvoiceitem
)
UPDATE invoiceitems di
SET sortorder=rownum
FROM pre p
WHERE p.idinvoiceitem=di.idinvoiceitem;
这样,每次添加一个新项目时,它将被编号为10+最后一个项目,如果我决定通过手动设置值来更改项目的排序顺序,则所有排序器将以10的增量重新计算:

id | sortorder
---+----------
 1 | 10
 2 | 20
 3 | 30
 4 | 40  ← I change this to 25
然后在查询之后,我将得到:

id | sortorder
---+----------
 1 | 10
 2 | 20
 4 | 30
 3 | 40
我想把这个放在触发器里。问题是第4项将被触发器更新,因此再次调用触发器,我将得到某种无休止的递归

有办法做到这一点吗?例如,设置一些信号量,以防止在触发器本身内发生更新时调用触发器?或者是一个明确的锁


使用PostgreSQL 11+

可以做的一件事是使用pg_trigger_depth函数,这是有文档记录的

那么您的触发器应该与此类似:

CREATE TRIGGER trigger_name
AFTER UPDATE OR INSERT ON invoiceitem
FOR EACH ROW
WHEN (pg_trigger_depth() = 0)
EXECUTE PROCEDURE your_procedure();

我建议阅读一些关于这种方法的讨论,但一般来说,对于不复杂的系统,这应该是好的。

解决方案可能是不坚持排序顺序…@LaurenzAlbe你是什么意思?用户希望强制执行某种排序顺序,因此我提出了要求。按插入时间戳排序并不总是有效。你有什么建议?我建议在你从表中选择的时候动态生成排序器。我的意思是。我明白了。这是我的第一个想法,但它不是非常友好的用户0.125的一半是什么?有些人很难弄清楚,或者会犯错误。我可以在界面上解决这个问题,但我喜欢这种简单化的方法。谢谢你的指点。