sql - 唯一性由两列的组合确定时的 UPDATE OR INSERT 函数

标签 sql postgresql stored-procedures

扩展通常的 INSERT OR UPDATE conondrum

我有一个服务于正常 UPDATE 或 INSERT 的函数,它看起来像这样:

CREATE OR REPLACE FUNCTION updateslave ( varchar(7), smallint ) RETURNS void AS
$$
 BEGIN
   LOOP
     UPDATE consist SET
       master = $1,
       time = now() WHERE slave = $2;
     IF found THEN
       RETURN;
     END IF;
     BEGIN
       INSERT INTO consist(master, slave, time) VALUES ( $1, $2, now() );
       RETURN;
     EXCEPTION WHEN unique_violation THEN
       -- do nothing, then loop and retry
     END;
   END LOOP;
 END;
##
LANGUAGE plpgsql;

现在,问题是我正在尝试重写它以在不同的表中执行类似的操作。但是,不同之处在于,在另一个表中没有单独的唯一列,而是两列的组合只存在于一行中。是否可以改为基于两列的组合来声明 unique_violation?

为了保持示例简单,我们假设该表看起来与我使用上述函数的表完全相同,但主从是共同产生唯一性的两列:

 Column |            Type             |                  Modifiers                   | Storage  | Description
--------+-----------------------------+----------------------------------------------+----------+-------------
 master | character varying(7)        | not null default 'unused'::character varying | extended |
 slave  | smallint                    | not null                                     | plain    |
 time   | timestamp without time zone | default now()                                | plain    |

最佳答案

最好的方法是在表上定义一个唯一约束,这样无论更新如何发生,即无论是否使用您的过程,一切都可以。

最简单的方法是在两列上创建唯一索引:

create unique index any_mame on mytable(col1, col2);

您也可以更改表以添加唯一约束,但差别不大。

关于sql - 唯一性由两列的组合确定时的 UPDATE OR INSERT 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13614407/

相关文章:

sql - CTE和TEMP表之间的主要区别是什么?

php - 在mysql查询中设置多个order by

ruby-on-rails - PostgreSQL "could not identify an equality operator for type json"的 Heroku 错误

sql - 有没有办法将 DBCC CheckIdent 的值存储到变量中?

mysql - 如何合并两个查询?

SQL查询将面积转换为通用基本单位(公顷),然后获取其总和

postgresql - 更改函数以进行额外的争论/添加参数

postgresql - 在 PostgreSQL 9.1 中使用不带时区的时间戳时,如何将 24 小时时间表示为 12 小时时间?

MySQL - 从一个过程中调用多个过程

过程参数的 MySql 语法错误