【问题标题】:EXECUTE of SELECT ... INTO is not implementedSELECT ... INTO 的 EXECUTE 未实现
【发布时间】:2016-01-11 10:42:35
【问题描述】:

我正在尝试在 PostrgeSQL 中运行此函数:

CREATE OR REPLACE FUNCTION create_partition_and_insert()
RETURNS trigger AS
$BODY$
DECLARE
partition VARCHAR(25);
_date text;
BEGIN
EXECUTE 'SELECT REPLACE(' || quote_literal(NEW.date) || ',''-'',''_'') into _date';
partition := TG_RELNAME || '_' || _date || ‘p’;
IF NOT EXISTS(SELECT relname FROM pg_class WHERE relname=partition) THEN
RAISE NOTICE 'A partition has been created %',partition;
EXECUTE 'CREATE TABLE ' || partition || ' (check (date = ''' || NEW.date || ''')) INHERITS (' || TG_RELNAME || ');';
END IF;
EXECUTE 'INSERT INTO ' || partition || ' SELECT(' || TG_RELNAME || ' ' || quote_literal(NEW) || ').*;';
RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql;

但是在运行时我得到这个错误:

ERROR:  EXECUTE of SELECT ... INTO is not implemented
HINT:  You might want to use EXECUTE ... INTO or EXECUTE CREATE TABLE ... AS instead.
CONTEXT:  PL/pgSQL function create_partition_and_insert() line 6 at EXECUTE statement

我不知道为什么会发生这种情况,在线提供的解决方案都没有帮助我。

【问题讨论】:

    标签: postgresql triggers plpgsql dynamic-sql partitioning


    【解决方案1】:

    代替

    execute 'select 1 into i'    -- error
    

    你应该使用

    execute 'select 1' into i
    

    【讨论】:

      【解决方案2】:

      错误消息是此函数中最少的问题。考虑完全重写。

      假设date列实际上是数据类型date

      CREATE OR REPLACE FUNCTION create_partition_and_insert()
        RETURNS trigger AS
      $func$
      DECLARE
         _partition text := quote_ident(TG_RELNAME
                                     || to_char(NEW.date,'_YYYY_MM_DD"p"'));
      BEGIN
         IF NOT EXISTS(SELECT relname FROM pg_class WHERE relname = _partition) THEN
            EXECUTE format('CREATE TABLE %s (CHECK (date = %L)) INHERITS (%I);'
                         , _partition, NEW.date, TG_RELNAME);
      
            RAISE NOTICE 'A new partition has been created: %', _partition;
         END IF;
      
         EXECUTE format('INSERT INTO %s SELECT ($1).*', _partition)
         USING NEW;
      
         RETURN NULL;
      END
      $func$  LANGUAGE plpgsql;
      

      要点

      • 您在第一条语句中根本不需要动态 SQL(源代码或您的语法错误)。实际上,您不需要整个语句或变量。我从根本上简化了名称连接。 Details for to_char() in the manual.

      • 忽略 ‘p’ 中的印刷引号 - 这些可能只是 c/p 人工制品。

      • 在 plpgsql 中分配相对昂贵。调整您的编程风格并减少变量和分配。

      • 不要将整行转换为其文本表示形式,将其连接起来然后再转换回来。这是不必要的昂贵、复杂和容易出错的。直接在USING 子句中将传递给EXECUTE,就像演示的那样。

      • 在通知完成之前不要提出通知。 RAISE 不会在异常导致潜在的误导性日志条目的情况下回滚。

      • 如果您的数据库中有多个模式(这很常见),您的代码仍然不安全。您需要为函数使用模式限定表名或SET search_path

      更详细的相关答案:

      【讨论】:

        猜你喜欢
        • 2013-09-10
        • 2016-01-11
        • 2023-03-18
        • 2014-07-26
        • 1970-01-01
        • 2019-06-26
        • 2012-01-23
        • 2014-04-23
        • 1970-01-01
        相关资源
        最近更新 更多