【问题标题】:How to fix PL/SQL: ORA-00918: column ambiguously defined in Oracle如何修复 PL/SQL:ORA-00918:Oracle 中定义不明确的列
【发布时间】:2019-02-12 15:59:44
【问题描述】:

我正在 Oracle 中创建一个包,当我编译包的主体时,我收到 PL/SQL: ORA-00918: column ambiguously defined 错误。

我已经检查了代码,并仔细检查了别名,所以对于我收到此错误的原因感到有些困惑。

有问题的错误在第 10 行。 WHERE 子句中的 PERSON_CODE、FUND_YEAR 和 UIO_ID 是我在包中创建的函数的参数。

    SELECT CASE 
            WHEN LH.PROP_NOT_TAUGHT > 50 AND LA.DELIVERY_PROVIDER IS NOT NULL THEN TO_NUMBER(OU.UKPRN)
            ELSE LA.UK_PROV_NO 
           END AS UKPRN_T
    FROM FES.LEARNER_AIMS LA
     JOIN FES.LEARNER_HE LH
      ON LH.PERSON_CODE = LA.PERSON_CODE
       AND LH.FUNDING_YEAR = LA.FUNDING_YEAR
     LEFT JOIN FES.ORGANISATION_UNITS OU
      ON OU.ORGANISATION_CODE = LA.DELIVERY_PROVIDER
    WHERE LA.PERSON_CODE = PERSON_CODE
     AND LA.FUNDING_YEAR = FUND_YEAR
     AND LA.UIO_ID = UIO_ID;

【问题讨论】:

    标签: sql oracle ora-00918


    【解决方案1】:

    您的函数参数名称和字段名称发生冲突,从而产生阴影效果。您可以在参数名称前加上函数名称以消除歧义

     AND LA.UIO_ID = MyfunctionName.UIO_ID;
    

    或者,重命名参数以避免此类情况发生。

    【讨论】:

    • 谢谢,这是我需要的解决方案。有点奇怪,因为我有很多函数,在不使用函数名称的包中似乎没问题。
    【解决方案2】:

    将表格别名与列名称一起使用总是很好的做法。

    SELECT CASE 
            WHEN LH.PROP_NOT_TAUGHT > 50 AND LA.DELIVERY_PROVIDER IS NOT NULL THEN TO_NUMBER(OU.UKPRN)
            ELSE LA.UK_PROV_NO 
           END AS UKPRN_T
    FROM FES.LEARNER_AIMS LA
     JOIN FES.LEARNER_HE LH
      ON LH.PERSON_CODE = LA.PERSON_CODE
       AND LH.FUNDING_YEAR = LA.FUNDING_YEAR
     LEFT JOIN FES.ORGANISATION_UNITS OU
      ON OU.ORGANISATION_CODE = LA.DELIVERY_PROVIDER
    WHERE LA.PERSON_CODE = <tableAlaisForPersonCode>PERSON_CODE
     AND LA.FUNDING_YEAR = <tableAlaisForFUND_YEAR>FUND_YEAR
     AND LA.UIO_ID = <tableAlaisForUIO_ID>UIO_ID;
    

    【讨论】:

    • 抱歉,我应该补充一下,PERSON_CODE、FUND_YEAR 和 UIO_ID 是我在包中创建的函数的参数。
    • 然后消除歧义,同时为列提供functionName
    【解决方案3】:

    。 PERSON_CODE、FUND_YEAR 和 UIO_ID 是函数的参数。

    使用与列名相同的 PL/SQL 参数名是不好的做法。编译器应用最近的命名空间检查,这意味着在这种情况下它会尝试将 PERSON_CODE 映射到表列。别名是可选的,因此它不会意识到您正在尝试引用 PL/SQL 参数。

    因为您有多个表,其中包含名为 PERSON_CODE 的列,所以您会收到 ORA-00918 错误。否则,您只会有一个返回所有行的查询。

    更好的做法是以不同的方式命名参数;惯例是在它们前面加上p_:

    WHERE LA.PERSON_CODE = P_PERSON_CODE
     AND LA.FUNDING_YEAR = P_FUND_YEAR
     AND LA.UIO_ID = P_UIO_ID;
    

    【讨论】:

      【解决方案4】:

      UIO_ID 列缺少别名,只需提供OU.UIO_ID

      SELECT CASE 
              WHEN LH.PROP_NOT_TAUGHT > 50 AND LA.DELIVERY_PROVIDER IS NOT NULL THEN TO_NUMBER(OU.UKPRN)
              ELSE LA.UK_PROV_NO 
             END AS UKPRN_T
      FROM FES.LEARNER_AIMS LA
       JOIN FES.LEARNER_HE LH
        ON LH.PERSON_CODE = LA.PERSON_CODE
         AND LH.FUNDING_YEAR = LA.FUNDING_YEAR
       LEFT JOIN FES.ORGANISATION_UNITS OU
        ON OU.ORGANISATION_CODE = LA.DELIVERY_PROVIDER
      WHERE LA.PERSON_CODE = PERSON_CODE
       AND LA.FUNDING_YEAR = FUND_YEAR
       AND LA.UIO_ID = OU.UIO_ID;
      

      【讨论】:

      • 对不起,我应该补充一点,WHERE 子句中的 PERSON_CODE、FUND_YEAR 和 UIO_ID 是我在包中创建的函数的参数。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多