我试图通过将id
字段设置为主键来更新所有表。我有一个没有id
列的表,需要跳过它。这就是我到目前为止所做的,但似乎无法让查询运行:
DECLARE
rec record;
BEGIN
FOR rec IN
SELECT table_schema, table_name, column_name
FROM information_schema.columns
WHERE column_name = 'id'
if not FOUND then
raise notice'no id found'
end if; END LOOP
LOOP
EXECUTE format('ALTER TABLE %I.%I ADD PRIMARY KEY (id)',
rec.table_schema, rec.table_name, rec.column_name);
END LOOP;
END;
$$
我一直得到这个错误:
ERROR: missing "LOOP" at end of SQL expression
LINE 12: end if; END LOOP;
哪里是END LOOP
假设去,如果不是在if的情况下?这个事件是大规模更新主键的正确方式吗?此外,在if大小写中,如何使表被跳过而不是返回通知?
你有几个问题。
- 声明前缺少DO(可能是打字错误)
- 在Select后缺少分号(;)。
- If语句是不必要的,因为查询已经消除了任何表
- IF语句后的End循环无效,此时有没有循环。
- 格式化立即执行将失败。它只包含2个参数(%I),但你传递了3个值。你需要加上第三个参数,否则不传递列名。
综合考虑这些因素:
do $$
rec record;
begin
for rec in
select table_schema, table_name
from information_schema.columns
where column_name = 'id';
loop
execute format('alter table %i.%i add primary key (id)',
rec.table_schema, rec.table_name);
end loop;
end;
$$;
还有一个大问题需要你解决。如果表已经有一个主键, id或任何其他列,甚至多个列,会发生什么?
要只获取没有主键的表,请将select更改为:
select col.table_schema, col.table_name
from information_schema.columns col
where col.column_name = 'id'
and not exists ( select null
from information_schema.table_constraints con
where col.table_schema = con.table_schema
and col.table_name = con.table_name
and con.constraint_type = 'PRIMARY KEY'
) ;
这将排除定义了主键的任何表,无论它定义在满足其他要求的哪些列上。