我调用命令
ALTER TABLE tableName ADD COLUMN IF NOT EXISTS columnName SERIAL
在PostgreSQL中。首次运行时,将根据需要使用相应的序列创建一个新列。但是,当再次运行时,将在数据库中创建另一个序列,即使该列已存在也是如此。有谁知道任何修复程序可以阻止这个新序列的创建?
看起来你发现了一个小错误。我可以在 Postgres 9.6 和 10 中重新创建它:
db<>小提琴在这里
事实上,它在 2017 年 9 月就已经报道过。到目前为止,修复的尝试已被拒绝,因为它会引入其他奇怪之处。
为了规避,请考虑劳伦茨回答中的建议。也许可以使用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
中得到的。
将其包装到一个 plpgsql 函数中,动态 SQL 获取参数以重复使用任意表名和列名。
相关:
- 创建 PostgreSQL 角色(用户((如果不存在(
对表名进行架构限定以避免歧义。字符串在这里不区分大小写。您不能在问题中使用 CaMeL 大小写拼写。看:
- PostgreSQL 列名是否区分大小写?
您可以使用以下步骤,这些步骤具有相同的效果:
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';
您可能希望将架构名称添加到条件中。