Oracle [Error] Execution (31: 5): ORA-00904: invalid identifier - sql

I have written the following query
SELECT TPD.*,
FMP.*
FROM TABLE TPD
LEFT JOIN
(SELECT *
FROM TBL FMP
WHERE FMP.FE6_MILEPOST_SEQ_I = 0)
ON FMP.FE6_MILEPOST_I = TPD.CURR_STATION_MP_I
The two sub queries inside works separately but when joined, it throws the following error
[Error] Execution (31: 5): ORA-00904: "FMP"."FE6_MILEPOST_I": invalid identifier

You have to alias your derived table, e.g. like this:
(SELECT FMP.FE6_MILEPOST_I,
FMP.OPERATIONAL_REGION_C,
FMP.OPERATIONAL_REGION_N,
FMP.OPERATING_ZONE_C,
FMP.OPERATING_ZONE_N,
FMP.OPERATING_SUBDIVISION_C,
FMP.OPERATING_SUBDIVISION_N
FROM TBL FMP
WHERE FMP.FE6_MILEPOST_SEQ_I = 0) FMP
The FMP alias that you gave your TBL within the derived table does not "escape" the derived table's nested namespacing scope. I.e. you cannot "see" that table name from outside. Without giving the derived table any name, you can only reference its projected columns without qualification.
Notice that Oracle is one of the few databases that actually allow you to skip aliasing derived tables in the first place, for quick and dirty querying. Even so, I recommend you always alias your derived tables, even in Oracle.

The subquery needs an alias, so you can refer to columns it returns in the outer query.
But here, I would suggest simplifying the FROM clause. Using a subquery does not see useful anyway, so you could just go:
SELECT ...
FROM TABLE TPD
LEFT JOIN TBL FMP
ON FMP.FE6_MILEPOST_SEQ_I = 0
AND FMP.FE6_MILEPOST_I = TPD.CURR_STATION_MP_I

Related

# of columns in two selected tables or a query of a union query do not match

I have a simple qry that give me error
SELECT *
FROM qry_ExecSum
inner join qry_IDS_IT_Everything on qry_ExecSum.P_Code = qry_IDS_IT_Everything.P_Code
It works good If change the * to column names like this :
SELECT qry_ExecSum.P_Code
FROM qry_ExecSum
inner join qry_IDS_IT_Everything on qry_ExecSum.P_Code = qry_IDS_IT_Everything.P_Code
All individual queries run good!!
Hope you are receiving error The multi-part identifier could not be bound, since both tables have the column named P_Code.
To avoid this you can specify the table name or table alias infront of the column name in the SELECT. That is the reason the second query doesn't return the error.

What table will be taken if table alias is not provided?

