refer to outside field value in subselect? - sql

I want to do a query to update values that I forgot to copy over in a mass insert. However I'm not sure how to phrase it.
UPDATE table
SET text_field_1 = (SELECT text_field_2
FROM other_table
WHERE id = **current row in update statement, outside parens**.id )
How do I do this? It seems like a job for recursion.

Use:
UPDATE YOUR_TABLE
SET text_field_1 = (SELECT t.text_field_2
FROM other_table t
WHERE t.id = YOUR_TABLE.id)
Warning
If there's no supporting record in other_table, text_field_1 will be set to NULL.
Explanation
In standard SQL, you can't have table aliases on the table defined for the UPDATE (or DELETE) statement, so you need to use full table name to indicate the source of the column.
It's called a correlated subquery -- the correlation is be cause of the evaluation against the table from the outer query.
Clarification
MySQL (and SQL Server) support table aliases in UPDATE and DELETE statement, in addition to JOIN syntax:
UPDATE YOUR_TABLE a
JOIN OTHER_TABLE b ON b.id = a.id
SET a.text_field_1 = b.text_field_2
...is not identical to the provided query, because only the rows that match will be updated -- those that don't match, their text_field_1 values will remain untouched. This is equivalent to the provided query:
UPDATE YOUR_TABLE a
LEFT JOIN OTHER_TABLE b ON b.id = a.id
SET a.text_field_1 = b.text_field_2

If there is one ID field:
UPDATE updtable t1
SET t1.text_field_1 = (
SELECT t2.text_field_2
FROM seltable t2
WHERE t1.ID = t2.ID
)
;

UPDATE Table1, Tabl2
SET Table1.myField = Table2.SomeField
WHERE Table1.ID = Table2.ID
Note: I have not tried it.
This will only update records where IDs match.

Try this:
UPDATE table
SET text_field_1 = (SELECT text_field_2
FROM other_table
WHERE id = table.id )

Related

How do I UPDATE from a SELECT of same table

I should update a column of table by converting other column of same table in oracle. something like this:
update table1 set colum1=(select TO_CHAR(column2) from table1)
but I have this error
single-row subquery returns more than one row
could I do this?
It's just
update table1 set
column1 = to_char(column2);
If you ever need it for more dynamic value generation, use WHERE to match a specific record
update table1 a
set colum1 = (select TO_CHAR(column2) from table1 b where b.id = a.id)
where a.id = .... -- <-- optional, for specific records

update with join in oracle sql

I want to update a column of a table1 but I should update only records where conditions are true in another table
something like this, but I don't know how to implement this purpose in Oracle SQL
update table1
join table2 on table1.msg_id = table2.id
set table1.index = table1.index-1
where table1.index > 10 and table2.type = 'myType'
I would write this as an exists subquery in any database:
update table1 t1
set index = t1.index - 1
where table1.index > 10 and
exists (select 1
from table2
where t2.id = t1.msg_id and
t2.type = 'myType'
);
The join sort of implies that you are going to use data from table2 in the update of table1. Instead, you simply want to change a value in a row when a particular condition is met.
Oracle does not support this syntax (sigh).
For your use case, you could use a not exists condition with a correlated subquery instead:
update table1
set table1.index = table1.index - 1
where
table1.index > 10
and exists (
select 1 from table2 where table1.msg_id = table2.id and table2.type = 'mytype'
)
Note: make your live easier, do not use index for a column name. This is a reserved work in pretty much all RDBMS.

ORA-01427 Subquery returns more then one row..Oracle Update Statement

