How to fix PL/SQL: ORA-00918: column ambiguously defined in Oracle - sql

I'm creating a package in Oracle, and when I've compiled the body of the package, i am getting the PL/SQL: ORA-00918: column ambiguously defined error.
I've gone through the code, and double checked the aliases, so am a bit stumped as to why I am receiving this error.
The error in question is on Line 10.
The PERSON_CODE, FUND_YEAR and UIO_ID in the WHERE clause are the arguments on the function that I am creating in the package.
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;

Your function parameter name and the name of the field are clashing, creating a shadowing effect. You can prefix the name of the parameter with the function name to remove the ambiguity
AND LA.UIO_ID = MyfunctionName.UIO_ID;
Alternatively, rename the parameter to avoid such occurrences.

Its always good practice to use table alais with columns Names.
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;

. The PERSON_CODE, FUND_YEAR and UIO_ID are the arguments on the function.
It is bad practice to use PL/SQL parameter names which are the same as column names. The compiler applies the nearest namespace check, which means in this case it tries to map PERSON_CODE to a table column. Aliasing is optional so it doesn't realise that you're trying to reference PL/SQL parameters.
Because you have more than one table with a column called PERSON_CODE you get the ORA-00918 error. Otherwise you would just have a query which returned all rows.
The better practice is to name parameters differently; the convention is to prefix them with p_:
WHERE LA.PERSON_CODE = P_PERSON_CODE
AND LA.FUNDING_YEAR = P_FUND_YEAR
AND LA.UIO_ID = P_UIO_ID;

Alias is missing for the column UIO_ID, just provide 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;

Related

Oracle database column ambiguously defined / invalid identifier

I've tried to write a SQL statement to select from some tables. But when I run it, I get an error, and I don't know how to fix it.
When I just select from vertrag and join pgrdat, abrkreis, mandant and komm_dat, everything works fine.
However, when I try to add literal into the joins, I get the following error:
ORA-00904: "VERTRAG"."MAN" invalid identifier
on (left join literal on literal.lit_kzl = pgrdat.beruftit and literal.man = vertrag.man)
or
ORA-00918: column ambiguously defined
on (left join Literal on Literal.LIT_KZL=pgrdat.BERUFTIT and Literal.man=man)
literal.man and vertrag.man both exist.
Here's my SQL:
SELECT man,
ak,
pnr,
vertrag.vertnr,
vertrag.eintrt2,
vertrag.ma_ab,
vertrag.verbegin,
vertrag.ver_ab,
vertrag.ver_bis,
vertrag.verende,
vertrag.enlogru,
pgrdat.spr,
pgrdat.anrede,
pgrdat.auswnr,
pgrdat.beruftit,
pgrdat.daschudat,
pgrdat.fax,
pgrdat.gebdat,
pgrdat.gebname,
pgrdat.gebort,
pgrdat.geschl,
pgrdat.lnd,
pgrdat.miname,
pgrdat.namevor,
pgrdat.namezus,
pgrdat.naname,
pgrdat.ort,
pgrdat.plz,
pgrdat.plzfach,
pgrdat.postfach,
pgrdat.pst_ab,
pgrdat.pst_bis,
pgrdat.staat,
pgrdat.staat2,
pgrdat.strasse,
pgrdat.telgesch,
pgrdat.telprivat,
pgrdat.titel,
pgrdat.vorname,
pgrdat.empfaenger,
pgrdat.taetint,
pgrdat.zimmer,
pgrdat.sachbegrp,
pgrdat.logasach,
pgrdat.stellung,
pgrdat.logasach2,
pgrdat.sachbegrp2,
abrkreis.ak_bez,
abrkreis.ak_kurz,
abrkreis.ak_ort,
abrkreis.ak_plz,
abrkreis.ak_fax,
abrkreis.ak_plzfach,
abrkreis.ak_postfach,
abrkreis.ak_strasse,
abrkreis.ak_telefon,
abrkreis.ak_text,
mandant.man_bez,
mandant.man_fax,
mandant.man_firma,
mandant.man_kurz,
mandant.man_ort,
mandant.man_plzfach,
mandant.man_plzstr,
mandant.man_postfach,
mandant.man_st_nr,
mandant.man_strasse,
mandant.man_telefon,
komm_dat.km_art,
komm_dat.km_ab,
komm_dat.km_bis,
komm_dat.km_bem,
literal.lit_txt
FROM vertrag
JOIN pgrdat
USING (man, ak, pnr)
JOIN abrkreis
USING (man, ak)
JOIN mandant
USING (man)
LEFT JOIN komm_dat
USING (man, ak, pnr)
LEFT JOIN literal
ON literal.lit_kzl = pgrdat.beruftit
AND literal.man = man
WHERE superman IN ('41900', '41901', '41902', '41903')
AND literal.lit_art = 'BERUFTIT'
AND ver_ab <= trunc(SYSDATE)
AND pgrdat.pst_ab <= trunc(SYSDATE)
AND ((ver_bis >= trunc(SYSDATE) AND pgrdat.pst_bis >= trunc(SYSDATE)) OR (ver_bis IS NULL AND pgrdat.pst_bis IS NULL));
The problem is with mixing using and on join syntax. There is a third variant you didn't try:
left join Literal on Literal.LIT_KZL=pgrdat.BERUFTIT and Literal.man=komm_dat.man
which gets
ORA-25154: column part of USING clause cannot have qualifier
You can't use the unqualified man because it's ambiguous (appearing in several tables); you can't use a qualifier because it's been used in earlier using() clauses.
If it was an inner join you could change that Literal join to using (man) and move the lit_kzl check to the where clause, but as it's an outer join that won't work (or at least, would force it back to being an inner join).
You probably need to change all the other using clauses to on, unfortunately:
...
from vertrag
join pgrdat on pgrdat.man = vertrag.man and pgrdat.ak = vertrag.ak and pgrdat.pnr = vertrag.pnr
join abrkreis on abrkreis.man = vertrag.man and abrkreis.ak = vertrag.ak
join mandant on mandant.man = vertrag.man
left join komm_dat on komm_dat.man = vertrag.man and komm_dat.ak = vertrag.ak and komm_dat.pnr = vertrag.pnr
left join Literal on Literal.LIT_KZL=pgrdat.BERUFTIT and Literal.man=vertrag.man
and Literal.LIT_ART='BERUFTIT'
where ...
I've moved and Literal.LIT_ART='BERUFTIT' from the where clause into the join condition, as that would also have forced that outer join to become an inner join again.

