SQL Server Cannot Update Table with Subqueries - sql-server

I'm trying to update a temporary table called #deletedRecords which looks like this:
With the data from a table called log that looks like this:
The KeyValue in the log table is the same as the ID in #deletedRecords.
There is a column in #deletedRecords for every FieldName for any particular key value.
I tried to extract the values using the following query:
UPDATE #deletedRecords
SET PatientName = (SELECT ACL.OldValue WHERE ACL.FieldName = 'CptCode'),
ChargeNotes = (SELECT ACL.OldValue WHERE ACL.FieldName = 'ChargeNotes'),
Units = (SELECT ACL.OldValue WHERE ACL.FieldName = 'Units'),
ChargeStatusID = (SELECT ACL.OldValue WHERE ACL.FieldName = 'Units')
FROM Log ACL
JOIN #deletedRecords DR ON ACL.KeyValue = DR.ID
WHERE ACL.TableName = 'BillingCharge'
AND ACL.EventType = 'DELETE'
However when I run the query all of the columns to be updated in #deletedRecords are null. Can somebody please help explain what I'm missing?
Thanks in advance.
EDIT:
In response to #Yogesh Sharma's answer, I elected to use the CTE method. I would this that using the values from the CTE to join to additional tables and extract their values during the update.
e.g. The Log table doesn't contain an old value for the StatusName but it does contain the ChargeStatusID which could be used to join to another table that contains that information such as this table ChargeStatus:
Thus I modified #Yogesh Sharma's code to the following:
WITH cte AS
...
UPDATE d
SET d.PatientName = c.PatientName
, d.StatusName = cs.StatusName
FROM #deletedBillingChargeTemp d
JOIN cte c ON c.KeyValue = d.chargeID
JOIN ChargeStatus cs ON c.ChargeStatusID = cs.ChargeStatusID
However, once I add that secondary join, all of the updated values return to null as they were before #Yogesh Sharma's suggestions were implemented.

Your query does not work because the UPDATE is executed multiple times for each row in DR, considering only the conditions specified in the last three rows of your query (not the ones specified in the subqueries). The values that remain in the table are the ones that correspond to the ACL row used in the last execution (and the order of execution cannot be controlled). If for ACL row used in the last execution the subqueries return NULL, you will get a NULL result.
See the example in the https://learn.microsoft.com/en-us/sql/t-sql/queries/update-transact-sql topic, where it says "The results of an UPDATE statement are undefined if the statement includes a FROM clause that is not specified in such a way that only one value is available for each column occurrence that is updated, that is if the UPDATE statement is not deterministic.".
You should rewrite your query like this:
UPDATE #deletedRecords
SET PatientName = (
SELECT ACL.OldValue FROM Log ACL
WHERE ACL.FieldName = 'CptCode' AND ACL.KeyValue = DR.ID
AND ACL.TableName = 'BillingCharge' AND ACL.EventType = 'DELETE'
),
ChargeNotes = (
SELECT ACL.OldValue FROM Log ACL
WHERE ACL.FieldName = 'ChargeNotes' AND ACL.KeyValue = DR.ID
AND ACL.TableName = 'BillingCharge' AND ACL.EventType = 'DELETE'
),
Units = (
SELECT ACL.OldValue FROM Log ACL
WHERE ACL.FieldName = 'Units' AND ACL.KeyValue = DR.ID
AND ACL.TableName = 'BillingCharge' AND ACL.EventType = 'DELETE'
),
ChargeStatusID = (
SELECT ACL.OldValue FROM Log ACL
WHERE ACL.FieldName = 'Units' AND ACL.KeyValue = DR.ID
AND ACL.TableName = 'BillingCharge' AND ACL.EventType = 'DELETE'
)
FROM #deletedRecords DR

You would required to do some conditional aggregation for log table and do the JOINs in order to update the temporary table #deletedRecords records
So, the conditional approach could be achieve via CTE or Subquery
WITH cte AS
(
SELECT KeyValue,
MAX(CASE WHEN FieldName = 'CptCode' THEN OldValue END) PatientName,
MAX(CASE WHEN FieldName = 'ChargeNotes' THEN OldValue END) ChargeNotes,
...
FROM Log
WHERE TableName = 'BillingCharge' AND EventType = 'DELETE'
GROUP BY KeyValue
)
UPDATE d
SET d.PatientName = c.PatientName,
...
FROM #deletedRecords d
INNER JOIN cte c ON c.KeyValue = d.ID
The other way is to update your temporary table via correlation approach
UPDATE d
SET d.PatientName = (SELECT TOP 1 OldValue FROM Log WHERE KeyValue = d.ID AND
TableName = 'BillingCharge' AND EventType = 'DELETE' AND FieldName = 'CptCode'),
d.ChargeNotes= (SELECT TOP 1 OldValue FROM Log WHERE KeyValue = d.ID AND
TableName = 'BillingCharge' AND EventType = 'DELETE' AND FieldName = 'ChargeNotes'),
...
FROM #deletedRecords d

