Oracle 在SQL中动态生成WHERE子句,并在不进行硬解析的情况下执行
在SQL中动态生成WHERE子句,并在不进行硬解析的情况下执行 我希望动态构建SQL,添加/更改/删除WHERE条件,直到找到记录。 根据业务规则设置的优先级添加/更改/删除条件 为了更好地描述问题陈述,下面是我的两个表(示例键列),它们的结构如下 表1:-->此表包含提交的每个索赔的索赔相关信息Oracle 在SQL中动态生成WHERE子句,并在不进行硬解析的情况下执行,oracle,plsql,oracle11g,plsqldeveloper,Oracle,Plsql,Oracle11g,Plsqldeveloper,在SQL中动态生成WHERE子句,并在不进行硬解析的情况下执行 我希望动态构建SQL,添加/更改/删除WHERE条件,直到找到记录。 根据业务规则设置的优先级添加/更改/删除条件 为了更好地描述问题陈述,下面是我的两个表(示例键列),它们的结构如下 表1:-->此表包含提交的每个索赔的索赔相关信息 CLAIM_DOCUMENT -------------- ( HDR_SID NUMBER, PRVDR_NPI NUMBER, INV_TYPE VARCHAR2(4), SPLT
CLAIM_DOCUMENT
--------------
(
HDR_SID NUMBER,
PRVDR_NPI NUMBER,
INV_TYPE VARCHAR2(4),
SPLTY VARCHAR2(100),
PRCDR_CODE VARCHAR2(100),
MDFR_CODE VARCHAR2(10),
DIAG_CODE VARCHAR2(100) )
表2:-->这是保存提供程序速率的配置表
PROVIDER_RATE
-------------
( PRVDR_SID NUMBER,
PRVDR_NPI NUMBER,
SPLTY VARCHAR2(100),
SUB_SPLTY VARCHAR2(100),
PRCDR_CODE VARCHAR2(100),
MDFR_CODE VARCHAR2(10)
RATE_VALUE NUMBER(20,6)
RATE_TYPE VARCHAR2(10)
);
目标是从提供者费率表中确定适用的费率值。
为了确定供应商费率,我们将索赔时提交的属性(即PRVDR\U NPI、PRCDR\U代码、MDFR\U代码)与提交给供应商费率的属性进行匹配,以找到费率值
索赔中的所有属性都可能与提供者费率不匹配,因此我们添加/更改/删除“WHERE”条件,直到从提供者费率表中找到费率值
例如,在第1遍中,业务规则说匹配所有可能的值,因此我编写SQL语句如下:
SELECT RATE_VALUE, RATE_TYPE into v_rate_value, v_rate_type
FROM CLAIM_DOCUMENT cd, PROVIDER_RATE pr
WHERE cd.hdr_sid = p_hdr_sid -- p_hdr_sid is passed as parameter to procedure for 1 claim
AND cd.PRVDR_NPI = pr.PRVDR_NPI -- PRVDR_NPI is key column to match between 2 tables
----all optional where clause to form here based on busienss rules priority --
AND cd.PRCDR_CODE = pr.PRCDR_CODE -- optional WHERE clause 1
AND cd.MDFR_CODE = pr.MDFR_CODE -- optional WHERE clause 2
AND cd.SPLTY = pr.SPLTY -- optional WHERE clause 3
--IF rate value is NOT found using all WHERE clause above, the next rule priority
--is to REMOVE SPLTY and check
IF v_rate_value IS NULL THEN
SELECT RATE_VALUE, RATE_TYPE into v_rate_value, v_rate_type
FROM CLAIM_DOCUMENT cd, PROVIDER_RATE pr
WHERE cd.hdr_sid = p_hdr_sid -- p_hdr_sid is passed as parameter to procedure for 1 claim
AND cd.PRVDR_NPI = pr.PRVDR_NPI -- PRVDR_NPI is key column to match between 2 tables
----all optional where clause to form here based on busienss rules priority --
AND cd.PRCDR_CODE = pr.PRCDR_CODE -- optional WHERE clause 1
AND cd.MDFR_CODE = pr.MDFR_CODE -- optional WHERE clause 2
END IF;
--IF rate value is NOT found using WHERE clause above,
--the next rule priority is to REMOVE MDFR_CODE and check
IF v_rate_value IS NULL THEN
SELECT RATE_VALUE, RATE_TYPE into v_rate_value, v_rate_type
FROM CLAIM_DOCUMENT cd, PROVIDER_RATE pr
WHERE cd.hdr_sid = p_hdr_sid -- p_hdr_sid is passed as parameter to procedure for 1 claim
AND cd.PRVDR_NPI = pr.PRVDR_NPI -- PRVDR_NPI is key column to match between 2 tables
----all optional where clause to form here based on busienss rules priority --
AND cd.PRCDR_CODE = pr.PRCDR_CODE -- optional WHERE clause 1
END IF;
我的问题:
有没有办法通过读取表中配置的业务规则,更重要的是执行
没有硬解析的动态形成的SQL语句?可以有条件地像这样打开/关闭条件:
AND (cd.PRCDR_CODE = pr.PRCDR_CODE OR l_prcdr_code_flag='off') -- optional WHERE clause 1
AND (cd.MDFR_CODE = pr.MDFR_CODE OR l_mdfr_code_flag='off') -- optional WHERE clause 2
AND (cd.SPLTY = pr.SPLTY OR l_splty_flag='off') -- optional WHERE clause 3
在代码的其余部分中,您所要做的就是处理“标志”,即在开始时将所有l_*\u标志
变量设置为'on'
,然后在运行时将其关闭(将其设置为'off'
)。
这样您就不会更改SQL,因此不需要进行硬解析。
为查询创建游标变量也是一个好主意,以避免重复代码。您可以尝试以下方法:
SELECT RATE_VALUE, RATE_TYPE,
CASE
WHEN
cd.PRCDR_CODE = pr.PRCDR_CODE -- optional WHERE clause 1
AND cd.MDFR_CODE = pr.MDFR_CODE -- optional WHERE clause 2
AND cd.SPLTY = pr.SPLTY -- optional WHERE clause 3
THEN 1
WHEN
cd.PRCDR_CODE = pr.PRCDR_CODE -- optional WHERE clause 1
AND cd.MDFR_CODE = pr.MDFR_CODE -- optional WHERE clause 2
THEN 2
WHEN
cd.PRCDR_CODE = pr.PRCDR_CODE -- optional WHERE clause 1
THEN 3
END matching_factor
FROM CLAIM_DOCUMENT cd, PROVIDER_RATE pr
WHERE cd.hdr_sid = p_hdr_sid -- p_hdr_sid is passed as parameter to procedure for 1 claim
AND cd.PRVDR_NPI = pr.PRVDR_NPI
ORDER BY 3;
这样,您将捕获满足连接条件的所有记录(cd.PRVDR\u NPI=pr.PRVDR\u NPI
),并且matching\u factor
将告诉您哪些附加条件也满足(1
=>所有3个可选子句都满足,3
=>只有PRCDR\u code子句满足)。
根据此匹配因子对结果集排序,第一行应该是最佳匹配。
这次我做对了吗?当然,只要阅读业务规则,把它们放在
变量varchar2(100)
和执行立即变量中
查询会有多少变化?如果只有3个,那么硬解析就不重要了。我不想使用EXECUTE IMMEDIATE,因为这个过程是最常用的,我相信这会造成性能问题。可能会有很多变化,所以我想让它更具可配置性和动态性,但不会以牺牲性能为代价只是一个提示:使用SELECT。。。如果查询返回零行或多行,INTO…
将引发异常,因此这种精确的查询语法将不适用于您。首先,谢谢。不确定是否正确,所以我想问一下这个场景。如果我不需要考虑每个业务需求,那么FLAG将如何帮助您,例如,您可以假设我必须只执行以下操作吗?(cd.PRCDR_CODE=pr.PRCDR_CODE或l_PRCDR_CODE_flag='off')--可选,其中第1条为}感谢GoranM的支持。您的解决方案看起来确实更好。当我们必须了解设计和实施过程中可能出现的所有排列时,您的解决方案工作得很好。我更感兴趣的是,如果出现新的更改请求,其中说检查PRVDR\u NPI和SPLY,这应该是最高优先级。我们可以接受吗在不更改代码的情况下修改此更改请求?如果需要更多详细信息,请告诉我。再次感谢