isnull with AND : -An expression of non-boolean type specified in a context where a condition is expected, near 'and'

I am tryng to use isnull with AND operator
SELECT *
FROM contacts AS cont
LEFT JOIN contactphones AS contPhone
ON cont.contactid = contPhone.contactid
LEFT JOIN sys_phonetypedesc AS phont
ON phont.typeid = contPhone.phonetype
LEFT JOIN salutations AS tsal
ON tsal.salutid = cont.salutation
WHERE cont.contactid = '29'
AND ( Isnull(phont.typedesc, 1) )
AND ( Isnull(contPhone.phonenum, 1) )
ORDER BY phont.typedesc
but got following error
An expression of non-boolean type specified in a context where a
condition is expected, near 'and'.
I also tried using the case statement
SELECT *
FROM contacts AS cont
LEFT JOIN contactphones AS contphone
ON cont.contactid = contphone.contactid
LEFT JOIN sys_phonetypedesc AS phont
ON phont.typeid = contphone.phonetype
LEFT JOIN salutations AS tsal
ON tsal.salutid = cont.salutation
WHERE cont.contactid = '29'
AND (
CASE
WHEN phont.typedesc = NULL THEN 1
ELSE phont.typedesc
END as a)
but it is not working. I am looking for ifnull logic in MSSQL but case and if else not working correctly
please suggest
I don't think you need to use ISNULL() here, instead you are looking for IS NULL/IS NOT NULL. First let's see why you get this error message
An expression of non-boolean type specified in a context where a condition is expected, near 'and'.
You get this error because ( Isnull(phont.typedesc, 1) ) is not a boolean expression and that what the WHERE clause needs (True or False).
eg: Let's assume phont IS NULL, then ISNULL() will return 1, so you are writing cont.contactid = '29' AND 1 AND ....
What should I do then to get ride of this error?
Just make it a boolean expression as Isnull(phont.typedesc, 1) = 1 or what ever you want instead of =1, it maybe other too because it's not clear what you need to check.
Now, the use of ISNULL() as I seeis point less, cause the possible cases I can see is like the follow:
Isnull(phont.typedesc, 1) = 1 then directly phont IS NULL.
Isnull(phont.typedesc, 1) <> 1 then directly phont IS NOT NULL.
Isnull(phont.typedesc, 1) = AnyValue then why not directly phont = value or phont IN(<Values>) if you are looking for more than 1 value.
You're not comparing the result of isnull to anything in your where clause.
(isnull(phont.TypeDesc,1))
gives you either the TypeDesc, or if it's null gives you 1, but then you move directly onto an AND statement. In other words, if all relevant fields are null, what you'd be trying to do is:
where cont.ContactID = '29' and 1 and 1
You either have the isnull in the wrong place (if you want see it in your selected fields), or you forgot to compare it to something.
If you want to select rows where those fields are actually null then what you want is:
where cont.ContactID = '29'
and phont.TypeDesc is null
and contPhone.PhoneNum is null
select * from contacts as cont left join ContactPhones as contPhone on cont.ContactID=contPhone.ContactID
left join SYS_PhoneTypeDesc as phont on
phont.TypeID = contPhone.PhoneType
left join SALUTATIONS as tsal on tsal.salutid = cont.Salutation where cont.ContactID = '29' and (isnull(phont.TypeDesc,1))=check what u want here
and (isnull(contPhone.PhoneNum,1))=check what u want here enter code here
order by
phont.TypeDesc
Isnull(contPhone.phonenum,1) return 1 when your contPhone.phonenum value will be null else it will return that column value but the point is you got error because you have not used any comparison value as a result it thrown error
Your condition will be like below
Where contactId=29 and isnull(phonenum,1)= // any value

