在循环中使用 replace()

Using replace() inside a loop

我正在尝试将索引从物化视图复制到表中。这是我正在尝试使用的脚本:

DO $$ 

declare indexdefname record; 
a text;
b text;
c text;

begin for indexdefname in

select indexdef
from pg_indexes i
join pg_class c
    on schemaname = relnamespace::regnamespace::text 
    and tablename = relname
where relkind = 'm'

loop

a:= FORMAT ('do $check$ begin replace(%s, public., 
myschema. ); end $check$', indexdef.indexdefname);

execute a;

end loop;

end $$;

这是我遇到的错误:

missing FROM-clause entry for table "indexdef".

所有,我正在尝试做的是替换

CREATE INDEX test_index
ON public.test
( name )

CREATE INDEX test_index
ON myschema.test
( name )

您报告错误的直接原因是切换器:
你有 indexdef.indexdefname 应该是 indexdefname.indexdef.

但还有更多。不要仅为替换构建动态嵌套 DO 语句。这是一个简单的函数调用,可以立即嵌套在初始 SELECT 中。此外,还有多个语法错误:缺少引号、未赋值的函数调用以及 DDL 语句从未执行。只需执行 CREATE INDEX 命令。喜欢:

DO
$do$ 
DECLARE
   _ddl text;
BEGIN
   SELECT INTO _ddl
          string_agg(replace(i.indexdef, 'ON public.', 'ON myschema.'), E';\n')
   FROM   pg_indexes i
   JOIN   pg_class c ON c.relnamespace::regnamespace::text = i.schemaname
                    AND c.relname = i.tablename
   WHERE  c.relkind = 'm';

   IF _ddl IS NULL THEN
      RAISE EXCEPTION 'No indexes found!';
   ELSE
      EXECUTE _ddl;
   END IF;
END
$do$;

小心! 这使用 all 索引 all 物化视图。替换 - 虽然看起来合理 - 可能会在极端情况下出错。您可能想要更有选择性,或者采用更安全、非动态的两步法:

1.生成DDL字符串

SELECT string_agg(replace(i.indexdef, 'ON public.', 'ON myschema.'), E';\n')
FROM   pg_indexes i
JOIN   pg_class c ON c.relnamespace::regnamespace::text = i.schemaname
                 AND c.relname = i.tablename
WHERE  c.relkind = 'm';  -- more predicates?

2. 执行字符串 after 检查它是否符合您的要求。