【问题标题】:Oracle stored proc - dynamically generate select statement based on optional paramsOracle 存储过程 - 根据可选参数动态生成选择语句
【发布时间】:2012-12-02 18:09:17
【问题描述】:
create or replace
PROCEDURE get_txn_by_account_id(
p_ACCOUNT_ID IN txn.ACCOUNT_ID%TYPE DEFAULT NULL
) 

IS

BEGIN
FOR x IN (SELECT * FROM txn where account_id=p_ACCOUNT_ID)
LOOP
    dbms_output.put_line(x.txn_ID || ', ' || x.txn_VER_NB);

END LOOP;
END get_txn_by_account_id;

我的存储过程基于一个输入作为搜索条件发出选择并输出搜索结果。我的输入是 帐户ID。我想添加 4 个额外的输入参数(param_a、param_b、param_c、param_d) - 其中至少两个是 可选的。

所以我可能会像这样更改我的存储过程声明

PROCEDURE get_txn_by_account_id(
p_ACCOUNT_ID IN txn.ACCOUNT_ID%TYPE DEFAULT NULL,
p_PARAM_A IN txn.PARAM_A%TYPE DEFAULT NULL,
p_PARAM_B IN txn.PARAM_B%TYPE DEFAULT NULL,
p_PARAM_C IN txn.PARAM_C%TYPE DEFAULT NULL,
p_PARAM_D IN txn.PARAM_D%TYPE DEFAULT NULL
) 

所以我的 SELECT 可能有不同数量的查询参数,具体取决于传递给存储的可选参数 过程。

例如,

FOR x IN (SELECT * FROM txn where account_id=p_ACCOUNT_ID, param_a=p_PARAM_A, param_b=p_PARAM_B, param_c=p_PARAM_C, param_d=p_PARAM_D)
FOR x IN (SELECT * FROM txn where account_id=p_ACCOUNT_ID, param_a=p_PARAM_A, param_c=p_PARAM_C, param_d=p_PARAM_D)
FOR x IN (SELECT * FROM txn where account_id=p_ACCOUNT_ID, param_a=p_PARAM_A, param_b=p_PARAM_B, param_d=p_PARAM_D)

FOR x IN (SELECT * FROM txn where account_id=p_ACCOUNT_ID, param_a=p_PARAM_A, param_b=p_PARAM_B)

等等

我遇到了问题 - 如何对我的存储过程进行编码,以便 SELECT 语句根据传递的可选参数进行更改 到存储的过程 - 可能是一个字符串构建器,它基于传递给过程的可选参数构建查询语句, 然后在查询中使用结果字符串?我不确定这是否可能。当然这是一个普遍的问题 - 有人有什么建议吗?谢谢!

【问题讨论】:

  • 为什么p_ACCOUNT_ID 是可选的?或者换一种说法,如果没有提供p_ACCOUNT_ID,你想返回什么?
  • 在这种情况下我会返回一个空集

标签: oracle stored-procedures plsql


【解决方案1】:

您可以使用以下技巧:

select * from FOO
where
  COLUMN_1 = nvl(pParam1, COLUMN_1)
  and COLUMN_2 = nvl(pParam2, COLUMN_2)
  and ...

这可确保如果 pParam1null,则您的条件始终计算为 true。以此类推。

【讨论】:

    【解决方案2】:
    FOR x IN ( SELECT * 
               FROM txn 
               WHERE account_id=p_ACCOUNT_ID
                 AND (p_PARAM_A is null or param_a=p_PARAM_A)
                 AND (p_PARAM_B is null or param_b=p_PARAM_B)
                 AND (p_PARAM_C is null or param_c=p_PARAM_C)
                 AND (p_PARAM_D is null or param_d=p_PARAM_D) )
    

    【讨论】:

    • 问题是 - 例如,如果 PARAM_A 没有传递到存储的过程中 - 我不一定要搜索 PARAM_A 为空的位置作为连接的一部分,我只想不完全将 PARAM_A 作为查询参数。
    • 让优化器来处理:p_PARAM_A is null 的结果在编译时是已知的。
    • 或者我误解了你:如果你使用我的查询,你不是搜索PARAM_A is null作为连接的一部分,你正在搜索p_PARAM_A is null,这是在编译时已知在这种情况下是正确的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-03
    • 1970-01-01
    • 2011-01-07
    • 1970-01-01
    • 2023-04-09
    相关资源
    最近更新 更多