Can't pinpoint error near the LIKE keyword

I'm running into an error with a sql inquery near my LIKE statement. Am I formatting the LIKE clause incorrectly within the WHEN clause of a CASE? Here is the code.
SELECT
substring (Cases.FileNumber,4,6) AS [FileNumber]
,Charge.ChargeCode
,Cases.BookedLastName
,Cases.BookedFirstName
,Cases.ArrestDate
,Cases.BookedDOB
,Cases.BookedAge
,Charge.OffenseToDate
,Cases.BookedRace
,Cases.BookedSex
,Charge.OffenseStreetAddress1
,Charge.OffenseCity
,Charge.OffenseState
,Charge.OffenseZipCode
,Charge.ChargeDescription
,(SELECT CASE
WHEN charge1.ChargeDescription LIKE N'%heroin%' THEN 'Heroin'
ELSE 'Not Heroin'
END
FROM tblCsCharge AS charge1
INNER JOIN tblCsCases AS cases1
ON charge1.FileNumber = cases1.FileNumber
WHERE
charge1.BookedLastName = cases1.BookedLastName
AND charge1.BookedLastName = cases1.BookedLastName
AND charge1.BookedDOB = Cases.BookedDOB
AND cases2.ChargeCode IN (N'579.015-001Y201735')) AS HeroinYN
FROM
tblCsCases AS Cases
INNER JOIN tblCsCharge AS Charge
ON Cases.FileNumber = Charge.FileNumber
WHERE Cases.IssuedDate >= 01/01/2017
AND
Cases.IssuedDate <= #EndDate
AND
Charge.ChargeCode IN (N'579.015-001Y201735')
AND
Cases.BookedLastName NOT IN (N'Bogus')
ORDER By
Cases.BookedLastName
This is a sub-query within a bigger query focused on building a column that will simply output Heroin or Not Heroin based off of a large text field in our database.
EDITs:
Despite the changes that should make the code compile, the following error now occurs:
Invalid column name 'BookedLastName'.
Invalid column name 'BookedLastName'.
Invalid column name 'BookedDOB'.
The multi-part identifier "cases2.ChargeCode" could not be bound.
You have two errors in your code, both of which were pointed out, though not in the same answer.
Your case statement should be without the column name in parenthesis - I commented it out in the copy of your code below)
You're missing a closing parenthesis at the end of the query, right before the alias - I added it below.
.
,(SELECT CASE--(charge1.ChargeDescription)
WHEN charge1.ChargeDescription LIKE N'%heroin%' THEN 'Heroin'
ELSE 'Not Heroin'
END
FROM tblCsCharge AS charge1
INNER JOIN tblCsCases AS cases1
ON charge1.FileNumber = cases1.FileNumber
WHERE
charge1.BookedLastName = cases1.BookedLastName
AND charge1.BookedLastName = cases1.BookedLastName
AND charge1.BookedDOB = Cases.BookedDOB
AND cases2.ChargeCode IN (N'579.015-001Y201735')) AS HeroinYN
This seems to be the issue..
AND cases2.ChargeCode IN (N'579.015-001Y201735') AS HeroinYN
Since this is part of a sub-query, you need another parenthese
AND cases2.ChargeCode IN (N'579.015-001Y201735')) AS HeroinYN
ALSO
You can't put the column name after a CASE statement when you are using an equality operator.
This is acceptable
select
case columnName
when 'X' then 1
when 'Y' then 0
end
This is not
select
case columnName
when = 'X' then 1
when columnName like '%Y%' then 0
end
CORRECTED SCRIPT
,(SELECT CASE
WHEN charge1.ChargeDescription LIKE N'%heroin%' THEN 'Heroin'
ELSE 'Not Heroin'
END
FROM tblCsCharge AS charge1
INNER JOIN tblCsCases AS cases1
ON charge1.FileNumber = cases1.FileNumber
WHERE
charge1.BookedLastName = cases1.BookedLastName
AND charge1.BookedLastName = cases1.BookedLastName
AND charge1.BookedDOB = Cases.BookedDOB
AND cases2.ChargeCode IN (N'579.015-001Y201735')) AS HeroinYN
The proper syntax for that is:
CASE
WHEN charge1.ChargeDescription LIKE N'%heroin%' THEN 'Heroin'
ELSE 'Not Heroin'
END
Don't put the field name after CASE in this syntax.

