postgres语法错误

nle07wnf  于 2021-07-24  发布在  Java
关注(0)|答案(3)|浏览(290)

给一张table

CREATE TABLE balances
(
    username   varchar(255)     NOT NULL,
    currency   varchar(255)     NOT NULL,
    balance    numeric          NULL,
    CONSTRAINT balances_pkey PRIMARY KEY (username, currency)
);

尝试之后

CREATE OR REPLACE FUNCTION merge_balance(username varchar(255), currency varchar(255), to_add numeric) RETURNS void
AS $$ BEGIN
    INSERT INTO balances(username, currency, to_add)
    ON CONFLICT balances_pkey DO UPDATE SET balance = OLD.balance + to_add
END; $$ LANGUAGE plpgsql;

我明白了

ERROR:  syntax error at or near "ON"

我的postgresql版本(在容器中运行)postgres:11.5)

SELECT version();
                                                             version
----------------------------------------------------------------------------------------------------------------------------------
 PostgreSQL 11.5 (Debian 11.5-3.pgdg90+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516, 64-bit
(1 row)

那些 ; , $ 事情太烦人了,现在我明白了=_=
有人解决过这样的问题吗?谢谢!

w7t8yxp5

w7t8yxp51#

不能在尝试时使用“old”。您所做的是引用dml语句为触发器生成的伪行old。即使可以引用,它也将为null,因为插入时所有旧列都为null。这不是你想要的结果将是空的。但是您确实需要为表设置别名,以避免update子句的歧义。此外,也不必在函数头上指定限制。尝试:

create or replace 
function merge_balance(
         p_username varchar  
       , p_currency varchar  
       , p_to_add   numeric
       )
  returns  void
  language sql
as $$
    insert into balances as bal (username, currency, balance)
    values (p_username, p_currency, p_to_add)
        on conflict (username, currency) 
        do update 
           set balance = bal.balance + excluded.balance;
$$;

请参阅此处的完整示例。
事后我想您可以使用old.balance,使用old作为表别名。

insert into balances as old (username, currency, balance) ...

但至少在我看来,这不是个好主意。,

kd3sttzy

kd3sttzy2#

考虑:

create or replace function merge_balance(
    p_username varchar(255), 
    p_currency varchar(255), 
    p_to_add numeric
) returns void
as $$
begin
    insert into balances (username, currency, balance)
    values(p_username, p_currency, p_to_add)
    on conflict (username, currency) do update set balance = old.balance + p_to_add;
end; $$ language plpgsql;

理论基础:
你需要一个 VALUES() 列出要插入的值的子句;将目标列环绕在列表中也是一种好的做法—为此,最好不要使用与表列同名的函数参数
冲突目标必须用括号括起来-可以使用约束名称,但我发现使用列名更清楚

8cdiaqws

8cdiaqws3#

不应该吗

INSERT INTO balances VALUES(username, currency, to_add)
   ON CONFLICT balances_pkey DO UPDATE SET balance = OLD.balance + to_add

相关问题