The multi-part identifier "tablename.column " could not be bound - sql

When I used this query above exception has thrown
SELECT FINQDET.InquiryNo,FINQDET.Stockcode,FINQDET.BomQty,FINQDET.Quantity,FINQDET.Rate,FINQDET.Required,FINQDET.DeliverTo,FSTCODE.TitleA AS FSTCODE_TitleA ,FSTCODE.TitleB AS FSTCODE_TitleB,FSTCODE.Size AS FSTCODE_Size,FSTCODE.Unit AS FSTCODE_Unit, FINQSUM.TITLE AS FINQSUM_TITLE,FINQSUM.DATED AS FINQSUM_DATED
FROM FINQSUM , FINQDET left outer join [Config]..FSTCODE ON FINQDET.Stockcode=FSTCODE.Stockcode
WHERE FINQDET.InquiryNo=FINQSUM.INQUIRYNO
ORDER BY FINQDET.Stockcode,FINQDET.InquiryNo
but if I used below query problem solved,
SELECT FINQDET.InquiryNo,FINQDET.Stockcode,FINQDET.BomQty,FINQDET.Quantity,FINQDET.Rate,FINQDET.Required,FINQDET.DeliverTo,FSTCODE.TitleA AS FSTCODE_TitleA ,FSTCODE.TitleB AS FSTCODE_TitleB,FSTCODE.Size AS FSTCODE_Size,FSTCODE.Unit AS FSTCODE_Unit,
FINQSUM.TITLE AS FINQSUM_TITLE,FINQSUM.DATED AS FINQSUM_DATED
FROM FINQSUM As FINQSUM , FINQDET As FINQDET left outer join [Config]..FSTCODE As FSTCODE ON FINQDET.Stockcode=FSTCODE.Stockcode
HERE FINQDET.InquiryNo=FINQSUM.INQUIRYNO
ORDER BY FINQDET.Stockcode,FINQDET.InquiryNo
Please can you explain Why using Alias better than using actual table names

The table [Config]..FSTCODE is qualified with database name which works fine if you use alias. Otherwise you need to qualify full name as it is from different database

Looks like FSTCODE is a table in a different DB. In the first query, though the JOIN uses the DB name to identify the table, the ON statement does not. The second statement adresses this by using an ALIAS
You can also modify the first statement as
left outer join [Config]..FSTCODE
ON FINQDET.Stockcode=[Config]..FSTCODE.Stockcode

An alias allows you to reference a set without using the fullname. It saves you typing and allows you to express contextual information to the reader.

Related

Is this the table name?

I'm trying to learn SQL queries, and I've encountered things like this:
SELECT name FROM customer_list t
WHERE ...
What does the t mean? Is it like the name of an instance of that table?
Thanks!
The t is an alias that you can refer to instead of the table name in your query. If you have only one table you're querying from it isn't very useful, but it comes in hand when you have multiple tables (e.g., in join clauses and you want to avoid writing the entire long table name whenever you refer to it. E.g.:
SELECT t.name
FROM some_long_table_name t
JOIN some_other_long_table_name s ON t.id = s.id

Shorten the table names

I am using SQL Server and wondering if it's possible to shorten the table names. For example, my current SQL syntax is:
SELECT
t.Titlename
FROM [dbo].[Order] o
JOIN [dbo].[Title] t ON o.titleid=t.TitleId
However, if I just try doing select titlename from order I get an error. Why is this so? What would be the 'shortest' tablename I could reference; and why is it requiring the [dbo] namespace?
It doesn't require the [dbo] namespace, assuming that is the currently selected database. But it does require the Title table to be joined to Order to get the Titlename column:
SELECT
t.Titlename
FROM [Order] o
JOIN Title t ON o.titleid=t.TitleId
Demo on SQLFiddle
Note that Order must be enclosed in [] because it is an SQL reserved keyword.
It's also worth noting the point that is made in the article #GregLow mentions, which indicates that queries cannot be reused if object name resolution needs to occur. So it would generally be preferred to write the query as you originally did.
If your currently selected database be dbo, then it shouldn't be necessary to use the fully qualified object name. However, you have another problem, because ORDER is a reserved SQL Server keyword. The following should work:
SELECT t.Titlename
FROM [Order] o
INNER JOIN [Title] t
ON o.titleid = t.TitleId;
Here, using [Order] instead of Order counts as escaping that table name.

Getting value from a table and add value from table 2 if excist

I'm new to SQL and im wondering if something like this is possible.
It's probably a super simple solution but i cant seem to solve it. I'm using an Oracle database.
Employee_Table:
employeeNr
username
address
epost
Computer_Table:
employeeNr
ComputerNumber
ComputerUpdated
When I'm using
SELECT *
From Employee_Table,
Computer_Table
WHERE Employee_Table.EmployeeNr = Computer_Table.EmployeeNr
AND Employee_Table.username LIKE ('%SomeUsername%')
When I'm using this sqlstring I only get users with computers. I would like to get all users and the computers of those who has one.
Now the million dollar question. What modifications do I need to make?
Never use commas in the FROM clause. Always use explicit JOIN.
In this case, you want a LEFT JOIN:
SELECT *
FROM Employee_Table e LEFT JOIN
Computer_Table c
ON c.EmployeeNr = c.EmployeeNr
WHERE e.username LIKE '%SomeUsername%';
When you use LEFT JOIN, conditions on the first table go on the WHERE clause. Conditions on the second table go in the ON clause.

Mixing "USING" and "ON" in Oracle ANSI join

I wrote an Oracle SQL expression like this:
SELECT
...
FROM mc_current_view a
JOIN account_master am USING (account_no)
JOIN account_master am_loan ON (am.account_no = am_loan.parent_account_no)
JOIN ml_client_account mca USING (account_no)
When I try to run it, Oracle throws an error in the line with "ON" self-join saying: "ORA-25154: column part of USING clause cannot have qualifier".
If I omit the "am" qualifier, it says: "ORA-00918: column ambiguously defined".
What's the best way to resolve this?
The error message is actually (surprise!) telling you exactly what the problem is. Once you use the USING clause for a particular column, you cannot use a column qualifier/table alias for that column name in any other part of your query. The only way to resolve this is to not use the USING clause anywhere in your query, since you have to have the qualifier on the second join condition:
SELECT
...
FROM mc_current_view a
JOIN account_master am ON (a.account_no = am.account_no)
JOIN account_master am_loan ON (am.account_no = am_loan.parent_account_no)
JOIN ml_client_account mca ON (a.account_no = mca.account_no);
My preference is never to use USING; always use ON. I like to my SQL to be very explicit and the USING clause feels one step removed in my opinion.
In this case, the error is coming about because you have account_no in mc_current_view, account_master, and ml_client_account so the actual join can't be resolved. Hope this helps.
The using is cleaner (imo) but it is still desirable to externally refererence the join fields as in the org example or an example like this:
select A.field,
B.field,
(select count(C.number)
from tableC C
where C.join_id = join_id -- wrong answer w/o prefix, exception with.
) avg_number
from tableA A
join tableB B using (join_id);
It gives the wrong answer because the join_id within the subquery implies C.join_id (matching all records) rather than A or B. Perhaps the best way to resolve might be just to allow explicit references with using, having the best of both worlds. Seems like there is a need because of cases like these.

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.