Update using Inner Join throwing syntax error - sql

I would like to update columns in Table A based on values in Table B. Using below format, but getting syntax error.
update TableA
set
TableA.MOdule_id =TableB.MOdule_id
from TableA
inner join
TableB
on TableA.end_Slot_id =TableB.Slot_Id
where TableA.Slot_Id = 'AAA';
It would be great help, if anyone can help on this.

A quick search for "informix sql update" returns two reference manual pages that describe the syntax for the UPDATE command. Neither one indicates support for the nonstandard FROM clause.
Standard SQL uses a correlated subquery for the purpose. Your query should look something like
update TableA
set MOdule_id =
(select TableB.MOdule_id
from TableB
on TableA.end_Slot_id = Slot_Id)
where Slot_Id = 'AAA'
and exists (
select 1
from TableB
on TableA.end_Slot_id = Slot_Id
and TableA.Slot_Id = 'AAA'
);
The EXISTS clause ensures that only rows that exist in B are applied to A. Without it, any missing rows would be updated to NULL.

Related

Oracle SQL Language Reference Merge/Subquery Documentation Error?

When using the merge::= MERGE INTO ... USING subquery t_alias it appears one must enclose the subquery in parenthesis like MERGE INTO ... USING (subquery) t_alias. However, the Oracle SQL Language Reference documentation's syntax diagram for subquery::= appears to show that an optional path (via query_block) does not require parenthesis. That is the documentation appears to allow both versions.
For example:
This following is invalid, but allowable per the documentation.
MERGE INTO tblA A
USING SELECT col FROM tblB B -- ORA-00903 invalid table name and "SELECT" is highlighted.
ON (A.id = B.id)
...
The following is valid (and also allowable per the documentation).
MERGE INTO tblA A
USING (SELECT col FROM tblB) B
ON (A.id = B.id)
...
According to How to Read Syntax Diagrams
If the syntax diagram has more than one path, then you can choose any path.
Is there an Oracle SQL Language Reference documentation error?
Thanks in advance.
In MERGE query, the operand used after USING clause is not exactly a sub query. It actually defines a table. For example: if you want to update a table from the values from another table.
MERGE INTO tblA A
USING tblB B
ON (A.id = B.id)
...
In case tblB has very huge amount of data and you want to optimise the
perfomance, you can use a query to fetch required columns from the table.
MERGE INTO tblA A
USING (SELECT col1, col2, col3 FROM tblB) B -- here we are not using complete table,
instead we are using only required columns from the table
ON (A.id = B.id)
...
Merge is also similar to join, below is the better way of understanding
select * from tblA A
inner join tblB B
ON (A.id = B.id);
or
select * from tblA A
inner join (SELECT col1, col2, col3 FROM tblB) B
ON (A.id = B.id);
The reason you get invalid table name is, when you do not enclose the select statement in brackets, Oracle will not know the aliases of the table you are using. So always enclose a bracket when you have a certain conditions in the query.

Oracle, update column in table 1, when related row does not exist in table 2

I have seen many answers that will update a table 1 when rows exist in table 2, but not one that works using a LEFT JOIN in selecting the rows, (for better performance). I have a solution to the update, but it will perform badly as it uses NOT IN.
So this SQL will update the tables as required, but looks to be very costly when run against large tables making it difficult to use.
update header
set status='Z'
where status='A'
and header.id not in (
select headerid
from detail
where detail.id between 0 and 9999999
);
Now I have a well performing query using a LEFT JOIN which returns the correct ids, but I have not been able to insert it into an update statement to give the same results.
The select statement is
select header.id
from header
left join detail on detail.headerid = header.id
where detail.headerid is null
and header.status='A'
So if I use this in the update statement as in:
update header
set status = 'Z'
where header.id = (
select header.id
from header
left join detail on detail.headerid = header.id
where detail.headerid is null and header.status='A'
)
Then I fail with:
ORA-01427: single-row subquery returns more than one row
I am expecting multiple header.id to be returned and want to update all these rows.
So I am still searching for a solution which will update the returned rows, using a well performing SQL select to return rows in table header, that do not have related rows in the detail table.
Any help would be appreciated, otherwise I will be left with the badly performing update.
Since you are expecting multiple header ID & the sub query returns multiple ID as you expected you should use IN
Try this
Update
header
Set status = 'Z'
Where
header.id IN (select
header.id
From
header
Left join
detail
On
detail.headerid = header.id
Where
detail.headerid is null
And
header.status='A')
I wouldn't put the condition on the outer table in the subquery. I am more comfortable writing this logic as:
update header h
set status = 'Z'
where not exists (select 1
from detail d
where d.headerid = h.id
) and
h.status = 'A';
If performance is an issue, indexes on detail(headerid) and header(status, id) and help.
typical, the next place I looked, I found an answer...
update header set status='Z' where not exists (select detail.headerid from detail where detail.headerid = header.id) and status = 'A'
Oh well, at least its here if anyone else wants to find it.
As the error states your subquery is returning more than one rows and you are using a = sign in your update query. = sign is not allowed if your query returns more than one records use either IN, NOT IN , EXISTS, NOT EXISTS as per your requirement

How does SQL Server Update rows with more than one value?