If your updated columns are NULL, these are it's possible causes:
Since you are doing a INNER JOIN, records might not be joining correctly by their joining column. Make sure both tables have the same values on the joining columns.
Since you are filtering in a WHERE clause, records might not fulfill your TableName and EventType filters. Make sure there are records that sucessfully INNER JOIN between them and they have the supplied TableName and EventType.
The values you are asigning are NULL. Make sure your subqueries return a not null value.
Table reference is off. When updating a table in SQL Server, always use the updating table alias if you are using one.
Use
UPDATE DR SET
YourColumn = Value
FROM
Log ACL
JOIN #deletedRecords DR ON -...
Instead of
UPDATE #deletedRecords SET
YourColumn = Value
FROM
Log ACL
JOIN #deletedRecords DR ON -...
Make sure you are NOT checking the variable table values on another batch, script or procedure. Variable tables scope are limited to current batch or procedure, while temporary tables remain as long as the session is alive.
Make sure that there isn't another statement that is setting those values as NULL after your update. Also keep an eye on your transactions (might not be commited or rolled back).

Related

Update multiple tables with multiple rows with trigger

I have these tables Users, UserPackages, Packages, Refers.
Users table has columns UserRef_NO (his own unique number), RefNo (if he registered using someones reference number) and Refarning (where he/she gets earning if someone registered using his refNo and bought a package and package status changed to 'True').
UserPackages table has columns U_ID (foreign key to Users), P_ID (foreign key to Packages), PackageStatus (true if bought false if not), BuyDate (generated as soon as PackageStatus changes to true), ExpiryDate (calculated from the join of Packages table and BuyDate where validity is total days of Packages)
Packages table has columns Price, ReferComission (in percentage), Validity (in days).
EDIT:- Third Edit this works fine for single row updates but fails for multi row updates saying subquery returned more then one value
alter TRIGGER [dbo].[HeavyTriggerTest] ON [dbo].[UserPackages]
after update
as
update UP set
BuyDate = GETDATE(), Expirydate = dateadd(dd, P.Validitiy, getdate())
from dbo.UserPackages UP
inner join Inserted I on I.P_ID = UP.P_ID and I.U_ID = UP.U_ID
inner join dbo.Packages P on P.PID = I.P_ID
where UP.PackageStatus = 'True';
;
with firstCte(Name,UID,PName,Price,ReferComission,ReferredBy)
as
(
select distinct Users.Name,Users.ID,Packages.PName,Packages.Price,Packages.ReferCommission,(select DISTINCT ID from Users
where Users.UserRef_No=Refers.RefOf )
from Users inner join UserPackages on UserPackages.U_ID=Users.ID
inner join Packages on Packages.PID=UserPackages.P_ID
inner join Refers on Users.Ref_No=Refers.RefOf
inner join Inserted I on I.U_ID = UserPackages.U_ID and I.P_ID = UserPackages.P_ID
and UserPackages.PackageStatus='true' AND UserPackages.U_ID=i.U_ID
AND Refers.RefOf=(SELECT users.Ref_No where UserPackages. U_ID=i.U_ID)
)
update Users set RefEarning+= Price*ReferComission/100 from firstCte where ID=ReferredBy ;
update Users set Active='True' where ID=(select U_ID from inserted) and Active='False'
and here's the single update query which i tried to replace with above last two updates but it gives wrong results plus it also doesn't work for multiple row updates
update Users set RefEarning+=(
case when ID=firstCte.ReferredBy then firstCte.Price*ReferComission/100 else RefEarning end)
,Active=case when ID=(select U_ID from inserted) and Active='false' then 'True'
when firstCte.ReferredBy=(select U_ID from inserted) then 'true' else Active end
from firstCte
Your second query, first update, you need to join Inserted on as:
update UP set
BuyDate = GETDATE(), Expirydate = dateadd(dd, P.Validitiy, getdate())
from dbo.UserPackages UP
inner join Inserted I on I.P_IP = UP_P_ID and I.U_ID = UP.U_ID
inner join dbo.Packages P on P.PID = I.P_ID
where UP.PackageStatus = 'True';
Note the table aliases which I recommended to you in your last question - they make it much easier to read through a query.
Also note its best practice to schema qualify your tables.
Second query, second update:
with firstCte ([Name], [UID], PName, Price, ReferComission, ReferredBy)
as
(
select U.[Name], U.ID, P.PName, P.Price, P.ReferCommission
, max(U.ID) over () as referedby
from Users U
inner join UserPackages UP on UP.U_ID = U.ID
inner join Packages P on P.PID = UP.P_ID
inner join Refers R on R.RefOf = U.Ref_No
inner join Inserted I on I.U_ID = UP.U_ID and I.P_ID = UP.P_ID
where UP.PackageStatus='true'
)
update U set
Active = 'True'
, RefEarning += Price*ReferComission/100
from Users U
inner join firstCte on ReferredBy = U.id
where Active = 'False';
Note the window function max to avoid repeating the query in a sub-query.
Note joining the CTE to the Users table to perform the update.