I am analyzing one SQL statement and there is something with regard to aliases what isn't really clear to me, so I would like to ask if someone can try to explain it. So, this is how the statement looks like
SELECT
a.RecordID
, a.Account
, b.RecordID
, c.SomeField as AlternativeFieldName
FROM TableA a
LEFT JOIN TableB b
ON a.RecordID=b.RecordID
LEFT JOIN TableC c
ON b.RecordID=c.RecordID
WHERE a.DayFrom >= YYYYMMDD and a.DayFrom < YYYYMMDD
AND b.Field1 is null
AND Field2 = 'SOME_VALUE'
as you can see aliases are provided for all three tables in the statement and used always in data selection as well as joins, however in the where clause there is one field from one of the tables above for which an alias is not provided. I wonder it this is correct and if it is what does SQL take as a source table or does it throw an error if it is not?
On this page, I've tried something similar and it actually worked, although I've expected some error. I thought that SQL forces you to used aliases if joining multiple tables. Here is the statement
SELECT *
FROM Customers c
JOIN Orders o
ON c.CustomerID = o.CustomerID
WHERE OrderDate = '1996-07-04'
Thx in advance, cheers!
If SQL Server (or any database) finds an unqualified column name, then it looks to see which tables/subqueries in the FROM clause or outer queries might be providing it.
If the column is in exactly one table/subquery in the FROM clause, then the column is assumed to come from the table/subquery.
If the column is in multiple tables/subqueries in the FROM clause, then the query returns an error.
If the column does not exist in the FROM clause nor in any outer queries, the query returns an error.
If the column does not exist in the FROM clause, but does in an outer query, then that reference is used.
These rules go by the name "scoping". That is a common term in computer languages for figuring out the value of a variable.
No error will be raised for unqualified column names as long as the column name is not ambiguous. In the case of ambiguous names, the column name must be qualified with the table name or alias to avoid an error.
Note there is also the notion of scope that can become an issue when column names are not qualified. Consider this construct:
WHERE b.Field3 IN(
SELECT Field4
FROM TableD
)
If Field4 exists in TableD, the desired results will be returned. But if Field4 does not exist in TableD but exists in one of the outer tables, the predicate will be true for all outer rows when the Field4 value is not NULL and at least one row exists in TableD.
In short, the best practice is to qualify column names in multi-table queries.
Any RDBMS executing the sql queries with joins will try to find column names from all referenced tables. If it finds only one column with that name simply executes the query otherwise throughs ambiguity error. Alias names will be used to avoid ambiguity.

SQL Change View Name / Joins

I am trying to join two views I created, however I am joining them using their common field (cAuditNumber).
The issue is, once I have done the joins, it will not let me create the view as it cannot have the field name cAuditNumber twice.
Is the cAuditNumber the PK I should use?
How do I correct this and still join the tables?
CREATE VIEW KFF_Sales_Data_Updated AS
SELECT CustSalesUpdated.*, StkSalesUpdated.*
FROM CustSalesUpdated
INNER JOIN StkSalesUpdated
ON StkSalesUpdated.cAuditNumber = CustSalesUpdated.cAuditNumber
I get the following error:
Msg 4506, Level 16, State 1, Procedure KFF_Sales_Data_Updated, Line 2
Column names in each view or function must be unique. Column name 'cAuditNumber' in view or function 'KFF_Sales_Data_Updated' is specified more than once.
Substitute your own column names instead of ColumnA, Column B, etc, but it should follow this format:
CREATE VIEW KFF_Sales_Data_Updated AS
SELECT CustSalesUpdated.cAuditNumber
,CustSalesUpdated.ColumnA
,CustSalesUpdated.ColumnB
,CustSalesUpdated.ColumnC
,StkSalesUpdated.ColumnA as StkColumnA
,StkSalesUpdated.ColumnB as StkColumnB
,StkSalesUpdated.ColumnC as StkColumnC
FROM CustSalesUpdated
INNER JOIN StkSalesUpdated
ON StkSalesUpdated.cAuditNumber = CustSalesUpdated.cAuditNumber
You only have to alias duplicate columns using "as", or you can use it to rename any column that you so desire.
CREATE VIEW KFF_Sales_Data_Updated AS
SELECT csu.cAuditNumber cAuditNumber1 , ssu.cAuditNumber cAuditNumber2
FROM CustSalesUpdated csu
INNER JOIN StkSalesUpdated ssu
ON StkSalesUpdated.cAuditNumber = CustSalesUpdated.cAuditNumber
You could add any other column in the select statement from the two tables but if there are two column with the same name you should give them aliases
Using select * is a bad practice in general. On the other hand, it is a good practice to alias your table names and columns. Especially in your case, your table names as well as your same columns name(across two tables) could use aliases. The database is confused as to which cAuditNumber is coming from where. So, alias comes in handy.
CREATE VIEW KFF_Sales_Data_Updated
AS
SELECT
csu.cAuditNumber
,csu.Col1
,csu.Col2
,csu.Col3
,ssu.Col1 AS StkCol1
,ssu.Col2 AS StkCol2
,ssu.Col3 AS StkCol3
FROM CustSalesUpdated csu
INNER JOIN StkSalesUpdated ssu ON csu.cAuditNumber = ssu.cAuditNumber

