【问题标题】:Format specifier for integer variables in format() for EXECUTE?执行格式()中整数变量的格式说明符?
【发布时间】:2014-05-04 14:27:39
【问题描述】:
CREATE OR REPLACE FUNCTION getParentLtree(parent_id bigint, tbl_name varchar) 
  RETURNS ltree AS
$BODY$
DECLARE
   parent_ltree ltree;
BEGIN
-- This works fine:
-- select into parent_ltree l_tree from tbl1 where id = parent_id;

EXECUTE format('select into parent_ltree l_tree from %I
                where id = %I', tbl_name,parent_id);

RETURN parent_ltree;
END;
$BODY$ LANGUAGE plpgsql;

上面的函数有两个问题:

  1. parent_idinteger 但它被替换为引号? int 变量的正确格式说明符是什么?
  2. select into 不适用于EXECUTE?如何进行上述注释查询以使用传递的表名?

【问题讨论】:

    标签: postgresql plpgsql dynamic-sql string-concatenation


    【解决方案1】:

    这样会更短、更快、更安全:

    CREATE OR REPLACE FUNCTION get_parent_ltree(parent_id bigint, tbl_name regclass
                                              , OUT parent_ltree ltree)
      LANGUAGE plpgsql AS
    $func$
    BEGIN
       EXECUTE format('SELECT l_tree FROM %s WHERE id = $1', tbl_name)
       INTO  parent_ltree
       USING parent_id;
    END
    $func$;
    

    为什么?

    最重要的是,将USING clause of EXECUTE 用于参数值。不要将它们转换为text,将它们连接起来并解释回来。那会更慢且容易出错。

    通常您会使用%I specifier with format() 来表示表名等标识符。对于现有表,regclass object-identifier type 可能会更好。见:

    OUT parameter 使它更简单。性能是一样的。

    不要在 Postgres 中使用不带引号的 CaMeL 案例标识符,例如 getParentLtreeDetails in the manual.

    【讨论】:

    • 太棒了!,它好多了,不知道是否可以接受 2 个答案。将使用所有建议,CaMel 大小写是我的错误,只是出于习惯,我知道 postgres 会将其变为小写,使用引号只会让事情变得更糟。
    • $1 在您的 select 语句中是什么意思?
    • @RonaldDas:这是 USING 子句提供的第一个值的参数。详情请点击第一个链接。
    • @ErwinBrandstetter 嘿。我尝试复制您的答案,但遇到了一些问题。你愿意帮我解决吗。 link
    【解决方案2】:

    对字符串使用%s%I 用于标识符:

    select format('select into parent_ltree l_tree from %I  where id = %s', 'tbl1', 1);
                             format                          
    ---------------------------------------------------------
     select into parent_ltree l_tree from tbl1  where id = 1
    

    http://www.postgresql.org/docs/current/static/functions-string.html#FUNCTIONS-STRING-FORMAT

    PL/pgSQL 的 select into 与 Postgresql 的 select into 不同。改用create table as:

    create table parent_ltree as 
    select l_tree 
    from tbl1
    where id = 1
    

    http://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-SQL-ONEROW

    提示:请注意,这种对带有 INTO 的 SELECT 的解释与 PostgreSQL 的常规 SELECT INTO 命令完全不同,后者的 INTO 目标是一个新创建的表。如果要从 PL/pgSQL 函数中的 SELECT 结果创建表,请使用语法 CREATE TABLE ... AS SELECT。

    select into 来自execute 语句的变量:

    EXECUTE format('select l_tree from %I where id = %s', tbl_name,parent_id) 
    into parent_ltree;
    

    http://www.postgresql.org/docs/current/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN

    【讨论】:

    • 感谢回复,%s 是正确的类型说明符,适用于问题 1,但问题 2 结果只是一个值而不是集合,因为在这种情况下 id 是唯一的,我们如何阅读它变成一个变量而不是一个表?
    • 也可以,非常感谢!总结您的解决方案 1. 标识符 2. 的 %s 应在格式函数之外使用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-13
    • 2013-08-28
    • 1970-01-01
    相关资源
    最近更新 更多