How can I update records found with except in SQL

I'm comparing (one-way) two tables of different databases in SQL.
I want to update only the second table with the differences.
The comparing part gives me the correct results, but I have no clue how to get these result in the updating part
-- The comparing part DB1 with DB2
WITH RecordsWithUpdates AS
(SELECT DeviceID, DeviceName, DeviceNumber, Active FROM DB1.dbo.devices
EXCEPT
SELECT DeviceID, DeviceName, DeviceNumber, Active FROM DB2.dbo.devices
)
-- displaying the differences
Select * from DB2.dbo.Devices
WHERE DeviceID IN (SELECT DeviceID FROM RecordsWithUpdates)
-- Updating then columns of DB2
Update DB2.dbo.devices SET DeviceName = ?????, SET DeviceNumber = ??????, Active = ???????
The Code part with the ????? is where it should insert the found differences, but I cannot get it to work.
I would approach this with the UPDATE ... SET ... FROM ... JOIN syntax, like:
UPDATE
t2
SET
t2.DeviceName = t1.DeviceName,
t2.DeviceNumber = t1.DeviceNumber,
t2.Active = t1.Active
FROM
DB2.dbo.devices t2
INNER JOIN DB1.dbo.devices t1
ON t1.DeviceID = t2.DeviceID
AND NOT (
t1.DeviceName = t2.DeviceName
AND t1.DeviceNumber = t2.DeviceNumber
AND t1.Active = t2.Active
)
If you want at the same time to INSERT records that do not yet exists, then you can use the MERGE syntax instead:
MERGE DB2.dbo.devices t2
USING DB1.dbo.devices t1
ON (t1.DeviceID = t2.DeviceID)
WHEN MATCHED
THEN UPDATE SET
t2.DeviceName = t1.DeviceName,
t2.DeviceNumber = t1.DeviceNumber,
t2.Active = t1.Active
WHEN NOT MATCHED
THEN INSERT(DeviceID, DeviceName, DeviceNumber, Active)
VALUES (t1.DeviceID, t1.DeviceName, t1.DeviceNumber, t1.Active)
Finally: if you want to delete the records that exist in t2 but not in t1, just add this at the end of the MERGE query:
WHEN NOT MATCHED BY SOURCE
THEN DELETE;

Updating DISTINCTROW in SQL Server [duplicate]

