Postgresql ADD SERIAL COLUMN IF NOT EXISTS 仍在创建序列

Posted

技术标签:

【中文标题】Postgresql ADD SERIAL COLUMN IF NOT EXISTS 仍在创建序列【英文标题】:Postgresql ADD SERIAL COLUMN IF NOT EXISTS still creating sequences 【发布时间】:2018-11-06 06:59:14 【问题描述】:

我调用命令

ALTER TABLE tableName ADD COLUMN IF NOT EXISTS columnName SERIAL

在 postgresql 中。第一次运行时,会根据需要创建一个具有相应序列的新列。但是,当再次运行时,会在数据库中创建另一个序列,即使该列已经存在。有谁知道阻止这个新序列创建的任何修复?

【问题讨论】:

在执行alter table 之前检查列是否存在。据推测,序列是在检查表是否存在列之前创建的。 戈登是对的。见"8.1.4. Serial Types"。 【参考方案1】:

您可以使用以下步骤,效果相同:

ALTER TABLE tablename ADD COLUMN IF NOT EXISTS columnname integer;

现在,如果未创建列并且您收到通知,那么您就完成了。否则继续:

CREATE SEQUENCE IF NOT EXISTS tablename_columnname_seq
   OWNED BY tablename.columnname;
ALTER TABLE tablename ALTER COLUMN columnname
   SET DEFAULT nextval('tablename_columnname_seq');

或者,您可以在创建列之前检查列是否存在:

SELECT count(*) FROM information_schema.columns
   WHERE table_name = 'tablename' AND column_name = 'columnname';

您可能希望将架构名称添加到条件中。

【讨论】:

【参考方案2】:

您似乎发现了一个小错误。我可以在 Postgres 9.6 和 10 中重新创建它:

db小提琴here

事实上,it has been reported in Sept 2017。到目前为止,修复的尝试已被拒绝,因为它会引入其他奇怪的东西。

规避,请考虑 Laurenz 回答中的建议。也许可以使用 DO 命令自动化,例如:

DO
$do$
BEGIN
IF NOT EXISTS (SELECT FROM pg_attribute
               WHERE  attrelid = 'public.tblname'::regclass  -- table name here 
               AND    attname = 'colname'                    -- column name here
               AND    NOT attisdropped
              ) THEN
   ALTER TABLE public.tblname ADD COLUMN IF NOT EXISTS colname serial;
ELSE
   RAISE NOTICE 'column "colname" of relation "public.tblname" already exists, skipping';
END IF;
END
$do$;

如果多个事务可以同时更改同一个表结构,则检查和创建之间的竞争条件是可能的

生成的通知与IF NOT EXISTS 完全相同。

使用动态 SQL 将其包装到一个 plpgsql 函数中,该函数采用参数以与任意表和列名重复使用。

相关:

Create PostgreSQL ROLE (user) if it doesn't exist

模式限定表名以避免歧义。字符串在这里不区分大小写。您不能在问题中使用 CaMeL-case 拼写。见:

Are PostgreSQL column names case-sensitive?

【讨论】:

以上是关于Postgresql ADD SERIAL COLUMN IF NOT EXISTS 仍在创建序列的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL 中的从属 SERIAL 列

为啥这个查询这么慢? - PostgreSQL - 从 SERIAL、TIMESTAMP 和 NUMERIC(6,2) 中选择

Postgresql SERIAL 的工作方式是不是不同?

带有准备好的语句的 PostgreSQL 内部查询

如何使用 PostgreSQL 在 DBeaver 中创建自动递增/SERIAL id 列?

PostgreSQL数据库 实现ID自增