Cannot assign the second sql alias - sql

I am having difficulties getting my second alias to work in the example below.
I'm using Squirrel SQL 3.7
Getting an error
Error: [SQL5001] Column qualifier or table T2 undefined. SQLState:
42703 ErrorCode: -5001
UPDATE myDatabaseOne.myTableOne t1
SET
firstFieldToCopy = (SELECT DISTINCT alternateField FROM myDatabaseTwo.myTableTwo t2)
WHERE t1.firstFieldToCopy = t2.alternateField;

Did you mean...
UPDATE myDatabaseOne.myTableOne t1
SET firstFieldToCopy = (SELECT DISTINCT alternateField
FROM myDatabaseTwo.myTableTwo t2
WHERE t1.firstFieldToCopy = t2.alternateField);
Note the position of the ) ... This is why the t2 alias didn't work...
Otherwise the query is confusing as to your intent.

UPDATE t1
SET t1.firstfieldtocopy = t2.alternatefield
FROM mydatabaseone.mytableone t1
JOIN mydatabasetwo.mytabletwo t2 on t1.firstfieldtocopy = t2.alternate field
I don't understand your logic though.. Setting copy = alternate but you're filtering to where copy = alternate already.

The issue is with scoping. t2 is only accessible within
(SELECT DISTINCT alternateField FROM myDatabaseTwo.myTableTwo t2)
which means that when you say WHERE t1.firstFieldToCopy = t2.alternateField your DBMS has no clues what you're referring to.
There are still 2 issues to the query though :
Your subquery most probably returns 2+ values since DISTINCT isn't used to return a single value, but to eliminate duplicates.
You're overriding old values with identical new values (see Aaron D's answer).

Related

SQL - Update table values from values in another table

I have a select statement that is showing me all the data from table original every time it does not match the values on table real_values.
So every time it does not match, instead of showing me which routes have the wrong values for capacity, I would like the query to update it with the correct values.
Here is a shorter version to use as an example:
http://sqlfiddle.com/#!4/6a904/1
Instead of being a select statement, how could I just update the values? I have tried some things I've seen online but nothing seems to work.
#DavidFaber's answer is how most people would do this. However, for this kind of query, I prefer to use merge over update:
MERGE INTO original o
USING real_values rv
ON (o.origin = rv.origin AND o.destination = rv.destination)
WHEN MATCHED THEN
UPDATE SET
o.capacity_wt = rv.capacity_wt, o.capacity_vol = rv.capacity_vol
WHERE o.capacity_wt != rv.capacity_wt
OR o.capacity_vol != rv.capacity_vol
(It was unclear to me from your question whether you want to update original or real_values, so I chose one. If I got this wrong, reversing it should be trivial.)
I find merge more readable and easier to use when you want to update multiple columns.
The usual form of such an update query in Oracle is the following:
UPDATE table1 t1
SET t1.value = ( SELECT t2.value FROM table2 t2
WHERE t2.key = t1.key )
WHERE EXISTS ( SELECT 1 FROM table2 t2
WHERE t2.key = t1.key );
I'm confused though. You've tagged this question oracle and sql-server but your fiddle link uses MySQL.
In SQL Server, you would do this
update original set capacity_wt=b.capacity_wt,capacity_vol=b.capacity_vol
from original a, real_values b
where a.origin = b.origin
and a.destination = b.destination
and (a.capacity_wt != b.capacity_wt
or b.capacity_vol != b.capacity_vol);

Is EXISTS clause supported by DBISAM's sql engine?

Strangely, it seems that the EXISTS clause is not supported by DBISAM's sql engine, as it's always resulting in an SQL error. The following is a sample where EXISTS is being used. Am i missing anything here?
update Table1 set HASXACTION = False
WHERE EXISTS (SELECT SERIALID
From Table2
LEFT JOIN Table1 ON (Table2 .AUXILACT = Table1 .CODE)
AND (Table2 .CHARTACT = Table1 .CHARTACT) )
Never mind people, i just learned that DBISAM does not support EXISTS operator for specifying sub-select predicates in WHERE clauses. It's documented within DBISAM's help file(screenshot attached).
I presume that you don't really want the join in the subquery. You probably intend a correlated subquery:
UPDATE Table1
SET HASXACTION = False
WHERE EXISTS (SELECT SERIALID
FROM Table2
WHERE Table2.AUXILACT = Table1.CODE AND Table2.CHARTACT = Table1.CHARTACT
);
This should also fix the problem you are having, which is the reference to Table1 both in the update clause and the subquery. (This is a MySQL limitation.)
EDIT:
I cannot find any reference to EXISTS (or even subqueries) for dbisam. But, you can do updates with joins, so this should be equivalent:
UPDATE Table1
SET HASXACTION = False
FROM Table1 JOIN
Table2
ON Table2.AUXILACT = Table1.CODE AND Table2.CHARTACT = Table1.CHARTACT;
As you've already found, you can do it with the IN. However, there is a limitation that IN can only work with one field. So you can get around it by concatenating two fields to make expressions that fit the criteria. One for the inner, and one for the outer.
update Table1 set HASXACTION = False
WHERE Code+'.'+CHARTACT IN
(
SELECT AUXILACT+'.'+CHARTACT From Table2
)

