如何在 cockroachdb/postgresql 中执行相当于 ADD CONSTRAINT IF NOT EXISTS 的操作?

问题描述 投票:0回答:2

大多数 PostgreSQL 语句支持 IF NOT EXISTS 子句以允许幂等迁移,例如

CREATE TABLE IF NOT EXISTS foo ...
。但
ALTER TABLE ... ADD CONSTRAINT
没有。我怎样才能编写一条 SQL 语句来添加约束(如果约束尚不存在),否则不执行任何操作且不会出错?

postgresql cockroachdb
2个回答
2
投票

这是 PostgreSQL 语法中一种恼人的缺陷。以下是一些解决方法:

对于独特的约束

CREATE UNIQUE INDEX IF NOT EXISTS indexname ON tablename(columns)

这相当于添加了唯一约束,因为唯一约束是通过添加索引来实现的。

使用PLSQL

这里

CREATE OR REPLACE FUNCTION create_constraint_if_not_exists (t_name text, c_name text, constraint_sql text)
  RETURNS void
AS
$BODY$
  BEGIN
    -- Look for our constraint
    IF NOT EXISTS (SELECT constraint_name
                   FROM information_schema.constraint_column_usage
                   WHERE constraint_name = c_name) THEN
        EXECUTE 'ALTER TABLE ' || t_name || ' ADD CONSTRAINT ' || c_name || ' ' || constraint_sql;
    END IF;
  END;
$BODY$
LANGUAGE plpgsql VOLATILE;

SELECT create_constraint_if_not_exists('pokemon', 'league_max', 'CHECK (cp < 1500);');

这适用于 Postgres。 CockroachDB 尚不支持 PL/pgSQL(截至 2022 年 10 月),但很快就会支持。

代码中

if sqlconn.Query("SELECT 1
                   FROM information_schema.constraint_column_usage
                   WHERE constraint_name = league_max").empty?
  sqlConn.Exec("ALTER TABLE pokemon ADD CONSTRAINT league_max ...")

如果表当前未接收写入

ALTER TABLE pokemon DROP CONSTRAINT IF EXISTS league_max;
ALTER TABLE pokemon ADD CONSTRAINT league_max ...

这是一种简单的方法,适用于 CockroachDB 和 Postgres,适用于任何类型的约束,但在生产中的实时表上使用并不安全,而且如果表很大,成本可能会很高。


0
投票

在 PostgreSQL 中:

ALTER TABLE pokemon 
  DROP CONSTRAINT IF EXISTS league_max,
  ADD CONSTRAINT league_max ...
© www.soinside.com 2019 - 2024. All rights reserved.