【问题标题】:How can I do the equivalent of ADD CONSTRAINT IF NOT EXISTS in cockroachdb/postgresql?如果在 cockroachdb/postgresql 中不存在,我该如何做相当于 ADD CONSTRAINT 的操作?
【发布时间】:2022-10-14 02:07:14
【问题描述】:

大多数 PostgreSQL 语句都支持 IF NOT EXISTS 子句以允许幂等迁移,例如CREATE TABLE IF NOT EXISTS foo ...。但是ALTER TABLE ... ADD CONSTRAINT 没有。我如何编写一个 SQL 语句,如果它不存在则添加一个约束,否则什么都不做也不出错?

【问题讨论】:

    标签: postgresql cockroachdb


    【解决方案1】:

    这是 PostgreSQL 语法中一种令人讨厌的差距。以下是一些解决方法:

    对于独特的约束

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

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

    使用 PLSQL

    来自here

    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 的简单方法,适用于任何类型的约束,但在生产环境中使用实时表并不安全,而且如果表很大,成本可能会很高。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-02-22
      • 2021-07-13
      • 2020-08-06
      • 1970-01-01
      • 2010-09-29
      • 1970-01-01
      • 2013-11-29
      • 2012-01-21
      相关资源
      最近更新 更多