Bru*_*oLM 5 postgresql dynamic-sql plpgsql update
我有几个结构完全相同的表,我需要更新所有表中的值。
为此,我尝试构建以下脚本:
DO
$do$
DECLARE
i pg_tables%rowtype;
BEGIN
FOR i IN SELECT * FROM pg_catalog.pg_tables where schemaname like 'public' and tablename like '%_knex_migrations'
LOOP
UPDATE i.tablename SET name = replace(name, '.js', '.ts');
END LOOP;
END
$do$;
Run Code Online (Sandbox Code Playgroud)
我可以看到它i.tablename
具有正确的值(我插入到 tmp 表中进行检查),但更新失败。
name: error
length: 223
severity: ERROR
code: 42P01
internalPosition: 8
internalQuery: UPDATE i."tablename" SET name = replace(name, '.js', '.ts')
where: PL/pgSQL function inline_code_block line 7 at SQL statement
file: parse_relation.c
line: 965
routine: parserOpenTable
Run Code Online (Sandbox Code Playgroud)
只是声明i.tablename
上的插件UPDATE
不起作用。
有没有办法让它工作?还是一次更新所有表的更简单方法?
你实际上很接近..首先创建一些测试数据..
CREATE TABLE foo_knex_migrations ( name )
AS VALUES ('test.js'),('test2.js'),('bicycles');
CREATE TABLE bar_knex_migrations AS TABLE foo_knex_migrations;
CREATE TABLE baz_knex_migrations AS TABLE foo_knex_migrations;
Run Code Online (Sandbox Code Playgroud)
接下来,我们将使用EXECUTE...
FORMAT()
, 和%I
。
DO
$do$
DECLARE
i pg_tables%rowtype;
BEGIN
FOR i IN SELECT * FROM pg_catalog.pg_tables where schemaname like 'public' and tablename like '%_knex_migrations'
LOOP
EXECUTE FORMAT(
$$
UPDATE %I
SET name = replace(name, '.js', '.ts');
$$,
i.tablename
);
END LOOP;
END
$do$;
TABLE baz_knex_migrations ;
name
----------
test.ts
test2.ts
bicycles
(3 rows)
test=# TABLE foo_knex_migrations ;
name
----------
test.ts
test2.ts
bicycles
(3 rows)
Run Code Online (Sandbox Code Playgroud)
作为旁注,
information_schema
which 是针对此类简单事物标准化的,而速度无关紧要。UPDATE
通过添加WHERE
子句来检查是否需要运行。否则,您将毫无意义地重写表格。knex_migrations
有多个表,请考虑CREATE SCHEMA knex_migrations
存储它们,而不是根据所有表的命名约定来遍历目录。