What would the syntax be to convert this MS Access query to run in SQL Server as it doesn't have a DistinctRow keyword
UPDATE DISTINCTROW [MyTable]
INNER JOIN [AnotherTable] ON ([MyTable].J5BINB = [AnotherTable].GKBINB)
AND ([MyTable].J5BHNB = [AnotherTable].GKBHNB)
AND ([MyTable].J5BDCD = [AnotherTable].GKBDCD)
SET [AnotherTable].TessereCorso = [MyTable].[J5F7NR];
DISTINCTROW [MyTable] removes duplicate MyTable entries from the results. Example:
select distinctrow items
items.item_number, items.name
from items
join orders on orders.item_id = items.id;
In spite of the join getting you the same item_number and name multiple times when there is more than one order for it, DISTINCTROW reduces this to one row per item. So the whole join is merely for assuring that you only select items for which exist at least one order. You don't find DISTINCTROW in any other DBMS as far as I know. Probably because it is not needed. When checking for existence, we use EXISTS of course (or IN for that matter).
You are joining MyTable and AnotherTable and expect for some reason to get the same MyTable record multifold for one AnotherTable record, so you use DISTINCTROW to only get it once. Your query would (hopefully) fail if you got two different MyTable records for one AnotherTable record.
What the update does is:
update anothertable
set tesserecorso = (select top 1 j5f7nr from mytable where mytable.j5binb = anothertable.gkbinb and ...)
where exists (select * from mytable where mytable.j5binb = anothertable.gkbinb and ...)
But this uses about the same subquery twice. So we'd want to update from a query instead.
The easiest way to get one result record per <some columns> in a standard SQL query is to aggregate data:
select *
from anothertable a
join
(
select j5binb, j5bhnb, j5bdcd, max(j5f7nr) as j5f7nr
from mytable
group by j5binb, j5bhnb, j5bdcd
) m on m.j5binb = a.gkbinb and m.j5bhnb = a.gkbhnb and m.j5bdcd = a.gkbdcd;
How to write an updateble query is different from one DBMS to another. Here is the final update statement for SQL-Server:
update a
set a.tesserecorso = m.j5f7nr
from anothertable a
join
(
select j5binb, j5bhnb, j5bdcd, max(j5f7nr) as j5f7nr
from mytable
group by j5binb, j5bhnb, j5bdcd
) m on m.j5binb = a.gkbinb and m.j5bhnb = a.gkbhnb and m.j5bdcd = a.gkbdcd;
The DISTINCTROW predicate in MS Access SQL removes duplicates across all fields of a table in join statements and not just the selected fields of query (which DISTINCT in practically all SQL dialects do). So consider selecting all fields in a derived table with DISTINCT predicate:
UPDATE [AnotherTable]
SET [AnotherTable].TessereCorso = main.[J5F7NR]
FROM
(SELECT DISTINCT m.* FROM [MyTable] m) As main
INNER JOIN [AnotherTable]
ON (main.J5BINB = [AnotherTable].GKBINB)
AND (main.J5BHNB = [AnotherTable].GKBHNB)
AND (main.J5BDCD = [AnotherTable].GKBDCD)
Another variant of the query.. (Too lazy to get the original tables).
But like the query above updates 35 rows =, so does this one
UPDATE [Albi-Anagrafe-Associati]
SET
[Albi-Anagrafe-Associati].CRegDitte = [055- Registri ditte].[CRegDitte],
[Albi-Anagrafe-Associati].NIscrTribunale = [055- Registri ditte].[NIscrTribunale],
[Albi-Anagrafe-Associati].NRegImprese = [055- Registri ditte].[NRegImprese]
FROM [055- Registri ditte]
WHERE EXISTS(
SELECT *
FROM [055- Registri ditte]-- [Albi-Anagrafe-Associati]
WHERE ([055- Registri ditte].GIBINB = [Albi-Anagrafe-Associati].GKBINB)
AND ([055- Registri ditte].GIBHNB = [Albi-Anagrafe-Associati].GKBHNB)
AND ([055- Registri ditte].GIBDCD = [Albi-Anagrafe-Associati].GKBDCD))
Update [AnotherTable]
Set [AnotherTable].TessereCorso = MyTable.[J5F7NR]
From [AnotherTable]
Inner Join
(
Select Distinct [J5BINB],[5BHNB],[J5BDCD]
,(Select Top 1 [J5F7NR] From MyTable) as [J5F7NR]
,[J5BHNB]
From MyTable
)as MyTable
On (MyTable.J5BINB = [AnotherTable].GKBINB)
AND (MyTable.J5BHNB = [AnotherTable].GKBHNB)
AND (MyTable.J5BDCD = [AnotherTable].GKBDCD)

Update records SQL?

