【问题标题】:How to select from variable that is a table name n Postgre >=9.2如何从表名 n Postgre >=9.2 的变量中进行选择
【发布时间】:2014-01-13 08:43:22
【问题描述】:

我有一个变量是表的名称。如何在查询中使用变量从中选择或更新,例如:

create or replace function pg_temp.testtst ()
returns varchar(255) as 
$$
declare 
r record; t_name name;
begin   
  for r in SELECT tablename FROM pg_tables WHERE schemaname = 'public' limit 100 loop
      t_name = r.tablename; 
      update  t_name set id = 10 where id = 15; 
  end loop; 
  return seq_name;
end;
$$
language plpgsql; 

它显示 错误:关系“t_name”不存在

【问题讨论】:

  • 尝试 tname 作为表名。
  • 根据我对 postgresql 的记忆,你有更好的机会让它评估动态生成的 SQL(用'update '+t_name+' set id = 10 where id = 15' 做一些事情)。查找 PREPARE 和 EXECUTE 语句。
  • 我想是 t-sql 语法

标签: postgresql select plpgsql dynamic-sql


【解决方案1】:

正确的回复是来自 Anton Kovalenko 的评论

您永远不能在嵌入式 SQL 中将变量用作表名或列名。

UPDATE dynamic_table_name SET ....

PostgreSQL 为嵌入式 SQL 使用准备和保存的计划,并且对目标对象(表)的引用在计划中被深度和硬编码 - 一些特征对计划有重大影响 - 对于一个表可以使用索引,对于其他表不是。查询计划相对较慢,因此 PostgreSQL 不会透明地尝试它(几乎没有例外)。

您应该使用动态 SQL - 一个目的是用于类似情况。你总是生成一个新的 SQL 字符串并且计划没有保存

DO $$
DECLARE r record;
BEGIN
  FOR r IN SELECT table_name 
              FROM information_schema.tables
             WHERE table_catalog = 'public'
  LOOP
    EXECUTE format('UPDATE %I SET id = 10 WHERE id = 15', r.table_name);
  END LOOP;
END $$;

注意:动态 SQL 是不安全(存在 SQL 注入风险),没有参数清理。我为它使用了一个函数“format”。另一种方法是使用“quote_ident”函数。

EXECUTE 'UPDATE ' || quote_ident(r.table_name) || 'SET ...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-06
    • 1970-01-01
    • 1970-01-01
    • 2014-05-02
    • 2012-05-15
    • 2013-01-22
    • 1970-01-01
    • 2012-06-10
    相关资源
    最近更新 更多