在Oracle 11.2中,如何在两个级别的子查询中解决引用别名的问题

时间:2018-08-09 23:55:50

标签: sql oracle11g reference sql-update subquery

我在查询在Oracle 12.1而不是Oracle 11.2不能正常工作的情况下遇到了一个难题。经过一番挖掘,看来在Oracle 11.2中,如果子查询太深,则不能在最外面的查询中引用别名。

在下面的查询中,(1)和(2)都从各自的子查询中引用LT,这些子查询是嵌套在UPDATE内的两个或三个级别。显然,此限制已在12中删除,但在11.2中仍然存在,并且一直存在。

我不能使用WITH子句,因为这是一个更新。还有其他解决方案可以使此查询在11.2中运行吗?

UPDATE TBL LT
SET LT.DW = 'W'
WHERE (LT.CID, LT.ID) IN (
    SELECT 
        A.CID,
        A.ID 
    FROM (
        SELECT DISTINCT 
            CID,
            ROW_NUMBER() OVER (PARTITION BY ID ORDER BY 
                (CASE
                        WHEN ((SELECT F.NET_INC 
                               FROM BUDGET F 
                               WHERE F.TRACE_ID = LT.TRACE_ID ) -- (1)
                            < (SELECT LOINC 
                               FROM MAL 
                               WHERE CODE = (SELECT F.SIZEC 
                                             FROM BUDGET F 
                                             WHERE F.TRACE_ID = LT.TRACE_ID))) -- (2)
                        THEN 1
                        ELSE 2
                 END),
                OC_DT , 
                CID) AS "RANK", 
            ID, 
            G_ID
        FROM TBL
        WHERE RN = 120) A 
    WHERE 
        A.RANK = 1
        AND A.RN = 'B'
        AND LT.STS = 'V'
); 

1 个答案:

答案 0 :(得分:1)

也许您可以尝试使用MERGE

尝试(有点),但由于我没有您的桌子而无法对其进行测试。试试看,如有必要,请修复它(难怪您不必这样做)。

(顺便说一句,“大小”似乎是无效的列名,所以我给它加上了“ c”作为前缀。)

MERGE INTO tbl lt
     USING (SELECT a.cid, a.id
              FROM (
                    -- subquery where TRACE_ID isn't too deeply nested ...
                    SELECT DISTINCT
                           y.cid,
                           y.sts,
                           ROW_NUMBER ()
                           OVER (
                              PARTITION BY id
                              ORDER BY
                                 CASE
                                    WHEN ( (SELECT f.net_inc
                                              FROM budget f
                                             WHERE f.trace_id =
                                                      y.trace_id) <
                                             (SELECT loinc
                                                FROM mal
                                               WHERE code =
                                                        (SELECT f.sizec
                                                           FROM budget f
                                                          WHERE f.trace_id =
                                                                   y.trace_id)))
                                    THEN
                                       1
                                    ELSE
                                       2
                                 END,
                                 oc_dt,
                                 cid)
                              AS rnk,
                           y.id,
                           y.g_id
                      FROM tbl y           -- ... because you select from TBL in it
                     WHERE y.rn = 120) a
             WHERE     a.rnk = 1
                   AND a.rn = 'B'
                   AND a.sts = 'V') x
        ON (    lt.cid = x.cid
            AND lt.id = x.id)
WHEN MATCHED
THEN
   UPDATE SET lt.dw = 'W';

或者,使用基于您的“ A”子查询的视图:

CREATE VIEW v_tbl
AS
   SELECT DISTINCT
          cid,
          ROW_NUMBER ()
          OVER (
             PARTITION BY id
             ORDER BY
                (CASE
                    WHEN ( (SELECT f.net_inc
                              FROM budget f
                             WHERE f.trace_id = y.trace_id)            -- (1)
                                                            <
                             (SELECT loinc
                                FROM mal
                               WHERE code = (SELECT f.csize
                                               FROM budget f
                                              WHERE f.trace_id = y.trace_id))) -- (2)
                    THEN
                       1
                    ELSE
                       2
                 END),
                oc_dt,
                cid)
             AS rnk,
          id,
          g_id
     FROM tbl y
    WHERE rn = 120;

UPDATE tbl lt
   SET lt.dw = 'W'
 WHERE (lt.cid, lt.id) IN (SELECT v.cid, v.id
                             FROM v_tbl
                            WHERE     v.rnk = 1
                                  AND v.rn = 'B'
                                  AND lt.sts = 'V');