How to update two different tables using a single UPDATE statement - sql

I am trying to update two tables with a single statement like this
db2 update catentry, catentdesc
set catentry.buyable=0,
catentdesc.published=0
where catentry.catentry_id=catentdesc.catentry_id
and catentry.partnumber='some value'
but getting an error
How can I accomplish this?

Set DB2 CLP to autocommit OFF and use ; command terminator:
db2 +c -t
update catentry set buyable=0 where partnumber='some value';
update catentdesc set published=0 where catentry_id IN
(SELECT catentry_id FROM catentry where partnumber='some value');
commit;

Not sure why you want to do this in a single statement, but recent versions of DB2 for LUW (and, with some restrictions, DB2 for z/OS) support what is called data change table references that allow tricks like
WITH t1 (catentry_id) AS (
SELECT catentry_id FROM FINAL TABLE (
UPDATE catentry SET buyable = 0 WHERE partnumber = 'some value'
)
), t2 (catentry_id) AS (
SELECT catentry_id FROM FINAL TABLE (
UPDATE catentdesc SET published = 0 WHERE catentry_id = (
SELECT catentry_id FROM t1
)
)
) SELECT 1 FROM sysibm.sysdummy1
Note that the actual statement must be a SELECT from something, and UPDATE statements are also wrapped in their own SELECTs, but this is executed as a single statement.

Related

Not able to update columns of a table by bind parameters using sql developer

The following select statement returns one row:
SELECT *
FROM CM_APOLLO_DET
WHERE
CM_APOLLO_DET.DETAIL_ID = TRIM(:detailId) AND
CM_APOLLO_DET.HEADER_ID IN (SELECT HEADER_ID FROM CM_APOLLO_HDR
WHERE TRIM(FILE_NAME) = TRIM(:fileName));
Values of bind parameters are as follows:
detailId: 775686609762
filename:sample3.txt
but when I run following update statement, it updates zero rows.
UPDATE CM_APOLLO_DET
SET CM_APOLLO_DET.DIVISION = :div
WHERE
CM_APOLLO_DET.DETAIL_ID = TRIM(:detailId) AND
CM_APOLLO_DET.HEADER_ID IN (SELECT HEADER_ID FROM CM_APOLLO_HDR
WHERE TRIM(FILE_NAME) = TRIM(:fileName));
div=2030
detailId: 775686609762
filename:sample3.txt
This update where condition is same as above select statement.
You can try below using exists
update CM_APOLLO_DET set CM_APOLLO_DET.DIVISION=:div
where CM_APOLLO_DET.DETAIL_ID=trim(:detailId) and
exists (SELECT 1 from
CM_APOLLO_HDR where CM_APOLLO_DET.HEADER_ID=CM_APOLLO_HDR.HEADER_ID
and trim(FILE_NAME)=trim(:fileName)
);

Update and Insert Trigger

I have four tables which constantly truncate then inserts and updates data every five minutes from another system into SQL Server. So I need to create an update and insert trigger to update another in SQL Server using if exists or merge.
Select
[Barcode]
,[TradingPartnerOrderNo]
,[ProductNo]
,[BarcodeCreatedDateTime]
,[BarcodeScheduledDateTime]
,[CancelledIndicator]
,[CancelledDateTime]
,[SiteIndicator]
,[InterfaceTimeStamp]
,[OperationDate]
,[Operation]
from [dbo].[BookingView]
For me it is not very clear your demande but here is a trigger example :
CREATE TRIGGER [dbo].[up_update_mytable]
ON [dbo].[MyTable] FOR UPDATE
AS
DECLARE #ID VARCHAR(50)
SELECT #ID = ID FROM INSERTED --Use INSERTED keyword for insert and update triggers to get informations of the inserted or updated record.
UPDATE MyOtherTable SET
Column1 = 'test value',
Column2 = 'test value 2'
WHERE OtherTableID = #ID
If you are using SQL Server 2008+, then you can use MERGE to do that. Something like this:
MERGE INTO table2 AS TGT
USING
(
Select
[Barcode]
,[TradingPartnerOrderNo]
,[ProductNo]
,[BarcodeCreatedDateTime]
,[BarcodeScheduledDateTime]
,[CancelledIndicator]
,[CancelledDateTime]
,[SiteIndicator]
,[InterfaceTimeStamp]
,[OperationDate]
,[Operation]
FROM [dbo].[BookingView]
) AS SRC ON SRC.Barcode = TGT.BarCode AND
WHEN NOT MATCHED THEN
INSERT (Barcode, TradingPartnerOrderNo, ...)
VALUES (SRC.Barcode, SRC.TradingPartnerOrderNo, ...);

How to update all of the values of a table using merge into statement

How to update all the values from source table to destination table using merge into statement?
What I am trying to do is something like:
merge into src_table
using (select * from dest) dest_table
on (<some_condition>)
when matched then update set src_table.* = dest_table.*
where <condition>
I didn't find anything related to this on Google. I know one can achieve this using execute immediate style statement but I am looking for a better way.
you can do it with pl/sql
for src in ( select * from B ) loop
update A set ROW = src where A.id = src.id;
end loop;
or you can use alter table;
alter table your_table
rename to
your_new_table;

CTE with insert and update in sql server 2008 [duplicate]

