【问题标题】:Correctly inserting literals in PL/PgSQL EXECUTE dynamic queries在 PL/PgSQL EXECUTE 动态查询中正确插入文字
【发布时间】:2012-10-11 00:51:02
【问题描述】:

以下是 plpgsql 函数的一部分。问题是source_geomtarget_geom 的结果是character varying 数据类型,因此我需要将source_geomtarget_geom 括在引号('')中。问题是在 plpgsql 语言中我不知道我能做到。
这是我目前拥有的:

 EXECUTE 'update ' || quote_ident(geom_table) || 
        ' SET source = ' || source_geom || 
        ', target = ' || target_geom ||
        ' WHERE ' || quote_ident(gid_cname) || ' =  ' || _r.id;

我遇到的错误如下;

ERROR:  syntax error at or near "C03B9E3B66052D400DDEFC2BD0F24140"
LINE 1: ...pdate track_points SET source = 0101000020E6100000C03B9E3B66...
                                                             ^
QUERY:  update track_points SET source = 0101000020E6100000C03B9E3B66052D400DDEFC2BD0F24140, target = 0101000020E610000075690DEF83052D40F88E75CCD4F24140 WHERE ogc_fid =  2
CONTEXT:  PL/pgSQL function "create_network" line 26 at EXECUTE statement

请给我建议如何解决这个问题。?

【问题讨论】:

    标签: sql postgresql plpgsql dynamic-sql


    【解决方案1】:

    使用额外的引号:

    EXECUTE 'update ' || quote_ident(geom_table) || 
            ' SET source = ''' || source_geom || ''' 
            , target = ''' || target_geom || '''
            WHERE ' || quote_ident(gid_cname) || ' =  ' || _r.id;
    

    【讨论】:

    • quote_literal 避免SQL注入?
    【解决方案2】:

    EXECUTE ... USINGformat() 函数及其格式说明符一起使用将使您的代码更安全、更简单、更易于阅读并且可能更快。


    SQL 注入警告:如果您曾经接受来自最终用户的source_geomtarget_geom,您的代码可能会受到SQL injection 的攻击。重要的是使用参数化语句(如EXECUTE ... USING)或失败,偏执引用以防止 SQL 注入攻击。即使您认为您的函数不接受用户输入,您仍然应该加强它以防止 SQL 注入,因为您不知道您的应用将如何发展。


    如果您使用的是带有 format function 的较新 PostgreSQL,您的代码可以显着简化为:

    EXECUTE format('update %I SET source = %L, target = %L WHERE %I = %L',
        geom_table, source_geom, target_geom, gid_cname, _r.id);
    

    ... 它使用格式说明符为您处理标识符 (%I) 和文字 (%L) 引用,因此您不必编写所有糟糕的 || 连接和 quote_literal/quote_ident东西。

    然后,根据the documentation on EXECUTE ... USING,您可以将查询进一步细化为:

    EXECUTE format(
        'update %I SET source = $1, target = $2 WHERE %I =  $3',
        geom_table, gid_cname
    ) USING source_geom, target_geom, _r.id;
    

    将查询转换为参数化语句,清楚地将参数与标识符分开,并降低字符串处理成本以实现更高效的查询。

    【讨论】:

    • EXECUTE format('...') USING 可能是最好的。当不能在 USING 子句中使用时,应使用格式函数中的参数 - 列、表名。
    • 很好的解释和救命稻草。我刚刚遇到了一种情况,我不得不根据传入的表名和动态创建的几何图形来更新一些东西,我想我终于明白了如何像这样使用格式和一起使用。
    • @Craig Ringer 很棒的解释和救命稻草。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-21
    • 2012-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 2018-06-26
    相关资源
    最近更新 更多