error when joining 2 tables

Query :
select i.Name,ri.Country,ri.State,ri.City
from Information as i
join ResidenceInformation as ri
order by Name
The error that i get is :
Error code -1, SQL state 42X01: Syntax error: Encountered "order" at line 4, column 5.
Line 1, column 1
Execution finished after 0 s, 1 error(s) occurred.
Why am i getting an error ?
The error is because you forgot to specify JOIN criteria, like this:
SELECT i.Name, ri.Country, ri.State, ri.City
FROM Information as i
JOIN ResidenceInformation as ri ON ri.column = i.column
ORDER BY Name
You need to replace column with the names of the appropriate columns that link the tables correctly for the output you need.
You should also specify the table alias in your ORDER BY, to protect against an ambiguous column reference error.
You get an error because your syntax is wrong: after join there needs to be on, like this:
select i.Name,ri.Country,ri.State,ri.City
from Information as i
join ResidenceInformation as ri
on ri.info_id=i.id -- <<< Added a join condition
order by Name
SQL needs to know how to "link up" the rows of the table that you are joining to the row(s) of the other table(s) in the query. I am assuming that ResidenceInformation has a foreign key into Information called info_id.
If the Name is present in both ResidenceInformation and Information, you need to prefix it with the table name or an alias. In fact, it's a good idea to do it anyway for added clarity.
I think you may have forgot to tell the join clause which columns to join against. You need to tell the database how these 2 tables connect to each other. Something like ON i.id = ri.InformationId
select i.Name,ri.Country,ri.State,ri.City
from Information as i
join ResidenceInformation as ri ON i.id = ri.InformationId
order by i.Name
Also, you may need the table alias in the order by clause, which I've added as well.

Ambiguity in Left joins (oracle only?)