This question already has answers here:
How can I reuse a Common Table Expression
(2 answers)
Closed 8 years ago.
I am using SQL Server 2008 and I want to know if I can use CTE with insert and update together e.g. if one condition fails then insert else update.
With X As
(
Select COMP
From comp
)
IF EXISTS ( Select * From A Where A.COMP = X.COMP )
Insert Into A (COMP,comp1)
select X.COMP, #COMP1 from X
Else
Update A set comp1=#comp1
where comp= X.Comp
I have tried to use
With X As
(
Select COMP
From comp
)
Insert Into A (COMP,comp1)
select X.COMP, #COMP1 from X
With Y As
(
Select COMP
From comp
)
Update A set comp1=#comp1
join Y on comp= Y.Comp
But if it is a insert then it is inserting the record and also it is executing the Update block . Can you tell me how to avoid that with If statement.
As you can only use CTE once after it is declared, you cannot used it in both INSERT and UPDATE statements.
As you cannot use MERGE due to constraints out of your control, as you say, you can use a temporary table instead:
Select COMP
into #temp
From comp
IF EXISTS ( Select * From A Where A.COMP = #temp.COMP )
Insert Into A (COMP,comp1)
select #temp.COMP, #COMP1 from #temp
Else
Update A set comp1=#comp1 where comp= #temp.Comp
A WITH clause can only be used with a single SELECT, INSERT, UPDATE or DELETE statement. It cannot be used with an IF or any other statement. That you've already been told in comments.
The reason why your second attempt, where you are trying to use separate WITH clauses for INSERT and UPDATE, fails is probably because there is no semicolon at the end of the INSERT statement. The WITH keyword has multiple uses in Transact-SQL and sometimes it is expected in the middle of the statement while at other times it goes at the beginning. To avoid ambiguity, a semicolon is made mandatory (in SQL Server 2008 and later version) at the end of a statement if the next statement begins with a WITH clause.
But actually it would be a good idea to get into the habit of using semicolons anyway.
So, this is how you should run these two statements together:
With X As
(
Select COMP
From comp
)
Insert Into A (COMP,comp1)
select X.COMP, #COMP1 from X; /* <-- this semicolon is required */
With Y As
(
Select COMP
From comp
)
Update A set comp1=#comp1
join Y on comp= Y.Comp; /* <-- this one is optional,
but why not make things consistent? */

IF UPDATE() in SQL server trigger

If there's:
IF UPDATE (col1)
...in the SQL server trigger on a table, does it return true only if col1 has been changed or been updated?
I have a regular update query like
UPDATE table-name
SET col1 = 'x',
col2 = 'y'
WHERE id = 999
Now what my concern is if the "col1" was 'x' previously then again we updated it to 'x'
would IF UPDATE ("col1") trigger return True or not?
I am facing this problem as my save query is generic for all columns, but when I add this condition it returns True even if it's not changed...So I am concerned what to do in this case if I want to add condition like that?
It returns true if a column was updated. An update means that the query has SET the value of the column. Whether the previous value was the same as the new value is largely irelevant.
UPDATE table SET col = col
it's an update.
UPDATE table SET col = 99
when the col already had value 99 also it's an update.
Within the trigger, you have access to two internal tables that may help. The 'inserted' table includes the new version of each affected row, The 'deleted' table includes the original version of each row. You can compare the values in these tables to see if your field value was actually changed.
Here's a quick way to scan the rows to see if ANY column changed before deciding to run the contents of a trigger. This can be useful for example when you want to write a history record, but you don't want to do it if nothing really changed.
We use this all the time in ETL importing processes where we may re-import data but if nothing really changed in the source file we don't want to create a new history record.
CREATE TRIGGER [dbo].[TR_my_table_create_history]
ON [dbo].[my_table] FOR UPDATE AS
BEGIN
--
-- Insert the old data row if any column data changed
--
INSERT INTO [my_table_history]
SELECT d.*
FROM deleted d
INNER JOIN inserted i ON i.[id] = d.[id]
--
-- Use INTERSECT to see if anything REALLY changed
--
WHERE NOT EXISTS( SELECT i.* INTERSECT SELECT d.* )
END
Note that this particular trigger assumes that your source table (the one triggering the trigger) and the history table have identical column layouts.
What you do is check for different values in the inserted and deleted tables rather than use updated() (Don't forget to account for nulls). Or you could stop doing unneeded updates.
Trigger:
CREATE TRIGGER boo ON status2 FOR UPDATE AS
IF UPDATE (id)
BEGIN
SELECT 'DETECT';
END;
Usage:
UPDATE status2 SET name = 'K' WHERE name= 'T' --no action
UPDATE status2 SET name = 'T' ,id= 8 WHERE name= 'K' --detect
To shortcut the "No actual update" case, you need also check at the beginning whether your query affected any rows at all:
set nocount on; -- this must be the first statement!
if not exists (select 1 from inserted) and not exists (select 1 from deleted)
return;
SET NOCOUNT ON;
declare #countTemp int
select #countTemp = Count (*) from (
select City,PostCode,Street,CountryId,Address1 from Deleted
union
select City,PostCode,Street,CountryId,Address1 from Inserted
) tempTable
IF ( #countTemp > 1 )
Begin
-- Your Code goes Here
End
-- if any of these "City,PostCode,Street,CountryId,Address1" got updated then trigger
-- will work in " IF ( #countTemp > 1 ) " Code)
This worked for me
DECLARE #LongDescDirty bit = 0
Declare #old varchar(4000) = (SELECT LongDescription from deleted)
Declare #new varchar(4000) = (SELECT LongDescription from inserted)
if (#old <> #new)
BEGIN
SET #LongDescDirty = 1
END
Update table
Set LongDescUpdated = #LongDescUpdated
.....