Oracle正在SQL中运行my函数,用于WHERE子句中过滤掉的数据
我有一个Oracle SQL语句,它获取一些数据,并将其传递给一个函数,该函数返回一个值。如果收到的数据无效,该函数将引发应用程序错误 函数正在引发错误,因为它正在获取不应该包含的数据,即使该数据已在where子句中或通过隐式内部联接过滤掉 基本上,Oracle似乎是在过滤掉数据之前将数据传递给函数。我怎样才能防止这种情况 您可以在查询正在运行的函数下面看到注释。最后一个谓词和WHSE.WIDX=5632使此SQL返回0个结果,但是如果没有它,该值将传递给PAS.PAS\u MERCH\u PLAN.GET\u WHSE\u CUST\u PRICE\u SCHEME函数Oracle正在SQL中运行my函数,用于WHERE子句中过滤掉的数据,sql,oracle,oracle11g,Sql,Oracle,Oracle11g,我有一个Oracle SQL语句,它获取一些数据,并将其传递给一个函数,该函数返回一个值。如果收到的数据无效,该函数将引发应用程序错误 函数正在引发错误,因为它正在获取不应该包含的数据,即使该数据已在where子句中或通过隐式内部联接过滤掉 基本上,Oracle似乎是在过滤掉数据之前将数据传递给函数。我怎样才能防止这种情况 您可以在查询正在运行的函数下面看到注释。最后一个谓词和WHSE.WIDX=5632使此SQL返回0个结果,但是如果没有它,该值将传递给PAS.PAS\u MERCH\u PL
SELECT
DISTINCT WHSE.WIDX
FROM
AP21.STKAUD
LEFT JOIN
AP21.POZD
ON POZD.POZDIDX = STKAUD.TRANIDX
LEFT JOIN
AP21.PORDD
ON PORDD.PORDDIDX = POZD.PORDDIDX
LEFT JOIN
AP21.PORD
ON PORD.PORDIDX = PORDD.PORDIDX
INNER JOIN
AP21.WHSE
ON WHSE.WIDX = STKAUD.WHSIDX
-- INNER JOIN
-- AP21.REFCODE CURRENCY ON
-- CURRENCY.RCIDX = PAS.PAS_MERCH_PLAN.GET_PRICE_SCHEME_CURRENCY(PAS.PAS_MERCH_PLAN.GET_WHSE_CUST_PRICE_SCHEME(WHSE.WIDX))
INNER JOIN
AP21.REFCODE WHSE_RC ON
WHSE_RC.RCIDX = STKAUD.WHSIDX
LEFT OUTER JOIN
(
SELECT
BUSDIV,
WHSEIDX
FROM
AP21.GIT_MERCH_PLANNING_CONFIG PLAN_CONF
UNPIVOT (WHSEIDX FOR WAREHOUSE_CODE IN (WHSE1,WHSE2,WHSE3,WHSE4,WHSE5))
) RETAIL_WAREHOUSE ON
RETAIL_WAREHOUSE.WHSEIDX = WHSE.WIDX
AND RETAIL_WAREHOUSE.BUSDIV = WHSE.REF1
WHERE
(
WHSE.TYPE = 'R'
OR RETAIL_WAREHOUSE.WHSEIDX IS NOT NULL
)
AND
(
STKAUD.TRANTYPE = '231' --TRANSFER OUT
OR STKAUD.TRANTYPE = '32125' --STOCK WRITEDOWN
OR STKAUD.TRANTYPE = '32124' --DIRECT STOCK TRANSFER
OR (STKAUD.TRANTYPE = '210' AND COLUMN1 = 0 AND NVL(PORD.ARMS_LENGTH_DIRECT,0) <> 1 ) --WAREHOUSE PURCHASE ORDER RECEIPTS excluding Intercompany
OR (STKAUD.TRANTYPE = '104' AND COLUMN1 = 0) --WAREHOUSE PRODUCTION RECEIPTS
)
AND TRANDATE >= TRUNC(SYSDATE-1)
AND TRANDATE < TRUNC(SYSDATE-1)+1
AND WHSE.WIDX = 5632
我认为您无法控制Oracle在解决查询时的操作 当显示查询时,它会准备一个执行计划,并可能决定首先计算这些值,然后在最后进行筛选 也许,如果您修改了内部连接并在其中添加了该条件,那么它会在调用函数之前应用该过滤器
...
INNER JOIN
AP21.REFCODE CURRENCY ON
WHSE.WIDX = 5632
AND
CURRENCY.RCIDX = PAS.PAS_MERCH_PLAN.GET_PRICE_SCHEME_CURRENCY(PAS.PAS_MERCH_PLAN.GET_WHSE_CUST_PRICE_SCHEME(WHSE.WIDX))
...
您可以使用CASE语句强制条件短路,例如,写入函数为_VALIDwidx
INNER JOIN
AP21.REFCODE CURRENCY ON
CURRENCY.RCIDX =
CASE WHEN IS_VALID(WHSE.WIDX) = 'Y'
THEN PAS.PAS_MERCH_PLAN.GET_PRICE_SCHEME_CURRENCY(PAS.PAS_MERCH_PLAN.GET_WHSE_CUST_PRICE_SCHEME(WHSE.WIDX))
END
确保只对满足查询中其他条件的行调用该函数的一个好方法是将查询的其余部分放入子查询中,并在外部查询中调用该函数,例如:
SELECT q.WIDX
FROM (your query) q
JOIN AP21.REFCODE CURRENCY
ON CURRENCY.RCIDX
= PAS.PAS_MERCH_PLAN.GET_PRICE_SCHEME_CURRENCY(
PAS.PAS_MERCH_PLAN.GET_WHSE_CUST_PRICE_SCHEME(q.WIDX))
我想情况就是这样,但是我希望有一种方法可以重新安排查询,或者可能是优化器提示。上述方法不起作用,因为谓词WHSE.WIDX=5632不是硬编码的,它只是为了解决这个问题。我可以修改函数以只返回NULL,但是我们希望它在合法情况下引发错误。即使没有硬编码,也不能动态地重复它?不幸的是,即使这种方法也不是100%可靠的。有关案例短路不能防止错误的示例,请参阅。