存储过程中为空时处理动态参数

Posted

技术标签:

【中文标题】存储过程中为空时处理动态参数【英文标题】:Handle dynamic parameter when null in the stored procedure 【发布时间】:2020-11-23 17:31:00 【问题描述】:

我在 redshift 中处理存储过程。我看到当传递的参数是NULL 到存储过程中的执行语句时。它以cannot execute a null string 失败。

请告诉我如何解决问题。

存储过程:

CREATE OR REPLACE PROCEDURE outer_proc() LANGUAGE plpgsql
AS $$
DECLARE
cond_holder RECORD;
iter RECORD;
BEGIN

  drop table if exists tmp_direction_comms;

  create temporary table  tmp_direction_comms as select distinct code from direction_coms;

  DROP TABLE if exists final_direction_comms;

  EXECUTE  'CREATE TEMP TABLE final_direction_comms
     (
    code varchar(100),
    direction varchar(100),
    dir_flg  Boolean
    )';

  FOR iter IN select code from tmp_direction_comms LOOP
    RAISE INFO 'code is %', iter.code;

    SELECT INTO cond_holder distinct condition FROM mapping where  code = iter.code;

    RAISE INFO 'engmnt_cd is %', cond_holder.condition;

    EXECUTE 'INSERT INTO final_direction_comms select code, direction, case when  NVL('||cond_holder.condition||',false) then true else false end as dir_flg
    from direction_coms where code = '''||iter.code||'''';

  END LOOP;
END;
$$;

【问题讨论】:

【参考方案1】:
 EXECUTE 'INSERT INTO final_direction_comms select code, direction, 
           case when  NVL('||cond_holder.condition||',false) then true else false end as dir_flg
              from acp_edw.stg_edw.direction_coms where code = '''||iter.code||'''';

有两个变量可以为 NULL - iter.codecond_holder.conditioncond_holder.conditionNVL 包裹,但NVL 在结果字符串中,而不是在生成表达式中。

第二个大问题是针对 SQL 注入的漏洞。也许你应该这样做:

 EXECUTE 'INSERT INTO final_direction_comms select code, direction, 
           case when  ' || NVL(cond_holder.condition, false) ' || then true else false end as dir_flg
              from acp_edw.stg_edw.direction_coms where code = $1'
    USING iter.code;

我不确定 Redshift 是否支持 USING 子句。如果没有,那么你应该使用quote_literal函数:

'... where code = ' || quote_literal(iter.code);

【讨论】:

我相信是管道符号 ||导致整个字符串变为空。我可以知道是否有任何其他方法。 @kites - 那么空值应该在iter.code 中。不可能有其他的可能。在执行前尝试推送 - RAISE NOTICE '% %', cond_holder.condition is null, iter.code is null; @kites - || 对空值敏感。 Postgres 有concat 功能,但是redshift 太旧了。也许你可以使用COALESCE 函数而不是NVL NVL 和 coalese 在红移中似乎是相同的。我收到此错误 COALESCE types character varying and boolean cannot be match; @kites,对于这种情况,你可以写'false'而不是false

以上是关于存储过程中为空时处理动态参数的主要内容,如果未能解决你的问题,请参考以下文章

mysql存储过程

存储过程中参数是动态的,需要判断是不是为空

存储过程输出参数+选择不传回输出参数

当我尝试通过存储过程插入空值时出现 SqlException

oracle存储过程输入参数能否为空

高效多表分页存储过程,可支持多表查询,任意排序