postgresql 使用 for 循环更改所有序列

Yav*_*lim 6 sql postgresql for-loop

对于所有表,我在 postgresql 中都有类似 table_name_sq 的序列。例如;

seqtest-> seqtest_sq
seqtest2-> seqtest2_sq
Run Code Online (Sandbox Code Playgroud)

我需要更改数据库中的所有序列。(我无法手动为每个表运行查询)

我可以获取表格并制作序列字符串

select table_name || '_sq' as sequence_name from information_schema.tables where table_catalog='test' and table_schema='public'
Run Code Online (Sandbox Code Playgroud)

我可以更改指定表的序列值

select setval('seqtest_sq',(select max(id) from seqtest)+1)
Run Code Online (Sandbox Code Playgroud)

但我不能合并这两个。我认为应该使用 for 循环,但我无法做到这一点。

代码是:

DO $$
DECLARE 
i RECORD;
BEGIN
    FOR i IN (select table_name from information_schema.tables) LOOP
         EXECUTE 'SELECT count(*) FROM ' || i;
    END LOOP;
END$$;
Run Code Online (Sandbox Code Playgroud)

输出是:

ERROR:  syntax error at or near ")"
LINE 1: SELECT count(*) FROM (seqtest)
                                     ^
QUERY:  SELECT count(*) FROM (seqtest)
CONTEXT:  PL/pgSQL function inline_code_block line 6 at EXECUTE
********** Error **********

ERROR: syntax error at or near ")"
SQL state: 42601
Context: PL/pgSQL function inline_code_block line 6 at EXECUTE
Run Code Online (Sandbox Code Playgroud)

我还用 for 循环打印了表名,但表名带有括号。

这是代码

DO $$
DECLARE 
i RECORD;
BEGIN
    FOR i IN (select table_name from information_schema.tables where table_catalog='test' and table_schema='public') LOOP
    raise notice 'Value: %',i;
    END LOOP;
END$$;
Run Code Online (Sandbox Code Playgroud)

这是输出:

NOTICE:  Value: (seqtest)
NOTICE:  Value: (seqtest2)
Run Code Online (Sandbox Code Playgroud)

我觉得去掉这个括号就够了。

你能帮我建立一个适当的循环或找到一种简单的方法来实现这一目标吗?

小智 8

我有一些没有“id”列的表,并且一些表使用驼峰命名法的特殊名称,因此需要引用它们。希望这个 javuzs 的解决方案升级能够对某人有所帮助。

DO $$
DECLARE
i TEXT;
BEGIN
  FOR i IN (SELECT tbls.table_name FROM information_schema.tables AS tbls INNER JOIN information_schema.columns AS cols ON tbls.table_name = cols.table_name WHERE tbls.table_catalog='YOUR_DATABASE_NAME' AND tbls.table_schema='public' AND cols.column_name='id') LOOP
      EXECUTE 'SELECT setval(''"' || i || '_id_seq"'', (SELECT MAX(id) FROM ' || quote_ident(i) || '));';
  END LOOP;
END $$;
Run Code Online (Sandbox Code Playgroud)


小智 7

这是我使用的脚本。

DO $$
DECLARE
i TEXT;
BEGIN
  FOR i IN (
    SELECT 'SELECT SETVAL('
        || quote_literal(quote_ident(PGT.schemaname) || '.' || quote_ident(S.relname))
        || ', COALESCE(MAX(' ||quote_ident(C.attname)|| '), 1) ) FROM '
        || quote_ident(PGT.schemaname)|| '.'||quote_ident(T.relname)|| ';'
      FROM pg_class AS S,
           pg_depend AS D,
           pg_class AS T,
           pg_attribute AS C,
           pg_tables AS PGT
     WHERE S.relkind = 'S'
       AND S.oid = D.objid
       AND D.refobjid = T.oid
       AND D.refobjid = C.attrelid
       AND D.refobjsubid = C.attnum
       AND T.relname = PGT.tablename
  ) LOOP
      EXECUTE i;
  END LOOP;
END $$;
Run Code Online (Sandbox Code Playgroud)

  • 这是最普遍的。看起来它来自 https://wiki.postgresql.org/wiki/Fixing_Sequences 所以也许值得一个归属链接? (3认同)

Yav*_*lim 5

这是@Nick Barnes 和@a_horse_with_no_name 帮助下的解决方案

如果有人需要了解如何修复序列,可以使用此脚本。

DO $$
DECLARE 
i TEXT;
BEGIN
    FOR i IN (select table_name from information_schema.tables where table_catalog='YOUR_DATABASE_NAME' and table_schema='public') LOOP
    EXECUTE 'Select setval('''||i||'_sq'', (SELECT max(id) as a FROM ' || i ||')+1);';
    END LOOP;
END$$;
Run Code Online (Sandbox Code Playgroud)