如何在PL/SQL中仅当参数非空时为存储过程添加AND查询条件
实现条件动态添加的PL/SQL方案
嘿,这个需求在PL/SQL里处理起来很灵活,我给你两种常用的靠谱方案,你可以根据实际场景选择:
方案一:静态SQL(推荐,更安全高效)
这种方式不需要拼接SQL,直接通过逻辑条件控制过滤规则,既能避免SQL注入,还能让Oracle优化器缓存执行计划,性能更稳定。
注意:你原代码里的两个表vtr_t_doc_atch_type_master和vtr_t_doc_atch_job_mapping没有关联条件,会产生笛卡尔积(结果完全不符合预期),我先补上一个合理的关联逻辑(比如用code_sp_type关联,你可以根据实际表结构调整),再加上动态条件:
procedure get_documents (pi_id in varchar2, -- Inside Outside param pi_entry_pemit in varchar2, po_resultSet out sys_refcursor) is begin OPEN po_resultSet FOR select typ.description, typ.attch_type, typ.code_sp_type from vtr_t_doc_atch_type_master typ join vtr_t_doc_atch_job_mapping jmap on typ.code_sp_type = jmap.code_sp_type -- 必须添加表关联条件,避免笛卡尔积 where typ.active = 'Y' -- 核心逻辑:参数为空时跳过该条件,不为空时匹配对应值 AND (pi_entry_pemit IS NULL OR jmap.inside_outside_type = pi_entry_pemit); end get_documents;
逻辑说明:如果pi_entry_pemit为空,pi_entry_pemit IS NULL为真,括号内整体条件成立,不会过滤jmap.inside_outside_type;如果参数不为空,就会强制要求jmap.inside_outside_type等于传入值。
方案二:动态SQL(适合复杂条件拼接场景)
如果后续需求有更多动态条件组合,可以用动态SQL拼接语句,但一定要用绑定变量防止SQL注入:
procedure get_documents (pi_id in varchar2, -- Inside Outside param pi_entry_pemit in varchar2, po_resultSet out sys_refcursor) is v_sql varchar2(1000); begin -- 先写固定的基础SQL部分 v_sql := 'select typ.description, typ.attch_type, typ.code_sp_type from vtr_t_doc_atch_type_master typ join vtr_t_doc_atch_job_mapping jmap on typ.code_sp_type = jmap.code_sp_type where typ.active = ''Y'''; -- 判断参数是否为空,动态拼接条件 if pi_entry_pemit is not null then v_sql := v_sql || ' AND jmap.inside_outside_type = :p_entry_pemit'; end if; -- 打开游标并绑定变量 OPEN po_resultSet FOR v_sql USING pi_entry_pemit; -- 参数为空时,Oracle会自动忽略该绑定变量 end get_documents;
两种方案对比
- 静态SQL:代码简洁,执行计划可缓存,性能稳定,优先推荐。
- 动态SQL:灵活性更高,适合多条件动态组合场景,但要严格使用绑定变量规避SQL注入风险。
最后再提醒一遍:必须给两个表添加正确的关联条件,否则查询结果会是两个表的笛卡尔积,数据量异常且完全不符合业务预期。
内容的提问来源于stack exchange,提问作者Kgn-web
相关产品推荐
相关产品推荐