In an update statement for a temp table, how does SQL Server decide which value to use when there are multiple values returned, for example:
UPDATE A
SET A.dte_start_date = table1.dte_start_date
FROM #temp_table A
INNER JOIN table1 ON A.id = table1.id
In this situation the problem is more than one dte_start_date is returned for each id value in the temp table. There is there's no index or unique value in the tables I'm working on so I need to know how SQL Server will choose between the different values.
It is non-deterministic. See the following example for a better understanding. Though it is not exactly the same scenario explained here, it is pretty similar
When the single value is to be retrieved from the database also use the SET statement with a query to set the value. For example:
SET #v_user_user_id = (SELECT u.user_id FROM users u WHERE u.login = #v_login);
Reason: Unlike Oracle, SQL Server does not raise an error if more than one row is returned from a SELECT query that is used to populate variables. The above query will throw an exception whereas the following will not throw an exception and the variable will contain a random value from the queried table(s).
SELECT #v_user_user_id = u.user_id FROM users u WHERE u.login = #v_login;
It is non-deterministic which value is used if you have a one two many relationship.
In MS-SQL-Sever (>=2005) i would use a CTE since it's a readable way to specify what i want using ROW_NUMBER. Another advantage of a CTE is that you can change it easily to do a select instead of an update(or delete) to see what will happen.
Assuming that you want the latest record(acc.to dte_start_date) for every id:
WITH CTE AS
(
SELECT a.*, rn = ROW_NUMBER() OVER (PARTITION BY a.id
ORDER BY a.dte_start_date DESC)
FROM #temp_table A
INNER JOIN table1 ON A.id = table1.id
)
UPDATE A
SET A.dte_start_date = table1.dte_start_date
FROM #temp_table A INNER JOIN CTE ON A.ID = CTE.ID
WHERE CTE.RN = 1

ORA-01427: single-row subquery returns more than one row update...?? Help?

My Query returns this error ORA-01427: single-row subquery returns more than one row update, This is my query
Update Table_b B
Set B.Material_Desc = (Select A.Material_Desc From Table_a A Where A.PartNo = B.PartNo)
I have two different tables : Table_a and Table_b, both have same columns PartNo and Material_Desc. I want the Material_Desc in Table_b to update the Material_Desc in Table_a when PartNo are equals.
The above query returns the ORA-01427 error, Please can anyone correct my query ?
The problem is your subquery is returning a whole bunch of rows where you should have only one. You can't do this like this.
Depending on the SQL database you're using, something like this should work better :
UPDATE Table_b B
SET B.Materiel_Desc = A.Materiel_Desc
INNER JOIN Table_a A ON A.PartNo = B.PartNo
It is possible you must adapt the syntax to your database. For example, I think you cannot do it like this with MySQL. According to http://dev.mysql.com/doc/refman/5.0/en/update.html you should do :
UPDATE Table_b, Table_A
SET Table_b.Materiel_Desc = Table_A.Materiel_Desc
WHERE Table_b.PartNo = Table_a.PartNo;

What is wrong with my SQL syntax for an UPDATE with a JOIN?

I have two tables, related by a common key. So TableA has key AID and value Name and TableB has keys AID, BID and values Name, Value:
AID Name
74 Alpha
AID BID Name Value
74 4 Beta Brilliance
I would like to update the TableB Value here from Brilliance to Barmy, using just the Name fields. I thought I could do it via an UPDATE containing a JOIN, but Access (I know...) is complaining with 'Syntax error (missing operator) in query expression ' and then everything from 'Barmy' here:
UPDATE tB
SET tB.Value='Barmy'
FROM `TableB` tB
INNER JOIN `TableA` tA
ON tB.AID=tA.AID
WHERE tB.Name='Beta'
AND tA.Name='Alpha';
What is my heinous crime? Or is it just Access not conforming?
Oddly, I've discovered the answer is to use an implicit JOIN:
UPDATE `TableA`, `TableB`
SET `TableB`.Value = 'Barmy'
WHERE `TableA`.AID=`TableB`.AID
AND `TableA`.Name='Alpha'
AND `TableB`.Name='Beta';
I have to be honest i haven't touched ACCESS in years (luckily) this thread seems to suggest this is the correct syntax.
UPDATE TableB tB
SET tB.BValue='Barmy'
INNER JOIN TableA tA
ON tB.AID=tA.AID
WHERE tB.Name='Beta'
AND tA.Name='Alpha';
I reckon, based on a test:
UPDATE TableB tB
INNER JOIN TableA tA
ON tB.AID=tA.AID
SET tB.Value='Barmy'
WHERE tB.Name='Beta'
AND tA.Name='Alpha';
it may not know what tB is until you get to the aliasing in the FROM line. Try UPDATE TableB ....
One solution is to write in Hoyle ANSI (which does not recognize the FROM clause in an UPDATE statement):
UPDATE TableB
SET BValue="Barmy"
Where Name="Beta"
And Exists( Select 1
From TableA As TA
Where TA.Name = "Alpha"
And TA.AID = TableB.AID );
One last addition, Access deals with JOINS in an UPDATE statement by putting them in the UPDATE clause like so:
UPDATE TableB
INNER JOIN TableA tA
ON TableB.AID=tA.AID
SET TableB.BValue="Barmy"
WHERE TableB.Name="Beta"
AND tA.Name="Alpha";
EDIT One other item, Access uses double quotes to identify strings, not single quotes.
Does Access do subqueries?
UPDATE TableB
SET TableB.Value='Barmy'
WHERE TableB.AID = (SELECT TableA.AID WHERE TableA.Name='Alpha')