plpgsql 函数中 IF EXISTS 内的标识符变量

问题描述 投票:0回答:2
CREATE OR REPLACE FUNCTION drop_now()
  RETURNS void AS
$BODY$
DECLARE
    row     record;
BEGIN
    RAISE INFO 'in';
    FOR row IN 
        select relname from pg_stat_user_tables
        WHERE schemaname='public' AND relname LIKE '%test%'
    LOOP    
    IF EXISTS(SELECT row.relname.tm FROM row.relname
              WHERE row.relname.tm < current_timestamp - INTERVAL '90 minutes'
              LIMIT 1)              
    THEN
    -- EXECUTE 'DROP TABLE ' || quote_ident(row.relname);
    RAISE INFO 'Dropped table: %', quote_ident(row.relname);

    END IF;

    END LOOP;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE;

你能告诉我如何在

SELECT
里面使用变量吗?目前,
IF EXISTS
row.relname.tm
按字面意思处理,这不是我想要的。
    

postgresql postgresql-9.1 plpgsql dynamic-sql exists
2个回答
1
投票
CREATE OR REPLACE FUNCTION drop_now()
  RETURNS void
 LANGUAGE plpgsql AS
$func$
DECLARE
   _tbl   regclass;
   _found int;
BEGIN
   FOR _tbl IN 
      SELECT relid
      FROM   pg_stat_user_tables
      WHERE  schemaname = 'public'
      AND    relname LIKE '%test%'
   LOOP
      EXECUTE format($f$SELECT 1 FROM %s WHERE tm < now() - interval '90 min'$f$, _tbl);
      GET DIAGNOSTICS _found = ROW_COUNT;
      IF _found > 0 THEN
         -- EXECUTE 'DROP TABLE ' || _tbl;
         RAISE NOTICE 'Dropped table: %', _tbl;
      END IF;
   END LOOP;
END
$func$;

是标准 SQL 中的

保留字
。 Postgres 中允许使用它,但仍然不明智。我喜欢在 PL/pgsql 变量前面加上下划线 row 以避免命名冲突。
无论如何,您都不会选择整个

,仅选择本示例中的表名称。最好使用 _ 类型的变量,从而避免隐式通过非法表名进行 SQL 注入。参见:


    表名作为 PostgreSQL 函数参数
regclass

表达式中不需要

LIMIT
,该表达式仅检查
any
行是否存在。另外,您可以将 EXISTS 列表留空。参见:

    EXISTS 子查询中什么更容易阅读?
  • 您需要
动态 SQL

来进行带有变量标识符的查询。普通 SQL 不允许这样做。即:构建一个查询字符串并 SELECT 它。参见:


    动态SQL(EXECUTE)作为IF语句的条件
  • 如果您想运行
EXECUTE

语句,情况也是如此。我添加了评论。

    


0
投票
的 plpgsql 部分中有关执行动态命令的部分。

© www.soinside.com 2019 - 2024. All rights reserved.