How do you write a update statement with a Sub-Select in an Oracle Environment (SQL Developer)?
Example: UPDATE table SET column = (SELECT....)
Every time I try this it gives me ORA-01427 "Sub select returns more then one row" even if there is no WHERE clause..
Based on the understanding of your question I'd suggest use Merge statement.
Merge into Table1
Using
(SELECT * from table2 where condition) Temp
On (Table1.columname condition Temp.columname)
When matched Then update Set Table1.column_name = Temp.column_name;
Table1 is the table where you want to update the records.
Table2 is the table from which you want to get the data (The sub query which you are talking about )
Using this merge statement you will be able to update n number of rows.
If you want to update multiple rows, you can either use a MERGE statement (as in #jackkds7's answer above) or you can use a filter on your subselect:
UPDATE table t1
SET column = ( SELECT column FROM table2 t2 WHERE t2.key = t1.key );
If there aren't matches in table2 for all the records in table then column will be set to NULL for the non-matches. To avoid that, add a WHERE EXISTS clause:
UPDATE table t1
SET column = ( SELECT column FROM table2 t2 WHERE t2.key = t1.key )
WHERE EXISTS ( SELECT 1 FROM table2 t2 WHERE t2.key = t1.key );
Oh and in the event that key is not unique for table2, you can aggregate (up to you to figure out which function would be best):
UPDATE table t1
SET column = ( SELECT MAX(column) FROM table2 t2 WHERE t2.key = t1.key )
WHERE EXISTS ( SELECT 1 FROM table2 t2 WHERE t2.key = t1.key );
Hope this helps.
I think it would help if you posted your actual query.
In essence, the "inner" select would be executed for each row that would be updated. This inner select query is called a correlated subquery:
UPDATE table t SET t.column = (
select ot.othercolumn from othertable ot
where ot.fk = t.id --This is the correlation part, that finds
--he right value for the row you are currently updating
)
You must ensure the subquery you use will always return just a single row and a single column for every time it runs (that is, for every row that is going to be updated). If needed, you can use MAX(), or ROWNUM to ensure you always only get 1 value
More examples:
Using Correlated Subqueries

SQL Update multiple rows and columns with subselect query

I have the problem of needing to update multiple columns (2) in multiple rows (7) from a subselect query.
Here is what I have so far:
UPDATE commandtbl2 t1
SET (attr, attr2) = (
SELECT attr, attr2
FROM commandtbl3 t2
WHERE t1.cmd=t2.cmd
);
However when I let that run I get SQLCODE=-811, SQLSTATE=21000
(THE RESULT OF AN EMBEDDED SELECT STATEMENT OR A SUBSELECT IN THE SET CLAUSE OF AN UPDATE STATEMENT IS A TABLE OF MORE THAN ONE ROW, OR THE RESULT OF A SUBQUERY OF A BASIC PREDICATE IS MORE THAN ONE VALUE)
Where is my mistake? It should change the 2 columns in 3 rows and leave the others rows as they are. I can only use SQL so no Java, PHP and so on.
Since this is DB2 solutions I have found online like:
UPDATE commandtbl2 t1
SET attr = t2.attr, attr2=t2.attr2
FROM commandtbl2 t1
JOIN commandtbl3 t2
ON t1.cmd = t2.cmd ;
Or
UPDATE
commandtbl2 t1
JOIN
commandtbl3 t2 ON t1.cmd=t2.cmd
SET
t1.attr = t2.attr,
t1.attr2=t2.attr2;
don't work but throw exceptions.
Thanks for your help.
TheVagabond
I think your first version should work. But here is another idea:
UPDATE commandtbl2
SET attr = t2.attr, attr2 = t2.attr2
FROM commandtbl3 t2
WHERE commandtbl2.cmd = t2.cmd ;
The version of DB2 matters. In V10, you may need two subqueries:
UPDATE commandtbl2
SET attr = (SELECT t2.attr FROM commandtbl3 t2 WHERE commandtbl2.cmd = t2.cmd FETCH FIRST 1 ROW ONLY),
attr2 = (SELECT t2.attr2 FROM commandtbl3 t2 WHERE commandtbl2.cmd = t2.cmd FETCH FIRST 1 ROW ONLY);
Note: Normally when using FETCH FIRST 1 ROW ONLY, you would have an ORDER BY.
Use a join:
UPDATE commandtbl2 t1 JOIN commandtbl3 t2 ON t1.cmd=t2.cmd SET t1.attr=t2.attr, t1.attr2=t2.attr2;
Problem is probably as stated, you try to update one row (or multiple) with the values of more rows.

SQL command to compare results is not working [duplicate]

I want to update a column in a table making a join on other table e.g.:
UPDATE table1 a
INNER JOIN table2 b ON a.commonfield = b.[common field]
SET a.CalculatedColumn= b.[Calculated Column]
WHERE
b.[common field]= a.commonfield
AND a.BatchNO = '110'
But it is complaining :
Msg 170, Level 15, State 1, Line 2
Line 2: Incorrect syntax near 'a'.
What is wrong here?
You don't quite have SQL Server's proprietary UPDATE FROM syntax down. Also not sure why you needed to join on the CommonField and also filter on it afterward. Try this:
UPDATE t1
SET t1.CalculatedColumn = t2.[Calculated Column]
FROM dbo.Table1 AS t1
INNER JOIN dbo.Table2 AS t2
ON t1.CommonField = t2.[Common Field]
WHERE t1.BatchNo = '110';
If you're doing something silly - like constantly trying to set the value of one column to the aggregate of another column (which violates the principle of avoiding storing redundant data), you can use a CTE (common table expression) - see here and here for more details:
;WITH t2 AS
(
SELECT [key], CalculatedColumn = SUM(some_column)
FROM dbo.table2
GROUP BY [key]
)
UPDATE t1
SET t1.CalculatedColumn = t2.CalculatedColumn
FROM dbo.table1 AS t1
INNER JOIN t2
ON t1.[key] = t2.[key];
The reason this is silly, is that you're going to have to re-run this entire update every single time any row in table2 changes. A SUM is something you can always calculate at runtime and, in doing so, never have to worry that the result is stale.
Try it like this:
UPDATE a
SET a.CalculatedColumn= b.[Calculated Column]
FROM table1 a INNER JOIN table2 b ON a.commonfield = b.[common field]
WHERE a.BatchNO = '110'
Answer given above by Aaron is perfect:
UPDATE a
SET a.CalculatedColumn = b.[Calculated Column]
FROM Table1 AS a
INNER JOIN Table2 AS b
ON a.CommonField = b.[Common Field]
WHERE a.BatchNo = '110';
Just want to add why this problem occurs in SQL Server when we try to use alias of a table while updating that table, below mention syntax will always give error:
update tableName t
set t.name = 'books new'
where t.id = 1
case can be any if you are updating a single table or updating while using join.
Although above query will work fine in PL/SQL but not in SQL Server.
Correct way to update a table while using table alias in SQL Server is:
update t
set t.name = 'books new'
from tableName t
where t.id = 1
Hope it will help everybody why error came here.
MERGE table1 T
USING table2 S
ON T.CommonField = S."Common Field"
AND T.BatchNo = '110'
WHEN MATCHED THEN
UPDATE
SET CalculatedColumn = S."Calculated Column";
UPDATE mytable
SET myfield = CASE other_field
WHEN 1 THEN 'value'
WHEN 2 THEN 'value'
WHEN 3 THEN 'value'
END
From mytable
Join otherTable on otherTable.id = mytable.id
Where othertable.somecolumn = '1234'
More alternatives here.
Seems like SQL Server 2012 can handle the old update syntax of Teradata too:
UPDATE a
SET a.CalculatedColumn= b.[Calculated Column]
FROM table1 a, table2 b
WHERE
b.[common field]= a.commonfield
AND a.BatchNO = '110'
If I remember correctly, 2008R2 was giving error when I tried similar query.
I find it useful to turn an UPDATE into a SELECT to get the rows I want to update as a test before updating. If I can select the exact rows I want, I can update just those rows I want to update.
DECLARE #expense_report_id AS INT
SET #expense_report_id = 1027
--UPDATE expense_report_detail_distribution
--SET service_bill_id = 9
SELECT *
FROM expense_report_detail_distribution erdd
INNER JOIN expense_report_detail erd
INNER JOIN expense_report er
ON er.expense_report_id = erd.expense_report_id
ON erdd.expense_report_detail_id = erd.expense_report_detail_id
WHERE er.expense_report_id = #expense_report_id
Another approach would be to use MERGE
;WITH cteTable1(CalculatedColumn, CommonField)
AS
(
select CalculatedColumn, CommonField from Table1 Where BatchNo = '110'
)
MERGE cteTable1 AS target
USING (select "Calculated Column", "Common Field" FROM dbo.Table2) AS source ("Calculated Column", "Common Field")
ON (target.CommonField = source."Common Field")
WHEN MATCHED THEN
UPDATE SET target.CalculatedColumn = source."Calculated Column";
-Merge is part of the SQL Standard
-Also I'm pretty sure inner join updates are non deterministic..
Similar question here where the answer talks about that
http://ask.sqlservercentral.com/questions/19089/updating-two-tables-using-single-query.html
I think, this is what you are looking for.
UPDATE
Table1
SET
Table1.columeName =T1.columeName * T2.columeName
FROM
Table1 T1
INNER JOIN Table2 T2
ON T1.columeName = T2.columeName;
I had the same issue.. and you don't need to add a physical column.. cuz now you will have to maintain it..
what you can do is add a generic column in the select query:
EX:
select tb1.col1, tb1.col2, tb1.col3 ,
(
select 'Match' from table2 as tbl2
where tbl1.col1 = tbl2.col1 and tab1.col2 = tbl2.col2
)
from myTable as tbl1
Aaron's approach above worked perfectly for me. My update statement was slightly different because I needed to join based on two fields concatenated in one table to match a field in another table.
--update clients table cell field from custom table containing mobile numbers
update clients
set cell = m.Phone
from clients as c
inner join [dbo].[COSStaffMobileNumbers] as m
on c.Last_Name + c.First_Name = m.Name
Those who are using MYSQL
UPDATE table1 INNER JOIN table2 ON table2.id = table1.id SET table1.status = 0 WHERE table1.column = 20
Try:
UPDATE table1
SET CalculatedColumn = ( SELECT [Calculated Column]
FROM table2
WHERE table1.commonfield = [common field])
WHERE BatchNO = '110'