Why does Oracle SQL update query return "invalid identifier" on existing column?

I have an update query for an Oracle SQL db. Upon execution the query returns ORA-00904: "t1"."sv_id": invalid identifier
So, why do I get an "invalid identifier" error message although the column exists?
Here is the complete query (replaced actual table and column names by dummies in np++)
UPDATE table_1 t1 SET (type) =
CASE
WHEN
((SELECT COUNT(dateCheck.id) FROM table_2 dateCheck
WHERE dateCheck.s_id = t1.s_id AND dateCheck.sv_id = t1.sv_id) = 0)
THEN
(SELECT sv.type FROM table_3 sv WHERE sv.id = t1.sv_id)
ELSE
(SELECT type FROM
(SELECT d.type as type FROM table_2 d
WHERE d.s_id = t1.s_id AND d.sv_id = t1.sv_id
ORDER BY d.creationTimestamp ASC)
WHERE ROWNUM = 1)
END
Now I don't understand why that error occurs.
Here is what I already know:
The Queries in the CASE statement work when executed separately, provided they are wrapped into a query that provides table_1 t1 for sure.
t1.s_id seems to work since oracle doesn't complain about that. When i change it to a column that really doesn't exist, oracle starts complaining about that non existent column before returning something about t1.sv_id. So somehow the alias might work, although I'm not sure about it.
I'm 100% sure that the column t1.sv_id exists and no typo was made. Executed a query on t1 directly and doublechecked everything in notepad by marking all occurences.
An (completely unrelated) update query like the following works as well (note the alias t1 is used in the select query). Don't assume table_1/2 to be the same as in the update query above, just reused the names. This should just illustrate that I successfully used an alias in an update query before.
update table_1 t1 set (t2_id) = (select id from table_2 t2 where t1.id = t2.t1_id)
UPDATE
Thx a lot for pointing me to the "you don't have access to alises in deeper suquery layers" issue. That got me on track again pretty fast.
So here is the query I ended up with. This seems to work fine. Eliminates the acces to t1 in the deeper layers and selects the oldest row, so that the same result should be returned from the query I expected from the original query in the ELSE part.
UPDATE table_1 t1 SET (type) =
CASE
WHEN
((SELECT COUNT(dateCheck.id) FROM table_2 dateCheck
WHERE dateCheck.s_id = t1.s_id AND dateCheck.sv_id = t1.sv_id) = 0)
THEN
(SELECT sv.type FROM table_3 sv WHERE sv.id = t1.sv_id)
ELSE
(SELECT d.type as type FROM table_2 d
WHERE d.s_id = t1.s_id
AND d.sv_id = t1.sv_id
AND d.creation = (SELECT MIN(id.creation) FROM table_2 id
WHERE d.s_id = id.s_id AND d.sv_id = id.sv_id))
END
You can't reference a table alias in a subquery of a subquery; the alias doesn't apply (or doesn't exist, or isn't in scope, depending on how you prefer to look at it). With the code you posted the error is reported against line 11 character 24, which is:
(SELECT type FROM
(SELECT d.type as type FROM table_2 d
WHERE d.s_id = t1.s_id AND d.sv_id = t1.sv_id
^^^^^^^^
If you change the t1.s_id reference on the same line to something invalid then the error doesn't change and is still reported as ORA-00904: "T1"."SV_ID": invalid identifier. But if you change the same reference on line 5 instead to something like
((SELECT COUNT(dateCheck.id) FROM table_2 dateCheck
WHERE dateCheck.s_id = t1.s_idXXX AND dateCheck.sv_id = t1.sv_id) = 0)
... then the error changes to ORA-00904: "T1"."S_IDXXX": invalid identifier. This is down to how the statement is being parsed. In your original version the subquery in the WHEN clause is value, and you only break it by changing that identifier. The subquery in the ELSE is also OK. But the nested subquery in the ELSE has the problem, and changing the t1.s_id in that doesn't make any difference because the parser reads that part of the statement backwards (I don't know, or can't remember, why!).
So you have to eliminate the nested subquery. A general approach would be to make the whole CASE an inline view which you can then join using s_id and sv_id, but that's complicated as there may be no matching table_2 record (based on your count); and there may be no s_id value to match against as that isn't being checked in table_3.
It isn't clear if there will always be a table_3 record even then there is a table_2 record, or if they're mutually exclusive. If I've understood what the CASE is doing then I think you can use an outer join between those two tables and compare the combined data with the row you're updating, but because of that ambiguity it needs to be a full outer join. I think.
Here's a stab at using that construct with a MERGE instead of an update.
MERGE INTO table_1 t1
USING (
SELECT t2.s_id,
coalesce(t2.sv_id, t3.id) as sv_id,
coalesce(t2.type, t3.type) as type,
row_number() over (partition by t2.s_id, t2.sv_id
order by t2.creationtimestamp) as rn
FROM table_2 t2
FULL OUTER JOIN table_3 t3
ON t3.id = t2.sv_id
) tmp
ON ((tmp.s_id is null OR tmp.s_id = t1.s_id) AND tmp.sv_id = t1.sv_id AND tmp.rn = 1)
WHEN MATCHED THEN UPDATE SET t1.type = tmp.type;
If there will always be a table_3 record then you could use that as the driver and have a left outer join to table_2 instead, but hard to tell which might be appropriate. So this is really just a starting point.
SQL Fiddle with some made-up data that I believe would have hit both branches of your case. More realistic data would expose the flaws and misunderstandings, and suggest a more robust (or just more correct) approach...
Your query and your analysis seems sound to me. I have no solution but a few things you can try to maybe trigger something that explains this odd behavior:
Quote the column (just in case it happens to be a SQL keyword).
Use table_1.sv_id - this works as long as the whole query contains this table only once.
Make sure that the alias t1 exists only once
Run the query with a query tool like SQuirrel SQL - the tool can examine the exact position where Oracle reports the problem. Maybe it's in a different place of the query than you think
Check () and make sure they are around the parts where they should be.
Swap the order of expressions around =

Update using Join(s) - Multi DB/Table

I have a scenario where I would like to update multiple fields in multiple Tables using just one instuction. I need a Syntax to perform such opperations on multiple Databases (Oracle and MSSQL).
At the moment I am stuck at the following statement from MSSQL:
update table1
set table1.value = 'foo'
from table1 t1 join table2 t2 on t1.id = t2.tab1_id
where t1.id = 1234
I would like to update a field in t2 aswell in the same statement.
Further I would like to perform the same Update(s) on Oracle.
EDIT:Seems like I can not update multiple Tables in just one statement. Is there a syntax that works for Oracle and MSSql when updating using a Join?
Regards
Seems like I can not update multiple
Tables in just one statement.
Is there a syntax that works for
Oracle and MSSql when updating using a
Join?
I assume when you re-posed the question you want syntax that will work on both Oracle and SQL Server even though it will inevitably affect only one table.
Entry level SQL-92 Standard code is supported by both platforms, therefore the following 'scalar subqueries' SQL-92 code should work:
UPDATE table1
SET my_value = (
SELECT t2.tab1_id
FROM table2 AS t2
WHERE t2.tab1_id = table1.id
)
WHERE id = 1234
AND EXISTS (
SELECT *
FROM table2 AS t2
WHERE t2.tab1_id = table1.id
);
Note that while using the correlation name t1 for Ttble1 is valid syntax according to the SQL-92 Standard this will materialize a table and the UPDATE will then target the materialized table 't1' and leave your base table 'table1` unaffected, which I assume is not the desired affect. While I'm fairly sure both Oracle and SQL Server are non-compliant is this regard and that in practise would work as expected, there's no harm in being ultra cautious and sticking to the SQL-92 syntax by fully qualifying the target table.
Folk tend not to like the 'repeated' code in the above subqueries (even though the optimizer should be smart enough to evaluate it only once).
More recent versions of Oracle and SQL Server support both support Standard SQL:2003 MERGE syntax, would may be able to use something close to this:
MERGE INTO table1
USING (
SELECT t2.tab1_id
FROM table2 AS t2
) AS source
ON id = source.tab1_id
AND id = 1234
WHEN MATCHED THEN
UPDATE
SET my_value = source.tab1_id;
I just noticed your example is even simpler than I first thought and merely requires a simple subquery that should run on most SQL products e.g.
UPDATE table1
SET my_value = 'foo'
WHERE EXISTS (
SELECT *
FROM table2 AS t2
WHERE t2.tab1_id = table1.id
);
on Oracle, you can update only one table , but you could think of using a trigger .

What is a 'multi-part identifier' and why can't it be bound?

I continually get these errors when I try to update tables based on another table. I end up rewriting the query, change the order of joins, change some groupings and then it eventually works, but I just don't quite get it.
What is a 'multi-part identifier'?
When is a 'multi-part identifier' not able to be bound?
What is it being bound to anyway?
In what cases will this error occur?
What are the best ways to prevent it?
The specific error from SQL Server 2005 is:
The multi-part identifier "..." could not be bound.
Here is an example:
SELECT * FROM [MainDB].[dbo].[Company]
WHERE [MainDB].[dbo].[Company].[CompanyName] = 'StackOverflow'
The actual error:
Msg 4104, Level 16, State 1, Line 2 The multi-part identifier
"MainDB.dbo.Company.CompanyName" could not be bound.
A multipart identifier is any description of a field or table that contains multiple parts - for instance MyTable.SomeRow - if it can't be bound that means there's something wrong with it - either you've got a simple typo, or a confusion between table and column. It can also be caused by using reserved words in your table or field names and not surrounding them with [].
It can also be caused by not including all of the required columns in the target table.
Something like redgate sql prompt is brilliant for avoiding having to manually type these (it even auto-completes joins based on foreign keys), but isn't free. SQL server 2008 supports intellisense out of the box, although it isn't quite as complete as the redgate version.
Actually sometimes when you are updating one table from another table's data, I think one of the common issues that cause this error, is when you use your table abbreviations incorrectly or when they are not needed. The correct statement is below:
Update Table1
Set SomeField = t2.SomeFieldValue
From Table1 t1
Inner Join Table2 as t2
On t1.ID = t2.ID
Notice that SomeField column from Table1 doesn't have the t1 qualifier as t1.SomeField but is just SomeField.
If one tries to update it by specifying t1.SomeField the statement will return the multi-part error that you have noticed.
It's probably a typo. Look for the places in your code where you call [schema].[TableName] (basically anywhere you reference a field) and make sure everything is spelled correctly.
Personally, I try to avoid this by using aliases for all my tables. It helps tremendously when you can shorten a long table name to an acronym of it's description (i.e. WorkOrderParts -> WOP), and also makes your query more readable.
Edit: As an added bonus, you'll save TONS of keystrokes when all you have to type is a three or four-letter alias vs. the schema, table, and field names all together.
Binding = your textual representation of a specific column gets mapped to a physical column in some table, in some database, on some server.
Multipart identifier could be: MyDatabase.dbo.MyTable. If you get any of these identifiers wrong, then you have a multipart identifier that cannot be mapped.
The best way to avoid it is to write the query right the first time, or use a plugin for management studio that provides intellisense and thus help you out by avoiding typos.
I found that I get these a lot when I try to abbreviate, such as:
Table1 t1, Table2 t2
where t1.ID = t2.ID
Changing it to:
Table1, Table2
where Table1.ID = Table2.ID
Makes the query work and not throw the error.
You probably have a typo. For instance, if you have a table named Customer in a database named Sales, you could refer to it as Sales..Customer (although it is better to refer to it including the owner name (dbo is the default owner) like Sales.dbo.Customer.
If you typed Sales...Customer, you might have gotten the message you got.
If you are sure that it is not a typo spelling-wise, perhaps it is a typo case-wise.
What collation are you using? Check it.
When updating tables make sure you do not reference the field your updating via the alias.
I just had the error with the following code
update [page]
set p.pagestatusid = 1
from [page] p
join seed s on s.seedid = p.seedid
where s.providercode = 'agd'
and p.pagestatusid = 0
I had to remove the alias reference in the set statement so it reads like this
update [page]
set pagestatusid = 1
from [page] p
join seed s on s.seedid = p.seedid
where s.providercode = 'agd'
and p.pagestatusid = 0
Adding table alias in front Set field causes this problem in my case.
Right
Update Table1
Set SomeField = t2.SomeFieldValue
From Table1 t1
Inner Join Table2 as t2
On t1.ID = t2.ID
Wrong
Update Table1
Set t1.SomeField = t2.SomeFieldValue
From Table1 t1
Inner Join Table2 as t2
On t1.ID = t2.ID
I had this issue and it turned out to be an incorrect table alias. Correcting this resolved the issue.
Mine was putting the schema on the table Alias by mistake:
SELECT * FROM schema.CustomerOrders co
WHERE schema.co.ID = 1 -- oops!
I had P.PayeeName AS 'Payer' --,
and the two comment lines threw this error
I actually forgot to join the table to the others that's why i got the error
Supposed to be this way:
CREATE VIEW reserved_passangers AS
SELECT dbo.Passenger.PassName, dbo.Passenger.Address1, dbo.Passenger.Phone
FROM dbo.Passenger, dbo.Reservation, dbo.Flight
WHERE (dbo.Passenger.PassNum = dbo.Reservation.PassNum) and
(dbo.Reservation.Flightdate = 'January 15 2004' and Flight.FlightNum =562)
And not this way:
CREATE VIEW reserved_passangers AS
SELECT dbo.Passenger.PassName, dbo.Passenger.Address1, dbo.Passenger.Phone
FROM dbo.Passenger, dbo.Reservation
WHERE (dbo.Passenger.PassNum = dbo.Reservation.PassNum) and
(dbo.Reservation.Flightdate = 'January 15 2004' and Flight.FlightNum = 562)
Error Code
FROM
dbo.Category C LEFT OUTER JOIN
dbo.SubCategory SC ON C.categoryID = SC.CategoryID AND C.IsActive = 'True' LEFT OUTER JOIN
dbo.Module M ON SC.subCategoryID = M.subCategoryID AND SC.IsActive = 'True' LEFT OUTER JOIN
dbo.SubModule SM ON M.ModuleID = SM.ModuleID AND M.IsActive = 'True' AND SM.IsActive = 'True' LEFT OUTER JOIN
dbo.trainer ON dbo.trainer.TopicID =dbo.SubModule.subModuleID
Solution Code
FROM
dbo.Category C LEFT OUTER JOIN
dbo.SubCategory SC ON C.categoryID = SC.CategoryID AND C.IsActive = 'True' LEFT OUTER JOIN
dbo.Module M ON SC.subCategoryID = M.subCategoryID AND SC.IsActive = 'True' LEFT OUTER JOIN
dbo.SubModule SM ON M.ModuleID = SM.ModuleID AND M.IsActive = 'True' AND SM.IsActive = 'True' LEFT OUTER JOIN
dbo.trainer ON dbo.trainer.TopicID = SM.subModuleID
as you can see, in error code, dbo.SubModule is already defined as SM, but I am using dbo.SubModule in next line, hence there was an error.
use declared name instead of actual name. Problem solved.
My best advise when having the error is to use [] braquets to sorround table names, the abbreviation of tables causes sometimes errors, (sometime table abbreviations just work fine...weird)
I was getting this error and just could not see where the problem was. I double checked all of my aliases and syntax and nothing looked out of place. The query was similar to ones I write all the time.
I decided to just re-write the query (I originally had copied it from a report .rdl file) below, over again, and it ran fine. Looking at the queries now, they look the same to me, but my re-written one works.
Just wanted to say that it might be worth a shot if nothing else works.
When you type the FROM table those errors will disappear.
Type FROM below what your typing then Intellisense will work and multi-part identifier will work.
I faced this problem and solved it but there is a difference between your and mine code. In spite of I think you can understand what is "the multi-part identifier could not be bound"
When I used this code
select * from tbTest where email = sakira#gmail.com
I faced Multi-part identifier problem
but when I use single quotation for email address It solved
select * from tbTest where email = 'sakira#gmail.com'
I had exactly the same issue, and similar to your coding I had missed out the FROM field, once it is added, the query knows what table to read the data from
Mine worked after removing square brackets in a SUBSTRING method. I changed from
SUBSTRING([dbo.table].[column],15,2)
to
SUBSTRING(dbo.table.column,15,2)
CTRL+SHIFT+R (refreshing the Intellisense) took care of it for me.