Update 2nd Table Based Upon Rows Updated In First Table - sql

I have two tables jhead and jjops. I am updating jhead with the following statement:
UPDATE jhead h
SET h.jhpcmp = 1
WHERE h.jhpcmp = '0' AND h.jhpqty <= h.jhqtys
But now I want to update jjops based upon what I updated in jhead. The statement would be like:
UPDATE jjops j
SET j.jascmp = 1, japcmp = 1
WHERE (This is where I am stuck)
What links the two tables is the following: h.jhjob = j.jajob
Is there some way to update both of the tables together? Should I first update table jjops using a join and then update table jhead and if so what Join should I use?

The way to update two tables "at the same time" is to use a transaction. You can use the output clause as one way to pass stuff from one statement to the next. SQL Server also has a special syntax for joining in an update statement (see the second update)
Declare #ids table (jhjob int not null) -- replace with correct data type
Begin Transaction
Update
jhead
Set
jhpcmp = 1
output
inserted.jhjob into #ids
Where
jhpcmp = '0' And
jhpqty <= jhqtys
Update
jjops
Set
jascmp = 1,
japcmp = 1
From
jjops j
inner join
#ids h
on j.jajob = h.jhjob
Commit Transaction

Related

PL/SQL Update Query

Attempting to update a table I have created with null values from another table I have created in PL/SQL:
I was able to utilize the below update in SQL Server but am running into issues within PL/SQL (dont ask why I am running it in both)
Overall_Inventory = Table created with some populated values and some null valuse; this is the table requiring updates to those null values
task_table = Table also created, but contains value needing to be updated into T1
update dbh.overall_inventory
set dbh.overall_inventory.case_due_date = tsk.TASK_ACTION_TIMESTAMP
from dbh.overall_inventory,
(SELECT tsk.INQ_KEY,
min(tsk.TASK_ACTION_TIMESTAMP) as TASK_ACTION_TIMESTAMP
FROM dbh.task_table tsk
inner join dbh.overall_inventory Inv
on tsk.INQ_KEY = inv.inq_key
where tsk.ACTION_CD = '324'
group by tsk.INQ_KEY
) tsk
where tsk.INQ_KEY = dbh.overall_inventory.inq_key`
Oracle doesn't support from clause in the update statement. In this situation merge statement can be used.
merge into overall_inventory oi
using (select tsk.inq_key,
min(tsk.task_action_timestamp) as task_action_timestamp
from task_table tsk
join overall_inventory Inv
on tsk.inq_key = inv.inq_key
where tsk.action_cd = '324'
group by tsk.inq_key) tsk
on (tsk.inq_key = oi.inq_key )
when matched then
update
set case_due_date = tsk.task_action_timestamp
where case_due_date is null -- as I understood only NULL values
-- need to be updated
Note: Not tested because no sample data and desired result were provided.
I think you're looking for update over a select:
UPDATE (
  SELECT product_id, category_id
  FROM product) st
SET st.category_id = 5
WHERE st.category_id = 4;

Using a LEFT OUTER JOIN WHERE then updating same data

I have two databases running on MSSQL 2005, SOURCE and DESTINATION, which have the same structure and tables in them.
I'm trying to update data from s to d.
In this example, I'm trying to copy data from s to d using a join and only bringing across entries which aren't already in d.
I'm then trying to update the same records just inserted with vales thus:
INSERT DESTINATION.ITEM_REPLENISH_VENDOR ([ITEM_CODE],[VEND_CODE],[PRIMARY_VENDOR],[PURCHASE_MEASURE],[STD_COST],[LAST_COST],[EOQ],[VENDOR_PART_NO],[LEAD_TIME],[COST])
SELECT s.[ITEM_CODE],s.[VEND_CODE],s.[PRIMARY_VENDOR],s.[PURCHASE_MEASURE],s.[STD_COST],s.[LAST_COST],s.[EOQ],s.[VENDOR_PART_NO],s.[LEAD_TIME], s.[COST] FROM SOURCE.dbo.ITEM_REPLENISH_VENDOR s
LEFT OUTER JOIN DESTINATION.dbo.ITEM_REPLENISH_VENDOR d ON (d.ITEM_CODE = s.ITEM_CODE)
WHERE d.ITEM_CODE IS NULL
UPDATE DESTINATION.dbo.ITEM_REPLENISH_VENDOR
SET VEND_CODE='100004', PRIMARY_VENDOR='T',STD_COST='0',LAST_COST='0',COST='0'
WHERE
My issue is once I reach the second WHERE I don't know how to refer to the data I've just updated. This script is going to run either every day at a set time and I don't want to overwrite that whole column with those values, just the entries that have been inserted on this execution.
It looks like you want the output clause This will let you stash away the inserted values.
-- item_code needs to have the same type as the source table
declare #inserted table (item_code int not null primary key);
insert destination.item_replenish_vendor (
[item_code], [vend_code], [primary_vendor],
[purchase_measure], [std_cost], [last_cost],
[eoq], [vendor_part_no], [lead_time],[cost]
) -- save inserted values
output
inserted.item_code into #inserted
select
s.[item_code], s.[vend_code], s.[primary_vendor],
s.[purchase_measure], s.[std_cost], s.[last_cost],
s.[eoq], s.[vendor_part_no], s.[lead_time], s.[cost]
from
source.dbo.item_replenish_vendor s
left outer join
destination.dbo.item_replenish_vendor d
on d.item_code = s.item_code
where
d.item_code is null;
update
d
set
vend_code = '100004',
primary_vendor = 'T',
std_cost = '0',
last_cost = '0,
cost = '0'
from
destination.dbo.item_replenish_vendor d
inner join
#inserted i
on d.item_code = i.item_code;
In this case, you could just put constant values in the insert statement, instead of doing things in two steps...
In the example you have:
UPDATE DESTINATION.dbo.ITEM_REPLENISH_VENDOR
SET VEND_CODE='100004', PRIMARY_VENDOR='T',STD_COST='0',LAST_COST='0',COST='0'
If your VEND_CODE, PRIMARY_VENDOR, STD_COST, LAST_COST, COST are always going to be a static value, you could just put them into the first query.
INSERT DESTINATION.ITEM_REPLENISH_VENDOR ([ITEM_CODE],[VEND_CODE],[PRIMARY_VENDOR],[PURCHASE_MEASURE],[STD_COST],[LAST_COST],[EOQ],[VENDOR_PART_NO],[LEAD_TIME],[COST])
SELECT s.[ITEM_CODE],'100004','T',s.[PURCHASE_MEASURE],'0','0',s.[EOQ],s.[VENDOR_PART_NO],s.[LEAD_TIME], '0'
FROM SOURCE.dbo.ITEM_REPLENISH_VENDOR s
LEFT OUTER JOIN DESTINATION.dbo.ITEM_REPLENISH_VENDOR d ON (d.ITEM_CODE = s.ITEM_CODE)
WHERE d.ITEM_CODE IS NULL
but if they do need to be calculated after insert, then I agree with Laurence's approach.

How to update on Two Tables

I need to make an update in a table based on other information.
How to proceed?
My case is:
I have a column iniciantes table MEMB_INFO
I need to make an update MEMB_INFO SET iniciantes = 0
But I need to make a query on WHERE table column resets the character table
Example:
UPDATE MEMB_INFO
SET iniciantes = 0
FROM MEMB_INFO CROSS JOIN
Character
WHERE (Character.Resets >= 100)
necessary that the update the memb_info only occur in cases where the reference character is greater than or equal to 100
Simply, join MEMB_INFO with your Character table and specify their relations:
update m
set iniciantes = 0
from MEMB_INFO m
inner join Character c on
c.Resets >= 100
AND m.CharacterId = c.CharacterId --Specify your tables' relations.
you have to specify columns on which you're joining this two tables. If you have characterId column in both tables, your query will be:
update MEMB_INFO set
iniciantes = 0
from MEMB_INFO as m
where
m.CharacterId in (
select c.CharacterId from Character as c where c.Reset >= 100
)

SQL update with count gets only nulls

I am using SQL Server 2008 R2 and SSRS 2008 to generate the report. I am trying to update a table to get a count of the results from another table.
UPDATE r
SET r.Race = d2.Race,
r.RaceNum = d2.count
FROM #results r
INNER JOIN
(SELECT d.Race,
COUNT(d.race) AS 'count'
FROM #Demographic d
GROUP BY d.Race)d2 ON r.Race = d2.Race
An insert works perfectly but I am inserting several times into the results table to create a demographics report. This is creating a lot Null data at the table of the results. If anyone has an idea of what I am going wrong the help would be appreciated.
Not certain, but first guess is that count is a reserved word... change it to something else such as...
update r
set r.Race = d2.Race, r.RaceNum = d2.cnt
from #results r
inner join
(select d.Race, COUNT(d.race) as 'cnt' from #Demographic d group by d.Race)d2
on r.Race = d2.Race
or alternatively try delimiting the column identifier as [count] or if you have quoted identifiers on "count"
Your query is:
update r
set r.Race = d2.Race, /*<---------*/
r.RaceNum = d2.count
from #results r inner join
(select d.Race, COUNT(d.race) as 'count'
from #Demographic d
group by d.Race
) d2
on r.Race = d2.Race /*<-------- */
The two marked lines stand out. You are joining on values using =, then you are setting one equal to the other. This may not be the problem, but it is suspicious. If you are joining on them, why are you setting them equal? My suspicion is that the join is failing, because nothing matches it.
You don't need to update the race column, since that's the equality portion of your join.
As written, any race not in #demographic would have its racenum set to null. If you want 0 for those try:
UDPATE
r
SET
r.RaceNum = ISNULL(d2.ct, 0)
FROM #results r
LEFT JOIN
(
SELECT
d.Race
, COUNT(d.race) as ct
FROM
#Demographic d
GROUP BY
d.Race
) d2
ON
r.Race = d2.Race

SQL Server 2008 R2 Trigger multiple rows in a single batch update issue

I have implemented a trigger in SQL Server 2008 R2 in this way -
ALTER TRIGGER [dbo].[trgtblOrgStaffAssocLastUpdate] ON [dbo].[tblOrgStaffAssoc]
AFTER UPDATE
AS
IF EXISTS (SELECT i.* FROM INSERTED i inner join deleted d on i.ORG_ID = d.ORG_ID and isnull(i.StaffType, -1111) = isnull(d.StaffType, -1111)
where i.Deleted = 0
and (isnull(i.PER_ID, cast(cast(0 as binary) as uniqueidentifier)) <> isnull(d.PER_ID, cast(cast(0 as binary) as uniqueidentifier))
))
BEGIN
IF EXISTS (SELECT * FROM DELETED)
BEGIN
--UPDATE PER_ID
update l
set PER_ID = 1, UpdatedOn = GETDATE()
from dbo.tblOrgStaffAssocLastUpadate l inner join [dbo].[inserted] i on l.ORG_ID = i.ORG_ID and l.StaffType = i.StaffType
inner join [dbo].[deleted] d on i.ORG_ID = d.ORG_ID and i.StaffType = d.StaffType
where isnull(i.PER_ID, cast(cast(0 as binary) as uniqueidentifier)) <> isnull(d.PER_ID, cast(cast(0 as binary) as uniqueidentifier))
END
END
My purpose is to update tblOrgStaffAssocLastUpadate when tblOrgStaffAssoc is updated. For only one row, it works fine. However for multiple rows send over in one batch, it updates one row only in tblOrgStaffAssocLastUpadate while tblOrgStaffAssoc has multiple rows updated.
When I use a intermediate tables _Inserted and _deleted to buffer the INSERTED and DELETED data and use the permanent tables to update like this way -
ALTER TRIGGER [dbo].[trgtblOrgStaffAssocLastUpdate] ON [dbo].[tblOrgStaffAssoc]
AFTER UPDATE
AS
IF EXISTS (SELECT i.* FROM INSERTED i inner join deleted d on i.ORG_ID = d.ORG_ID and isnull(i.StaffType, -1111) = isnull(d.StaffType, -1111)
where i.Deleted = 0
and (isnull(i.PER_ID, cast(cast(0 as binary) as uniqueidentifier)) <> isnull(d.PER_ID, cast(cast(0 as binary) as uniqueidentifier))
))
BEGIN
IF EXISTS (SELECT * FROM DELETED)
BEGIN
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[_inserted]') AND type in (N'U'))
insert into [dbo].[_inserted]
select * from inserted
else
select * into [dbo].[_inserted]
from inserted
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[_deleted]') AND type in (N'U'))
insert into [dbo].[_deleted]
select * from deleted
else
select * into [dbo].[_deleted]
from deleted
--UPDATE PER_ID
update l
set PER_ID = 1, UpdatedOn = GETDATE()
from dbo.tblOrgStaffAssocLastUpadate l inner join [dbo].[_inserted] i on l.ORG_ID = i.ORG_ID and l.StaffType = i.StaffType
inner join [dbo].[_deleted] d on i.ORG_ID = d.ORG_ID and i.StaffType = d.StaffType
where isnull(i.PER_ID, cast(cast(0 as binary) as uniqueidentifier)) <> isnull(d.PER_ID, cast(cast(0 as binary) as uniqueidentifier))
END
END
It works fine. Changing permanent table _Inserted to use #inserted or table variable #inserted does not work either.
Apparently using permanent table is not a good idea. I don't know how the trigger works in this way. Can anyone help out?
Thanks
Edit to answer #usr's comment -
It does not work correctly if I use -
update l set PER_ID = 1, UpdatedOn = GETDATE() from dbo.tblOrgStaffAssocLastUpadate l inner join [dbo].[inserted] i on l.ORG_ID = i.ORG_ID and l.StaffType = i.StaffType inner join [dbo].[deleted] d on i.ORG_ID = d.ORG_ID and i.StaffType = d.StaffType where isnull(i.PER_ID, cast(cast(0 as binary) as uniqueidentifier)) <> isnull(d.PER_ID, cast(cast(0 as binary) as uniqueidentifier))
Only one row is updated. The rest rows are not updated at all. Even though I can see multiple rows returned if I use
select l.* from dbo.tblOrgStaffAssocLastUpadate l inner join [dbo].[inserted] i on l.ORG_ID = i.ORG_ID and l.StaffType = i.StaffType inner join [dbo].[deleted] d on i.ORG_ID = d.ORG_ID and i.StaffType = d.StaffType where isnull(i.PER_ID, cast(cast(0 as binary) as uniqueidentifier)) <> isnull(d.PER_ID, cast(cast(0 as binary) as uniqueidentifier))
right before the update statement. That is where I am totally confused why the next update statement only updates one row only, and why only permanent table can persist all the rows update but not temporary table and table variables.
Updated question -
Since multiple update rows are send to the table in a single batch. It seems that the trigger's INSERT and DELETE table only one and the last one update row only at the time when I reach " update l " statement. Before that it holds multiple update rows. I can see that when I use permanent tables. I just don't understand SQL Server behave in this way. Anyone saw the same thing?
You are seriously over-complicating this. You do not need all those checks and links between INSERTED and DELETED.
This is a trigger on UPDATE only, therefore, there will always be a DELETED table that contains for each changed row what was in the table and there will always be an INSERTED that contains for each changed row what will be in the table. So for your purposes you only need to deal with one of these tables. Rows that are not changed are in neither table.
If this was a trigger on INSERT there would only be an INSERTED table. Similarly, a DELETE trigger only has a DELETED table.
Secondly, you seem to think that NULL=NULL is true - it isn't. The statement NULL=NULL returns NULL. So does NULL<>NULL, NULL>=NULL etc. etc. In a database NULL means not a value and something that does not have a value is incomparable. So your where statement is also superfluous.
So I think the code you want is:
ALTER TRIGGER [dbo].[trgtblOrgStaffAssocLastUpdate] ON [dbo].[tblOrgStaffAssoc]
AFTER UPDATE
AS
UPDATE l
SET PER_ID = 1
,UpdatedOn = GETDATE()
FROM dbo.tblOrgStaffAssocLastUpadate l
INNER JOIN
inserted i ON l.ORG_ID = i.ORG_ID and l.StaffType = i.StaffType