在 Postgres 中意外创建重复的唯一约束
Unexpected creation of duplicate unique constraints in Postgres
我正在为 Postgres 12 数据库编写幂等模式更改脚本。但是我注意到,如果我在 ADD COLUMN 语句中包含 IF NOT EXISTS,那么即使该列已经存在,它也会为已经存在的唯一性约束添加重复索引。简单示例:
-- set up base table
CREATE TABLE IF NOT EXISTS test_table
(id SERIAL PRIMARY KEY
);
-- statement intended to be idempotent
ALTER TABLE test_table
ADD COLUMN IF NOT EXISTS name varchar(50) UNIQUE;
运行 此脚本每次 运行 时都会创建一个新索引 test_table_name_key[n]
。我在 Postgres 文档中找不到任何内容,也不明白为什么允许这种情况发生?如果我把它分成两部分,例如:
ALTER TABLE test_table
ADD COLUMN IF NOT EXISTS name varchar(50);
ALTER TABLE
ADD CONSTRAINT test_table_name_key UNIQUE (name);
然后事务失败,因为 Postgres 拒绝创建一个已经存在的约束(然后我可以在 DO EXCEPTION 块中捕获)。据我所知,这是因为通过这种方法我不得不为约束命名。这与 ALTER COLUMN SET NOT NULL 对比,据我所知,它可以 运行 多次而没有错误或副作用。
问题:为什么要添加重复的唯一约束,在table列上有多个相同的索引有什么问题吗? (我认为这是一个微妙的 'error' 并且只是偶然发现它所以我担心它可能会出现在生产环境中)
您可以在同一列上创建多个唯一约束,只要它们具有不同的名称即可,因为 PostgreSQL 代码中没有任何内容禁止这样做。每个唯一约束都会创建一个同名的唯一索引,因为唯一约束就是这样实现的。
这可能是一个有效的用例:例如,如果索引膨胀,您可以创建一个新约束,然后删除旧约束。
但通常情况下,它是无用且有害的,因为每个索引都会使 table 上的数据修改变慢。
我正在为 Postgres 12 数据库编写幂等模式更改脚本。但是我注意到,如果我在 ADD COLUMN 语句中包含 IF NOT EXISTS,那么即使该列已经存在,它也会为已经存在的唯一性约束添加重复索引。简单示例:
-- set up base table
CREATE TABLE IF NOT EXISTS test_table
(id SERIAL PRIMARY KEY
);
-- statement intended to be idempotent
ALTER TABLE test_table
ADD COLUMN IF NOT EXISTS name varchar(50) UNIQUE;
运行 此脚本每次 运行 时都会创建一个新索引 test_table_name_key[n]
。我在 Postgres 文档中找不到任何内容,也不明白为什么允许这种情况发生?如果我把它分成两部分,例如:
ALTER TABLE test_table
ADD COLUMN IF NOT EXISTS name varchar(50);
ALTER TABLE
ADD CONSTRAINT test_table_name_key UNIQUE (name);
然后事务失败,因为 Postgres 拒绝创建一个已经存在的约束(然后我可以在 DO EXCEPTION 块中捕获)。据我所知,这是因为通过这种方法我不得不为约束命名。这与 ALTER COLUMN SET NOT NULL 对比,据我所知,它可以 运行 多次而没有错误或副作用。
问题:为什么要添加重复的唯一约束,在table列上有多个相同的索引有什么问题吗? (我认为这是一个微妙的 'error' 并且只是偶然发现它所以我担心它可能会出现在生产环境中)
您可以在同一列上创建多个唯一约束,只要它们具有不同的名称即可,因为 PostgreSQL 代码中没有任何内容禁止这样做。每个唯一约束都会创建一个同名的唯一索引,因为唯一约束就是这样实现的。
这可能是一个有效的用例:例如,如果索引膨胀,您可以创建一个新约束,然后删除旧约束。
但通常情况下,它是无用且有害的,因为每个索引都会使 table 上的数据修改变慢。