在PostgreSQL中为带有前缀的表创建索引

在PostgreSQL中为带有前缀的表创建索引,postgresql,plpgsql,dynamic-sql,ddl,Postgresql,Plpgsql,Dynamic Sql,Ddl,我试图实现一种在Postgresql中为多个表创建多个索引的方法 现在,我写了这样的东西 do $$ declare temprow record; declare idx_name character varying(200); begin for temprow in select table_name from information_schema.tables where table_schema = 'public' and table_name like 'prefix

我试图实现一种在Postgresql中为多个表创建多个索引的方法

现在,我写了这样的东西

do $$

declare temprow record;
declare idx_name character varying(200);

begin

for temprow in
    select table_name from information_schema.tables where table_schema = 'public' and table_name like 'prefix%' order by table_name
loop
    idx_name := 'index_name_prefix_' || temprow.table_name || '_idx';
    create index idx_name ON temprow.table_name (column1 asc, column2 desc);
end loop;

end$$;
看起来这应该行得通,但没有错误

ERROR:  schema "temprow" does not exist
我想我应该每周安排一次这个sql,因为这是完成任务的合适方式


您能帮我找到此SQL中的错误,或者建议一种更好的方法为多个表创建索引吗?

如果您在temprow上有
创建索引idx\u name。table\u name
,则table name必须是一个实表,而不是包含表名的字符串的变量,或者动态/间接引用表名的任何其他间接方式

  • 其中有
    temprow.table\u name
    语法要求
    schema.table
  • 因此,您告诉PostgreSQL在模式
    temprow
    中的表
    table\u name
    上创建索引
您需要的是动态SQL;这是将SQL作为字符串写入,然后分别执行该字符串的代码

DO $do$

DECLARE 
  temprow  RECORD;
  sql_stmt CHARACTER VARYING(1024);
BEGIN

  FOR temprow IN
    SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' AND table_name like 'prefix%' ORDER BY table_name
  LOOP
    sql_stmt := FORMAT(
                  'create index index_name_prefix_%s_idx ON %s (column1 asc, column2 desc);',
                  temprow.table_name,
                  temprow.table_name
                );

    EXECUTE(sql_stmt);

  END LOOP;

END $do$;
工作示例:


不过,一定要小心使用此模式。

  • 它开始让您面临SQL注入攻击

看看如果有人滥用引用的表名来攻击你会发生什么

  • CREATE TABLE“测试时的前缀(id)”;drop TABLE prefix_test;——“(id INT)

如果您有
在temprow.table\u name上创建索引idx\u name
,则表名必须是实表,而不是包含表名字符串的变量,或任何其他动态/间接引用表名的间接方式

  • 其中有
    temprow.table\u name
    语法要求
    schema.table
  • 因此,您告诉PostgreSQL在模式
    temprow
    中的表
    table\u name
    上创建索引
您需要的是动态SQL;这是将SQL作为字符串写入,然后分别执行该字符串的代码

DO $do$

DECLARE 
  temprow  RECORD;
  sql_stmt CHARACTER VARYING(1024);
BEGIN

  FOR temprow IN
    SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' AND table_name like 'prefix%' ORDER BY table_name
  LOOP
    sql_stmt := FORMAT(
                  'create index index_name_prefix_%s_idx ON %s (column1 asc, column2 desc);',
                  temprow.table_name,
                  temprow.table_name
                );

    EXECUTE(sql_stmt);

  END LOOP;

END $do$;
工作示例:


不过,一定要小心使用此模式。

  • 它开始让您面临SQL注入攻击

看看如果有人滥用引用的表名来攻击你会发生什么

  • CREATE TABLE“测试时的前缀(id)”;drop TABLE prefix_test;——“(id INT)

如果在
format()
中使用
%I
而不是
%s
,则这不再适用于SQL注入:如果在
format()
中使用
%I
而不是
%s
则这不再适用于SQL注入: