在sql查询中使用参数删除行的函数

问题描述 投票:0回答:1

我想创建一个删除行并在没有错误的情况下返回 true 的函数:

CREATE OR REPLACE FUNCTION s_grnplm_tt.sp_del_stts_cd(num text, package_name text, stts_cd text)
      returns bool
      LANGUAGE plpgsql as 
$func$ 
BEGIN
         EXECUTE 
     'delete FROM s_grnplm_'||num||'tt.log_copy d WHERE d.package_name =' ||package_name|| ' and d.stts_cd = $1'
      
      using stts_cd;
      return true;
end;
$func$;

我正在调用一个函数: select s_grnplm_tt.sp_del_stts_cd('089', '0202_20232211_2434', 'U')

但我收到错误: SQL 错误 [42601]:错误:“_20232211_2434”处或附近的语法错误其中:PL/pgSQL 函数 sp_del_stts_cd(text,text,text) 第 3 行在 EXECUTE 语句

function plpgsql sql-delete dynamic-sql identifier
1个回答
0
投票

首先,你应该阅读一些有关 SQL 注入问题的内容。

其次,当你对动态SQL(

EXECUTE
)语句有问题时,那么你应该使用
RAISE NOTICE
语句并显示执行的SQL语句。那么问题就干净了:

delete FROM s_grnplm_089tt.log_copy d WHERE d.package_name =0202_20232211_2434 and d.stts_cd = $1

谓词中缺少撇号

d.package_name =0202_20232211_2434

您的函数可以重写为:

CREATE OR REPLACE FUNCTION s_grnplm_tt.sp_del_stts_cd(num text,
                                                      package_name text,
                                                      stts_cd text)
      RETURNS void
      LANGUAGE plpgsql as 
$func$ 
DECLARE sqlstr text;
BEGIN
  sqlstr := format('DELETE FROM %I d WHERE d.package_name = %L AND d.stts_cd = $1',
                   's_grnplm_' || num || 'tt.log_copy', package_name);
  RAISE NOTICE '%', sqlstr;
  EXECUTE sqlstr USING stts_cd;
END;
$func$;

现在,查询是正确的:

DELETE FROM "s_grnplm_089tt.log_copy" d WHERE d.package_name = '0202_20232211_2434' AND d.stts_cd = $1

动态 SQL 只需要将 SQL 标识符作为字符串传递。其他可以通过使用

USING
子句传递二进制。因此谓词
d.package_name =
的使用方式应与
d.stts_cd =
谓词类似:

BEGIN
  sqlstr := format('DELETE FROM %I d WHERE d.package_name = $1 AND d.stts_cd = $2',
                   's_grnplm_' || num || 'tt.log_copy');
  RAISE NOTICE '%', sqlstr;
  EXECUTE sqlstr USING package_name, stts_cd;
END;
© www.soinside.com 2019 - 2024. All rights reserved.