2016-05-20 80 views
-2

这是关于将查询转换为ANSI SQL的。我试着用Oracle旧语法编写这个查询,并且抛出了下面的错误,所以我最终改变了它,如下所示。经过研究,我发现ANSI SQL支持这样的要求。Oracle将SQL迁移到ANSI SQL

ERROR:表可能是外部联接至多一个其他表提示

这里是我写的这是工作,但是如果有这种可能被改写的方式,将是巨大的,知道查询在ANSI-SQL中或通过使用旧的外部联接语法。我正在寻找联合查询在with子句中被重写为其他人的工作正常。

WITH BOM_PARENT AS (
    SELECT MX.SAP_MATNR MATNR 
     , TRIM(I.IPRODUCTION) IPRODUCTION 
     , TRIM(I.IDRAWING) IDRAWING 
     , TRIM(M.BCHLD) BCHLD 
     , M.BSEQ BSEQ 
     , PX.WERKS WERKS 
     , M.BPSCP MENGE 
     , UX.SAP_UOM MEINS 
     , I.IUMS 
    FROM XX_MAIN.XX_BPCS_IIM I 
     , XX_MAIN.XX_BPCS_MPB M 
     , XX_MAIN.XX_MATER_XREF MX 
     , XX_MAIN.XX_TRUNK_XREF PX 
     , XX_MAIN.XX_MP_UNIT_XREF UX 
    WHERE TRIM(I.IPRODUCTION) = TRIM(M.BPROD) 
     AND TRIM(MX.PROD_MATNR) = TRIM(I.IPRODUCTION) 
     AND MX.CONV_FACTOR = TO_CHAR(I.IUMCN) 
     AND I.IUMS = UX.LEGACY_UOM 
     AND UX.SOURCE = 'AP' 
     AND I.SOURCE = PX.SOURCE 
     AND I.ENTITY = PX.LEGACY_PLANT 
     AND I.ENTITY = 'SG' 
     AND I.IITYP = '4' 
     --AND PX.WERKS IN ('1379') 
     AND MX.SAP_MTART <> 'ZPRD' 
    ) 
    , BOM_CHILDS AS 
    (
    SELECT B.*, 
      X.SAP_MATNR IDNRK 
      , ROW_NUMBER() OVER (PARTITION BY B.MATNR,B.WERKS ORDER BY B.MATNR,B.WERKS) ID_ITEM_NO 
      , X.PROD_MATNR IDNRK_IPRODUCTION 
      , X.DRAWING_MATNR IDNRK_IDRAWING  
     FROM BOM_PARENT B 
      , XX_MAIN.XX_MATER_XREF X 
    WHERE B.BCHLD = TRIM(X.PROD_MATNR) 
     AND X.SAP_MTART <> 'ZPRD' 
     AND X.SOURCE = 'AP' 
    ) 
    SELECT DISTINCT C.MATNR 
     , C.IPRODUCTION 
     , C.IDRAWING 
     , C.WERKS 
     , (C.ID_ITEM_NO*10) ID_ITEM_NO 
     , C.BSEQ 
     , C.IDNRK 
     , C.IDNRK_IPRODUCTION 
     , C.IDNRK_IDRAWING 
     , C.MENGE BPSCP 
     , STPO.MENGE STPO_MENGE 
     , C.MEINS MEINS 
     , C.IUMS IUMS 
     , STPO.MEINS STPO_MEINS 
     FROM BOM_CHILDS C 
     , XX_MAIN.XX_MAST MAST 
     , XX_MAIN.XX_STPO STPO 
     WHERE C.MATNR = MAST.MATNR 
     AND MAST.STLNR = STPO.STLNR 
     AND MAST.STLAN = '1' 
     AND MAST.WERKS = C.WERKS 
     AND STPO.IDNRK = C.IDNRK 
    UNION 
    SELECT DISTINCT C.MATNR 
     , C.IPRODUCTION 
     , C.IDRAWING 
     , C.WERKS 
     , (C.ID_ITEM_NO*10) ID_ITEM_NO 
     , C.BSEQ 
     , C.IDNRK 
     , C.IDNRK_IPRODUCTION 
     , C.IDNRK_IDRAWING 
     , C.MENGE BPSCP 
     , STPO.MENGE STPO_MENGE 
     , C.MEINS MEINS 
     , C.IUMS IUMS 
     , STPO.MEINS STPO_MEINS 
     FROM BOM_CHILDS C 
     , XX_MAIN.XX_MAST MAST 
     , XX_MAIN.XX_STPO STPO 
     WHERE C.MATNR = MAST.MATNR(+) 
     AND MAST.STLNR = STPO.STLNR(+) 
     AND MAST.STLAN(+) = '1' 
     AND MAST.WERKS(+) = C.WERKS 
     AND STPO.IDNRK IS NULL 
    ORDER BY MATNR,WERKS,ID_ITEM_NO,BSEQ; 

