检测PostgreSQL函数(非PL/pgSQL)中的更新失败

检测PostgreSQL函数(非PL/pgSQL)中的更新失败,sql,postgresql,stored-procedures,Sql,Postgresql,Stored Procedures,为了模拟MySQL REPLACE语句(aka UPSERT),我需要尝试更新一条记录,如果更新失败,则插入它。但是,如何在我的SQL过程中检测更新失败 begin transaction; create table pref_users ( id varchar(32) primary key, first_name varchar(32), last_name varchar(32), female boolean, a

为了模拟MySQL REPLACE语句(aka UPSERT),我需要尝试更新一条记录,如果更新失败,则插入它。但是,如何在我的SQL过程中检测更新失败

begin transaction;

create table pref_users (
       id varchar(32) primary key,
       first_name varchar(32),
       last_name varchar(32),
       female boolean,
       avatar varchar(128),
       city varchar(32),
       lat real check (-90 <= lat and lat <= 90),
       lng real check (-90 <= lng and lng <= 90),
       last_login timestamp default current_timestamp,
       last_ip inet,
       medals smallint check (medals > 0)
);
create table pref_rate (
       obj varchar(32) references pref_users(id),
       subj varchar(32) references pref_users(id),
       good boolean,
       fair boolean,
       nice boolean,
       about varchar(256),
       last_rated timestamp default current_timestamp
);

create table pref_money (
       id varchar(32) references pref_users,
       yw char(7) default to_char(current_timestamp, 'YYYY-WW'),
       money real
);
create index pref_money_yw_index on pref_money(yw);

create or replace function update_pref_users(id varchar,
       first_name varchar, last_name varchar, female boolean,
       avatar varchar, city varchar, last_ip inet) returns void as $$

       update pref_users set
            first_name = $2,
            last_name = $3,
            female = $4,
            avatar = $5,
            city = $6,
            last_ip = $7
        where id = $1;

        -- XXX how to detect failure here? XXX

       insert into pref_users(id, first_name, last_name,
            female, avatar, city, last_ip)
            values ($1, $2, $3, $4, $5, $6, $7);
$$ language sql;

commit;
开始交易;
创建表pref_用户(
id varchar(32)主键,
名字varchar(32),
姓氏varchar(32),
女布尔,
阿凡达·瓦尔查尔(128),
城市瓦查尔(32),
横向真实检查(-90<代码>如果存在()
更新。。。
其他的
插入。。。

您不能将SQL用作一种语言,您需要pl/pgsql,因为SQL中缺少if-else构造

在pl/pgsql中,您可以使用特殊变量查看查询是否找到了某些内容

UPDATE ...;
IF NOT FOUND THEN -- UPDATE didn't touch anything
  INSERT ...;
END IF;

不需要额外的SELECT语句。

谢谢,但这不是plpgsql吗?我正在尝试寻找一个SQL解决方案。您的建议是原子性的还是中间有插入时会失败?不需要SELECT查询,只需使用FOUND查看更新是否涉及任何内容。谢谢您的回答。我想知道它是否是“原子性的”,也就是说,它不能发生,发现不是真的,但另一个会话调用了中间插入?我不确定我是否正确理解。Plpgsql函数本质上是原子函数。如果某个东西失败,它将回滚。
UPDATE ...;
IF NOT FOUND THEN -- UPDATE didn't touch anything
  INSERT ...;
END IF;