Invalid Column after Renaming

I have a nested SQL statement. In the inner SQL statement I rename a column like this: b."MANDT" b_MANDT. In the outer statement I try something similar: a."b_MANDT" a_b_MANDT.
But I'm getting the error message that this is an invalid column name, why?
SAP DBTech JDBC: [260]: invalid column name: A.b_MANDT: line 1 col 43 (at pos 42)
Original SQL Statement:
SELECT a."MANDT", a."VBELN", a."POSNR", a."b_MANDT" a_b_MANDT, a."b_VBELN" a_b_VBELN, a."VPOSN" a_VPOSN, b."MANDT" b_MANDT, b."VBELN" b_VBELN, b."VPOSN"
FROM (
SELECT a."MANDT", a."VBELN", a."POSNR", b."MANDT" b_MANDT, b."VBELN" b_VBELN, b."VPOSN"
FROM "SAP_ECC".VBAP a
LEFT JOIN "SAP_ECC".VEDA b ON a.MANDT = b.MANDT AND a.VBELN = b.VBELN AND a.POSNR = b.VPOSN
) a
LEFT JOIN "SAP_ECC".VEDA b ON a.MANDT = b.MANDT AND a.VBELN = b.VBELN AND a.VPOSN = b.VPOSN
Try changing b."MANDT" b_MANDT to b."MANDT" "b_MANDT".
Not sure what DB you are using, but typically, unless quoted, the alias defaults to upper-case yet you are trying to reference it as mixed-case.

ORA-00904 on join

I am trying to create the following view:
CREATE OR REPLACE VIEW AlbumDistribution AS
SELECT Album.Album_ID,
Album.title,
HasTrack.tracked,
FinishedTrack.released_title,
SUBSTR(Album.Album_ID, -1) is_distributed_as
FROM Album A
JOIN HasTrack HT
ON HT.Album_ID = A.Album_ID
JOIN FinishedTrack FT
ON HasTrack.OriginatesFrom = FT.OriginatesFrom
AND HasTrack.tracked = FT.version;
but I get the ORA-00904 error:
ERROR at line 6:
ORA-00904: "HASTRACK"."TRACKED": invalid identifier
Which I find very confusing, as I reference HasTrack.tracked before and there's no error. If I change the order of the statements, putting HasTrack.OriginatesFrom = FT.OriginatesFrom last then I get the same error but for HasTrack.OriginatesFrom.
You define an alias for this and other tables. You need to use the alias throughout the query:
CREATE OR REPLACE VIEW AlbumDistribution AS
SELECT A.Album_ID, A.title, HT.tracked,
FT.released_title, SUBSTR(A.Album_ID, -1) is_distributed_as
FROM Album A JOIN
HasTrack HT
ON HT.Album_ID = A.Album_ID JOIN
FinishedTrack FT
ON HT.OriginatesFrom = FT.OriginatesFrom AND
HT.tracked = FT.version;