First when I started this project seemed very simple. Two tables, field tbl1_USERMASTERID in Table 1 should be update from field tbl2_USERMASTERID Table 2. After I looked deeply in Table 2, there is no unique ID that I can use as a key to join these two tables. Only way to match the records from Table 1 and Table 2 is based on FIRST_NAME, LAST_NAME AND DOB. So I have to find records in Table 1 where:
tbl1_FIRST_NAME equals tbl2_FIRST_NAME
AND
tbl1_LAST_NAME equals tbl2_LAST_NAME
AND
tbl1_DOB equals tbl2_DOB
and then update USERMASTERID field. I was afraid that this can cause some duplicates and some users will end up with USERMASTERID that does not belong to them. So if I find more than one record based on first,last name and dob those records would not be updated. I would like just to skip and leave them blank. That way I wouldn't populate invalid USERMASTERID. I'm not sure what is the best way to approach this problem, should I use SQL or ColdFusion (my server side language)? Also how to detect more than one matching record?
Here is what I have so far:
UPDATE Table1 AS tbl1
LEFT OUTER JOIN Table2 AS tbl2
ON tbl1.dob = tbl2.dob
AND tbl1.fname = tbl2.fname
AND tbl1.lname = tbl2.lname
SET tbl1.usermasterid = tbl2.usermasterid
WHERE LTRIM(RTRIM(tbl1.usermasterid)) = ''
Here is query where I tried to detect duplicates:
SELECT DISTINCT
tbl1.FName,
tbl1.LName,
tbl1.dob,
COUNT(*) AS count
FROM Table1 AS tbl1
LEFT OUTER JOIN Table2 AS tbl2
ON tbl1.dob = tbl2.dob
AND tbl1.FName = tbl2.first
AND tbl1.LName = tbl2.last
WHERE LTRIM(RTRIM(tbl1.usermasterid)) = ''
AND LTRIM(RTRIM(tbl1.first)) <> ''
AND LTRIM(RTRIM(tbl1.last)) <> ''
AND LTRIM(RTRIM(tbl1.dob)) <> ''
GROUP BY tbl1.FName,tbl1.LName,tbl1.dob
Some data after I tested query above:
First Last DOB Count
John Cook 2008-07-11 2
Kate Witt 2013-06-05 1
Deb Ruis 2016-01-22 1
Mike Bennet 2007-01-15 1
Kristy Cruz 1997-10-20 1
Colin Jones 2011-10-13 1
Kevin Smith 2010-02-24 1
Corey Bruce 2008-04-11 1
Shawn Maiers 2016-08-28 1
Alenn Fitchner 1998-05-17 1
If anyone have idea how I can prevent/skip updating duplicate records or how to improve this query please let me know. Thank you.
You could check for and avoid duplicate matches using with common_table_expression (Transact-SQL)
along with row_number()., like so:
with cte as (
select
t.fname
, t.lname
, t.dob
, t.usermasterid
, NewUserMasterId = t2.usermasterid
, rn = row_number() over (partition by t.fname, t.lname, t.dob order by t2.usermasterid)
from table1 as t
inner join table2 as t2 on t.dob = t2.dob
and t.fname = t2.fname
and t.lname = t2.lname
and ltrim(rtrim(t.usermasterid)) = ''
)
--/* confirm these are the rows you want updated
select *
from cte as t
where t.NewUserMasterId != ''
and not exists (
select 1
from cte as i
where t.dob = i.dob
and t.fname = i.fname
and t.lname = i.lname
and i.rn>1
);
--*/
/* update those where only 1 usermasterid matches this record
update t
set t.usermasterid = t.NewUserMasterId
from cte as t
where t.NewUserMasterId != ''
and not exists (
select 1
from cte as i
where t.dob = i.dob
and t.fname = i.fname
and t.lname = i.lname
and i.rn>1
);
--*/
I use the cte to extract out the sub query for readability. Per the documentation, a common table expression (cte):
Specifies a temporary named result set, known as a common table expression (CTE). This is derived from a simple query and defined within the execution scope of a single SELECT, INSERT, UPDATE, or DELETE statement.
Using row_number() to assign a number for each row, starting at 1 for each partition of t.fname, t.lname, t.dob. Having those numbered allows us to check for the existence of duplicates with the not exists() clause with ... and i.rn>1
You could use a CTE to filter out the duplicates from Table1 before joining:
; with CTE as (select *
, count(ID) over (partition by LastName, FirstName, DoB) as IDs
from Table1)
update a
set a.ID = b.ID
from Table2 a
left join CTE b
on a.FirstName = b.FirstName
and a.LastName = b.LastName
and a.Dob = b.Dob
and b.IDs = 1
This will work provided there are no exact duplicates (same demographics and same ID) in table 1. If there are exact duplicates, they will also be excluded from the join, but you can filter them out before the CTE to avoid this.
Please try below SQL:
UPDATE Table1 AS tbl1
INNER JOIN Table2 AS tbl2
ON tbl1.dob = tbl2.dob
AND tbl1.fname = tbl2.fname
AND tbl1.lname = tbl2.lname
LEFT JOIN Table2 AS tbl3
ON tbl3.dob = tbl2.dob
AND tbl3.fname = tbl2.fname
AND tbl3.lname = tbl2.lname
AND tbl3.usermasterid <> tbl2.usermasterid
SET tbl1.usermasterid = tbl2.usermasterid
WHERE LTRIM(RTRIM(tbl1.usermasterid)) = ''
AND tbl3.usermasterid is null

Update a table using JOIN in SQL Server?

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'

Resources