【问题标题】:postgresql dynamic querypostgresql 动态查询
【发布时间】:2021-12-11 06:25:11
【问题描述】:

我需要用以下函数中的参数替换架构和表名(目前运行良好):

CREATE OR REPLACE FUNCTION public.my_function_119()
 RETURNS integer
 LANGUAGE plpgsql
AS $function$
                DECLARE _check INTEGER;
                BEGIN
                    SELECT SUM("length"/1000)
                    FROM public."National_Grid_multiline"
                    INTO _check;
                    RETURN _check;
                END
                $function$

我尝试了以下解决方案(及其众多变体):

CREATE OR REPLACE FUNCTION public.my_function_119(schema text, tablename text)
 RETURNS INTEGER
 LANGUAGE  plpgsql
AS
$function$
                DECLARE _check INTEGER;
                BEGIN
                  RETURN
                    '(SELECT SUM((length/1000))::integer FROM ' || schema || '."' || tablename || '")::integer INTO _check' ;
                RETURN _check;
                END
                $function$

但不断遇到以下错误代码:

psycopg2.errors.InvalidTextRepresentation: invalid input syntax for type integer: "(SELECT SUM((length/1000))::integer FROM public."National_Grid_multiline")::integer INTO _check"

CONTEXT:  PL/pgSQL function my_function_119(text,text) while casting return value to function's return type

为什么这不起作用? “长度”列包含浮点值。

【问题讨论】:

    标签: postgresql function dynamic


    【解决方案1】:

    您必须使用动态 SQL,因为您不能使用参数作为标识符。

    另外,请确保通过使用format 而不是连接字符串来避免 SQL 注入:

    EXECUTE
       format(
          'SELECT SUM((length/1000))::integer FROM %I.%I',
          schema,
          table_name
       )
       INTO _check';
    

    【讨论】:

    • 脚本在我的本地机器上运行,没有 SQL 注入危险
    • 这不一定有帮助。您可能有一个非标准名称的表...
    • 好的,但这不是现在真正的问题。我的问题仍然是我的原始函数没有参数(参见上面的代码)工作正常,但是 - 一旦我使用这两个参数 - 我就会得到各种似乎与参数本身无关的错误。
    • 是的。这就是我的答案所要解决的问题。
    • 不幸的是,您的解决方案引发了括号不匹配。纠正后,它会引发以下错误: .... psycopg2.errors.UndefinedObject: type "format" does not exist LINE 1: SELECT format('(SELECT SUM((length/1000))::integer FROM %I.% ... ^ QUERY: SELECT format('(SELECT SUM((length/1000))::integer FROM %I.%I', schema, table_name) 'INTO _check' CONTEXT: PL/pgSQL function my_function_119(text,text ) 第 4 行执行
    【解决方案2】:

    你可以试试这个:

    CREATE OR REPLACE FUNCTION public.my_function_119(schema text, tablename text)
     RETURNS INTEGER
     LANGUAGE  plpgsql
    AS
    $function$
    DECLARE
    res integer ;
    BEGIN
    EXECUTE E'
    (SELECT SUM((length/1000))::integer INTO res FROM ' || schema || '."' || tablename || '"):: integer' ;
    RETURN res ;
    END ;
    $function$
    

    【讨论】:

    • 以上两种解决方案都不能解决此问题。他们只是产生其他错误消息
    • public.National_Grid_multiline 表中“length”列的数据类型是什么?
    • 执行的结果是什么:SELECT SUM(length/1000) FROM public.National_Grid_multiline ?
    • 数据库中列的数据类型是双精度的(但是用整数替换函数中的数据类型也不能解决问题。您发布的答案会引发以下错误:-> 语法错误处或附近"END" SELECT SUM(length/1000) FROM public.National_Grid_multiline -> 关系 "public.national_grid_multiline" 不存在 SELECT SUM(length/1000) FROM public."National_Grid_multiline" -> 684921.2474125557 SELECT SUM("length"/1000) FROM public."National_Grid_multiline" 684921.2474125557
    • 我在之前的回答中更新了函数 my_function 以使其正常工作。报错“relation "public.national_grid_multiline" doesn't exist”表示你连接的数据库中不存在表public.national_grid_multiline,所以你必须先解决这个问题才能继续。
    猜你喜欢
    • 2022-06-28
    • 2013-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多