当我尝试将值输入交易 table 时,此代码出现问题

I'm having an issue with this code when I try to input values into the transactions table

因此,我正在建立一个架构,在该架构中,我可以输入彼此独立但又相互依赖的日记帐分录交易(主要是为了确保借方 = 贷方)。我设置了 tables、函数和触发器。然后,当我尝试将值输入交易 table 时,出现以下错误。我正在 pgAdmin4 中完成所有这些工作。

CREATE TABLE transactions (
    transactions_id UUID PRIMARY KEY DEFAULT uuid_generate_v1(),
    entry_id INTEGER NOT NULL,
    post_date DATE NOT NULL,
    account_id INTEGER NOT NULL,
    contact_id INTEGER NULL,
    description TEXT NOT NULL,
    reference_id UUID NULL,
    document_id UUID NULL,
    amount NUMERIC(12,2) NOT NULL
);

CREATE TABLE entries (
    id UUID PRIMARY KEY,
    test_date DATE NOT NULL,
    balance NUMERIC(12,2)
    CHECK (balance = 0.00)
);

CREATE OR REPLACE FUNCTION transactions_biut()
    RETURNS TRIGGER
    LANGUAGE plpgsql
    AS $$
    BEGIN
        EXECUTE 'INSERT INTO entries (id,test_date,balance)
        SELECT
            entry_id,
            post_date,
            SUM(amount) AS ''balance''
        FROM
            transactions
        GROUP BY
            entry_id;';
    END;
    $$;

CREATE TRIGGER transactions_biut
    BEFORE INSERT OR UPDATE ON transactions
FOR EACH ROW EXECUTE PROCEDURE transactions_biut();
INSERT INTO transactions (
    entry_id,
    post_date,
    account_id,
    description,
    amount
)
VALUES
    (
        '1',
        '2019-10-01',
        '101',
        'MISC DEBIT: PAID FOR FACEBOOK ADS',
        -200.00
    ),
    (
        '1',
        '2019-10-01',
        '505',
        'MISC DEBIT: PAID FOR FACEBOOK ADS',
        200.00
    );

执行此输入后,出现以下错误:

ERROR:  column "id" of relation "entries" does not exist
LINE 1: INSERT INTO entries (id,test_date,balance)
                             ^
QUERY:  INSERT INTO entries (id,test_date,balance)
        SELECT
            entry_id,
            post_date,
            SUM(amount) AS "balance"
        FROM
            transactions
        GROUP BY
            entry_id;
CONTEXT:  PL/pgSQL function transactions_biut() line 2 at EXECUTE
SQL state: 42703

这里有几个问题:

  • 你没有从触发器函数返回任何东西 => 应该是 return NEWreturn OLD 因为你没有修改任何东西
  • 由于您在每一行之前执行触发器,因此对于任何非 0 的事务都必然会失败 => 也许您想要延迟 constraint trigger?
  • 您没有按 post_date 分组,因此您的 select 应该失败
  • 您已将 entry_id 定义为 INTEGER,但 entries.id 的类型为 UUID

另请注意,这不会真正扩展(您要汇总所有天的所有交易,所以这会变得越来越慢...)

@chirs 我能够弄清楚如何使用语句级触发器创建一个有效的解决方案:

CREATE TABLE transactions (
    transactions_id UUID PRIMARY KEY DEFAULT uuid_generate_v1(),
    entry_id INTEGER NOT NULL,
    post_date DATE NOT NULL,
    account_id INTEGER NOT NULL,
    contact_id INTEGER NULL,
    description TEXT NOT NULL,
    reference_id UUID NULL,
    document_id UUID NULL,
    amount NUMERIC(12,2) NOT NULL
);

CREATE TABLE entries (
    entry_id INTEGER PRIMARY KEY,
    post_date DATE NOT NULL,
    balance NUMERIC(12,2),
    CHECK (balance = 0.00)
);

CREATE OR REPLACE FUNCTION transactions_entries() RETURNS TRIGGER AS $$
    BEGIN
        IF (TG_OP = 'DELETE') THEN
            INSERT INTO entries
                SELECT o.entry_id, o.post_date, SUM(o.amount) FROM old_table o GROUP BY o.entry_id, o.post_date;
        ELSIF (TG_OP = 'UPDATE') THEN
            INSERT INTO entries
                SELECT o.entry_id, n.post_date, SUM(n.amount) FROM new_table n, old_table o GROUP BY o.entry_id, n.post_date;
        ELSIF (TG_OP = 'INSERT') THEN
            INSERT INTO entries
                SELECT n.entry_id,n.post_date, SUM(n.amount) FROM new_table n GROUP BY n.entry_id, n.post_date;
        END IF;

        RETURN NULL; -- result is ignored since this is an AFTER trigger
    END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER transactions_ins
    AFTER INSERT ON transactions
    REFERENCING NEW TABLE AS new_table
    FOR EACH STATEMENT EXECUTE PROCEDURE transactions_entries();
CREATE TRIGGER transactions_upd
    AFTER UPDATE ON transactions
    REFERENCING OLD TABLE AS old_table NEW TABLE AS new_table
    FOR EACH STATEMENT EXECUTE PROCEDURE transactions_entries();
CREATE TRIGGER transactions_del
    AFTER DELETE ON transactions
    REFERENCING OLD TABLE AS old_table
    FOR EACH STATEMENT EXECUTE PROCEDURE transactions_entries();

对优化有什么想法吗?