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、TIMESTAMP 和 NUMERIC(6,2) 中选择