My boss found a bug in a query I created, and I don't understand the reasoning behind the bug, although the query results prove he's correct. Here's the query (simplified version) before the fix:
select PTNO,PTNM,CATCD
from PARTS
left join CATEGORIES on (CATEGORIES.CATCD=PARTS.CATCD);
and here it is after the fix:
select PTNO,PTNM,PARTS.CATCD
from PARTS
left join CATEGORIES on (CATEGORIES.CATCD=PARTS.CATCD);
The bug was, that null values were being shown for column CATCD, i.e. the query results included results from table CATEGORIES instead of PARTS.
Here's what I don't understand: if there was ambiguity in the original query, why didn't Oracle throw an error? As far as I understood, in the case of left joins, the "main" table in the query (PARTS) has precedence in ambiguity.
Am I wrong, or just not thinking about this problem correctly?
Update:
Here's a revised example, where the ambiguity error is not thrown:
CREATE TABLE PARTS (PTNO NUMBER, CATCD NUMBER, SECCD NUMBER);
CREATE TABLE CATEGORIES(CATCD NUMBER);
CREATE TABLE SECTIONS(SECCD NUMBER, CATCD NUMBER);
select PTNO,CATCD
from PARTS
left join CATEGORIES on (CATEGORIES.CATCD=PARTS.CATCD)
left join SECTIONS on (SECTIONS.SECCD=PARTS.SECCD) ;
Anybody have a clue?
Here's the query (simplified version)
I think by simplifying the query you removed the real cause of the bug :-)
What oracle version are you using? Oracle 10g ( 10.2.0.1.0 ) gives:
create table parts (ptno number , ptnm number , catcd number);
create table CATEGORIES (catcd number);
select PTNO,PTNM,CATCD from PARTS
left join CATEGORIES on (CATEGORIES.CATCD=PARTS.CATCD);
I get ORA-00918: column ambiguously defined
Interesting in SQL server that throws an error (as it should)
select id
from sysobjects s
left join syscolumns c on s.id = c.id
Server: Msg 209, Level 16, State 1, Line 1
Ambiguous column name 'id'.
select id
from sysobjects
left join syscolumns on sysobjects.id = syscolumns.id
Server: Msg 209, Level 16, State 1, Line 1
Ambiguous column name 'id'.
From my experience if you create a query like this the data result will pull CATCD from the right side of the join not the left when there is a field overlap like this.
So since this join will have all records from PARTS with only some pull through from CATEGORIES you will have NULL in the CATCD field any time there is no data on the right side.
By explicitly defining the column as from PARTS (ie left side) you will get a non null value assuming that the field has data in PARTS.
Remember that with LEFT JOIN you are only guarantied data in fields from the left table, there may well be empty columns to the right.
This may be a bug in the Oracle optimizer. I can reproduce the same behavior on the query with 3 tables. Intuitively it does seem that it should produce an error. If I rewrite it in either of the following ways, it does generate an error:
(1) Using old-style outer join
select ptno, catcd
from parts, categories, sections
where categories.catcd (+) = parts.catcd
and sections.seccd (+) = parts.seccd
(2) Explicitly isolating the two joins
select ptno, catcd
from (
select ptno, seccd, catcd
from parts
left join categories on (categories.CATCD=parts.CATCD)
)
left join sections on (sections.SECCD=parts.SECCD)
I used DBMS_XPLAN to get details on the execution of the query, which did show something interesting. The plan is basically to outer join PARTS and CATEGORIES, project that result set, then outer join it to SECTIONS. The interesting part is that in the projection of the first outer join, it is only including PTNO and SECCD -- it is NOT including the CATCD from either of the first two tables. Therefore the final result is getting CATCD from the third table.
But I don't know whether this is a cause or an effect.
I'm afraid I can't tell you why you're not getting an exception, but I can postulate as to why it chose CATEGORIES' version of the column over PARTS' version.
As far as I understood, in the case of left joins, the "main" table in the query (PARTS) has precedence in ambiguity
It's not clear whether by "main" you mean simply the left table in a left join, or the "driving" table, as you see the query conceptually... But in either case, what you see as the "main" table in the query as you've written it will not necessarily be the "main" table in the actual execution of that query.
My guess is that Oracle is simply using the column from the first table it hits in executing the query. And since most individual operations in SQL do not require one table to be hit before the other, the DBMS will decide at parse time which is the most efficient one to scan first. Try getting an execution plan for the query. I suspect it may reveal that it's hitting CATEGORIES first and then PARTS.
I am using Oracle 9.2.0.8.0. and it does give the error "ORA-00918: column ambiguously defined".
This is a known bug with some Oracle versions when using ANSI-style joins. The correct behavior would be to get an ORA-00918 error.
It's always best to specify your table names anyway; that way your queries don't break when you happen to add a new column with a name that is also used in another table.
It is generally advised to be specific and fully qualify all column names anyway, as it saves the optimizer a little work. Certainly in SQL Server.
From what I can gleen from the Oracle docs, it seems it will only throw if you select the column name twice in the select list, or once in the select list and then again elsewhere like an order by clause.
Perhaps you have uncovered an 'undocumented feature' :)
Like HollyStyles, I cannot find anything in the Oracle docs which can explain what you are seeing.
PostgreSQL, DB2, MySQL and MSSQL all refuse to run the first query, as it's ambiguous.
#Pat: I get the same error here for your query. My query is just a little bit more complicated than what I originally posted. I'm working on a reproducible simple example now.
A bigger question you should be asking yourself is - why do I have a category code in the parts table that doesn't exist in the categories table?
This is a bug in Oracle 9i. If you join more than 2 tables using ANSI notation, it will not detect ambiguities in column names, and can return the wrong column if an alias isn't used.
As has been mentioned already, it is fixed in 10g, so if an alias isn't used, an error will be returned.