回答

2

这部分可能是造成问题的原因:

FROM BOM_CHILDS C 
    , XX_MAIN.XX_MAST MAST 
    , XX_MAIN.XX_STPO STPO 
    WHERE C.MATNR = MAST.MATNR(+) 
    AND MAST.STLNR = STPO.STLNR(+) 
    AND MAST.STLAN(+) = '1' 
    AND MAST.WERKS(+) = C.WERKS 
    AND STPO.IDNRK IS NULL 

为了使这更容易一点,让我们重新排列WHERE条款下令由表它们之间的关系:

FROM BOM_CHILDS C 
, XX_MAIN.XX_MAST MAST 
, XX_MAIN.XX_STPO STPO 
-- Joining C to MAST 
WHERE C.MATNR = MAST.MATNR(+) 
    AND C.WERKS = MAST.WERKS(+) 
    AND MAST.STLAN(+) = '1' 
-- Joining MAST to STPO 
    AND MAST.STLNR = STPO.STLNR(+) 
    AND STPO.IDNRK IS NULL 

我们有C加入MAST使用从MAST它匹配的“驱动程序”表,拿起数据(左连接):

FROM BOM_CHILDS C 
LEFT JOIN XX_MAIN.XX_MAST MAST 
    ON C.MANTR = MAST.MANTR 
AND C.WERKS = MAST.WERKS 
AND MAST.STLAN = '1' 

然后我们需要添加STPO到联接:

LEFT JOIN XX_MAIN.XX_STPO STPO 
    ON MAST.STLNR = STPO.STLNR 
AND STPO.IDNRK IS NULL 

把这一切我们得到:

FROM BOM_CHILDS C 
LEFT JOIN XX_MAIN.XX_MAST MAST 
    ON C.MANTR = MAST.MANTR 
AND C.WERKS = MAST.WERKS 
AND MAST.STLAN = '1' 
LEFT JOIN XX_MAIN.XX_STPO STPO 
    ON MAST.STLNR = STPO.STLNR 
AND STPO.IDNRK IS NULL 

也就是说,即使(+)适用于左/右/外部连接,Oracle recommends not using it

Oracle建议您使用FROM条款OUTER JOIN语法,而不是甲骨文加入经营者。外连接是使用Oracle联接运算符(+)受到以下规则和限制,并不适用于FROM条款OUTER JOIN语法查询:...

+0

感谢@ Llama..How先生做我得到的不是null stpo.idnrk的值与STPO.IDNRK = C.IDNRK以及空值(我的联合查询中的第一个查询检索匹配的IDNRK)一样。是否有可能在只有一个查询而不是联合写入这个逻辑。 – Tina

+0

这就是外连接所做的。在匹配的地方,你会得到一个值,如果不匹配,你会得到NULL值。使用外部联接联合内部联接的结果总是会给出与仅外部联接相同的结果。 –

+0

@Tina - 如果此答案有助于解决您的问题,请使用投票箭头下的复选标记考虑[标记为已接受](https://stackoverflow.com/help/someone-answers)。谢谢! –