Merge Statement overwriting entire row if Matched - tsql

I am trying to update records in a Sql Server 2012 table by using a MERGE statement. I have my target table and my source staging table. When the ID field matches I want to replace the entire row with the matching row from the source, and if not, add the row to the table as a new row. I don't know what to write after update set (?) to achieve this. here is my code:
USE DataCompany
MERGE INTO MasterAddress ma
USING MasterAddressStaging ms
ON MasterAddress.ID = MasterAddressStaging.ID
WHEN MATCHED THEN
UPDATE SET (?)
WHEN NOT MATCHED THEN
INSERT (ID
,CompanyName
,CompanyNumber
,RegAddress_CareOf
,RegAddress_POBox
,RegAddress_AddressLine1
,RegAddress_AddressLine2
,RegAddress_PostTown
,RegAddress_County
,RegAddress_Country
,RegAddress_PostCode)
VALUES (ms.ID
,ms.CompanyName
,ms.CompanyNumber
,ms.RegAddress_CareOf
,ms.RegAddress_POBox
,ms.RegAddress_AddressLine1
,ms.RegAddress_AddressLine2
,ms.RegAddress_PostTown
,ms.RegAddress_County
,ms.RegAddress_Country
,ms.RegAddress_PostCode);
thanks for your help

USE DataCompany
MERGE INTO MasterAddress ma
USING MasterAddressStaging ms
ON ma.ID = ms.ID
WHEN MATCHED THEN
UPDATE SET ma.CompanyName = ms.CompanyName,
ma.CompanyNumber = ms.CompanyNumber,
ma.RegAddress_CareOf =ms.RegAddress_CareOf,
ma.RegAddress_POBox =ms.RegAddress_POBox,
ma.RegAddress_AddressLine1 = ms.RegAddress_AddressLine1,
ma.RegAddress_AddressLine2 = ms.RegAddress_AddressLine2,
ma.RegAddress_PostTown = ms.RegAddress_PostTown,
ma.RegAddress_County = ms.RegAddress_County,
ma.RegAddress_Country = ms.RegAddress_Country,
ma.RegAddress_PostCode = ms.RegAddress_PostCode
WHEN NOT MATCHED THEN
INSERT (ID
,CompanyName
,CompanyNumber
,RegAddress_CareOf
,RegAddress_POBox
,RegAddress_AddressLine1
,RegAddress_AddressLine2
,RegAddress_PostTown
,RegAddress_County
,RegAddress_Country
,RegAddress_PostCode)
VALUES (ms.ID
,ms.CompanyName
,ms.CompanyNumber
,ms.RegAddress_CareOf
,ms.RegAddress_POBox
,ms.RegAddress_AddressLine1
,ms.RegAddress_AddressLine2
,ms.RegAddress_PostTown
,ms.RegAddress_County
,ms.RegAddress_Country
,ms.RegAddress_PostCode);
See examples here

Related

I want to add database triggers to record changes to the RESB table in SAP HANA to enable delta extraction

We are running ECC6 on HANA, currently the extraction of RESB does a full table scan. I want to record that a change has happened to a Z table (I don't care what change).
I've attempted to create the triggers (in Word) from Help & Google, I would appreciate any suggestions for improvement.
create trigger tr_RESB_insert
after insert on RESB
referencing new row NR
for each row
begin
insert into ZBW_RESB_CDC (
MANDT
,RSNUM
,RSPOS
,RSART
,CHNGIND
,AEDAT
,AEZEIT
,AETMSTMP
,TZONE
,DELFLG )
values ( NR.MANDT
, NR.RSNUM
, NR.RSPOS
, NR.RSART
, ‘I’
, current_utcdate
, current_utctime
, current_utctimestamp
, ‘UTC’
,’ ’
)
end;
and
create trigger tr_RESB_update
after update on RESB
referencing new row NR
for each row
begin
merge ZBW_RESB_CDC as T
using NR
on ( NR.MANDT = T.MANDT and
,NR.RSNUM = T.RSNUM and
,NR.RSPOS = T.RSPOS and
,NR.RSART = T.RSART )
when matched then update
set T.CHNGIND = ‘U’
,T.AEDAT = current_utcdate
,T.AEZEIT = current_utctime
,T.AETMSTMP = current_utctimestamp
,T.TZONE = ‘UTC’
,T.DELFLG = ‘ ’
when not matched then insert (
MANDT
,RSNUM
,RSPOS
,RSART
,CHNGIND
,AEDAT
,AEZEIT
,AETMSTMP
,TZONE
,DELFLG )
values ( NR.MANDT
,NR.RSNUM
,NR.RSPOS
,NR.RSART
, ‘U’
, current_utcdate
, current_utctime
, current_utctimestamp
, ‘UTC’
,’ ’
end;
similarly for delete
At some time we'll upgrade to S4 but for the moment I would like to improve what we have.
I chose to use MERGE so that I don't need to initialise the table and so I can delete old records. Nor do I want to keep images of every change, just the fact that it has changed.
Thanks,
G.

sql update table condition depends on other rows in the same table

I have the following table
id,link_id,url,type,download,filename
44,11,https://google.com,extra,1,126cd08a-b963-48e5-878e-96dea057d57e.jpg
45,11,https://google.com,extra,0,53bfa01d-91d0-4b84-9389-b06e5e4ef618.jpg
46,11,https://google.com,extra,0,364cfdc2-c0b6-43fc-8936-33e49896014a.jpg
47,12,https://google.com,extra,0,9d26efbd-e6e0-42df-bde0-04c05babffe4.jpg
48,13,https://yahoo.com,extra,0,2d58b9f7-1860-40d8-88f0-9fc08cd7275f.jpg
49,13,https://yahoo.com,extra,0,574b1646-6316-4a4b-8e28-56c38c0999b9.jpg
...
I want to write a query to check download=1 and update all the rows with the same url and downoload=0 to set the same filename and download=1
so the output would be
44,11,https://google.com,extra,1,126cd08a-b963-48e5-878e-96dea057d57e.jpg
45,11,https://google.com,extra,1,126cd08a-b963-48e5-878e-96dea057d57e.jpg
46,11,https://google.com,extra,1,126cd08a-b963-48e5-878e-96dea057d57e.jpg
47,12,https://google.com,extra,1,126cd08a-b963-48e5-878e-96dea057d57e.jpg
48,13,https://yahoo.com,extra,0,2d58b9f7-1860-40d8-88f0-9fc08cd7275f.jpg
49,13,https://yahoo,extra,0,574b1646-6316-4a4b-8e28-56c38c0999b9.jpg
demo:db<>fiddle
UPDATE mytable t
SET download = s.download, filename = s.filename -- 3
FROM (
SELECT url, download, filename -- 1
FROM mytable
WHERE download = 1
) s
WHERE t.url = s.url -- 2
Find the expected record with download = 1
Find all related url records
Update the columns with the data fetched in step 1

Update columns based on different criteria using merge statement

So I am using the following merge statement to do an update and insert in one of my tables, however I would like to update another column in the Target table in addition to the one already in the statement. I'm just not sure if I can do that or how to go about it. What I want to do is add in something like
when MATCHED and Source.EventType='Change' Then UPDATE SET Target.DEDCAMT_1 = Source.EmpDedAmt
Can I do that in the same Merge statement?
MERGE dbo.BENTBL as Target
using dbo.BenPaycdUpdate as Source
ON Source.EmpID = Target.EMPLOYID AND Source.Paycode = Target.DEDUCTON
WHEN MATCHED AND source.EventType='Stop'
THEN UPDATE
SET INACTIVE = '1',
Target.DEDENDDT = Source.AsOfDate
WHEN NOT MATCHED BY Target
AND Source.PayCode <> 'FSAH'
THEN INSERT (EMPLOYID, DEDUCTON, INACTIVE, DEDBEGDT, DEDCAMNT_1)
VALUES (Source.EmpID, Source.Paycode,'0', Source.AsofDate,
CAST(REPLACE (REPLACE(ISNULL(source.EmpDed,0),',',''),'$','') AS numeric(19,5)));
You can move the condition from the merge to a case expression, like this:
MERGE dbo.BENTBL as Target
using dbo.BenPaycdUpdate as Source
ON Source.EmpID = Target.EMPLOYID AND Source.Paycode = Target.DEDUCTON
WHEN MATCHED THEN
UPDATE
SET INACTIVE = CASE WHEN source.EventType = 'Stop' THEN '1' ELSE INACTIVE END,
Target.DEDCAMT_1 = CASE WHEN source.EventType = 'Change' THEN Source.EmpDedAmt ELSE Target.DEDCAMT_1 END,
Target.DEDENDDT = Source.AsOfDate
WHEN NOT MATCHED BY Target AND Source.PayCode <> 'FSAH' THEN
INSERT (EMPLOYID, DEDUCTON, INACTIVE, DEDBEGDT, DEDCAMNT_1)
VALUES (Source.EmpID, Source.Paycode,'0', Source.AsofDate,
CAST(REPLACE (REPLACE(ISNULL(source.EmpDed,0),',',''),'$','') AS numeric(19,5)));

How do you identify the triggers associated with a table in a informix database?

How can we identify the triggers associated with a table in a Informix database?
select tabname,a.* from systriggers a, systables b
where a.tabid=b.tabid and tabname="TableName"
or
dbschema -d db -t tablename
The information is in the SysTriggers and SysTrigBody system catalog tables — primarily SysTriggers. You can find the description of these (and all other system catalog tables) in the Informix Guide to SQL: Reference manual. You can find that at the Informix 11.70 Info Centre. In particular, the tabid (from SysTables) identifies the triggers for a table in SysTriggers.
As Jonathan answered you can use systriggers and other system catalog tables. I used them in my schema reporting utility: http://code.activestate.com/recipes/576621-dump-informix-schema-to-text/
This utility can work with Python and ODBC or with Jython and JDBC. It shows info about trigger for every table like:
--- triggers ---
defbookacc defbookacc_dtrg D
defbookacc defbookacc_itrg I
defbookacc defbookacc_utrg U
mc_loadman loadman_del D
and then shows body for each trigger.
--OBTIENE LOS TRIGGERS DE LA TABLA:
SELECT T.tabid, TRIM(T.owner) owner, T.tabname, TR.trigid, TRIM(TR.owner) tr_owner, TR.trigname, TR.event, TR.old, TR.new, TR.mode, TRIM(TR.collation) collation,
TB.datakey, TB.seqno, TB.data
FROM systables T, systriggers TR, systrigbody TB
WHERE T.tabname = 'table_name' AND TR.tabid = T.tabid AND TB.trigid = TR.trigid AND TB.datakey IN ('D', 'A')
ORDER BY TB.trigid, TB.datakey DESC, TB.seqno ASC;
--Event: type of triggering event: D = Delete trigger, I = Insert trigger ,U = Update trigger ,S = Select trigger , d = INSTEAD OF Delete trigger , i = INSTEAD OF Insert trigger ,u = INSTEAD OF Update trigger (IDS)
--Old: Name of value before update.
--New: Name of value after update.
--DataKey: Code specifying the type of data: A = ASCII text for the body, triggered actions, B = Linearized code for the body, D = English text for the header, trigger definition, H = Linearized code for the header, S = Linearized code for the symbol table.

Metadata about a column in SQL Server 2008 R2?

I'm trying to figure out a way to store metadata about a column without repeating myself.
I'm currently working on a generic dimension loading SSIS package that will handle all my dimensions. It currently does :
Create a temporary table identical to the given table name in parameters (this is a generic stored procedure that receive the table name as parameter, and then do : select top 0 * into ##[INSERT ORIGINAL TABLE NAME HERE] from [INSERT ORIGINAL TABLE NAME HERE]).
==> Here we insert custom code for this particular dimension that will first query the data from a datasource and get my delta, then transform the data and finally loads it into my temporary table.
Merge the temporary table into my original table with a T-SQL MERGE, taking care of type1 and type2 fields accordingly.
My problem right now is that I have to maintain a table with all the fields in it to store a metadata to tell my scripts if this particular field is type1 or type2... this is nonsense, I can get the same data (minus type1/type2) from sys.columns/sys.types.
I was ultimately thinking about renaming my fields to include their type in it, such as :
FirstName_T2, LastName_T2, Sex_T1 (well, I know this can be type2, let's not fall into that debate here).
What do you guyz would do with that? My solution (using a table with that metadata) is currently in place and working, but it's obvious that repeating myself from the systables to a custom table is nonsense, just for a simple type1/type2 info.
UPDATE: I also thought about creating user defined types like varchar => t1_varchar, t2_varchar, etc. This sounds like something a bit sluggy too...
Everything you need should already be in INFORMATION_SCHEMA.COLUMNS
I can't follow your thinking of not using provided tables/views...
Edit: As scarpacci mentioned, this somewhat portable if needed.
I know this is bad, but I will post an answer to my own question... Thanks to GBN for the help tho!
I am now storing "flags" in the "description" field of my columns. I, for example, can store a flag this way : "TYPE_2_DATA".
Then, I use this query to get the flag back for each and every column :
select columns.name as [column_name]
,types.name as [type_name]
,extended_properties.value as [column_flags]
from sys.columns
inner join sys.types
on columns.system_type_id = types.system_type_id
left join sys.extended_properties
on extended_properties.major_id = columns.object_id
and extended_properties.minor_id = columns.column_id
and extended_properties.name = 'MS_Description'
where object_id = ( select id from sys.sysobjects where name = 'DimDivision' )
and is_identity = 0
order by column_id
Now I can store metadata about columns without having to create a separate table. I use what's already in place and I don't repeat myself. I'm not sure this is the best possible solution yet, but it works and is far better than duplicating information.
In the future, I will be able to use this field to store more metadata, where as : "TYPE_2_DATA|ANOTHER_FLAG|ETC|OH BOY!".
UPDATE :
I now store the information in separate extended properties. You can manage extended properties using sp_addextendedproperty and sp_updateextendedproperty stored procedures. I have created a simple store procedure that help me to update those values regardless if they currently exist or not :
create procedure [dbo].[UpdateSCDType]
#tablename nvarchar(50),
#fieldname nvarchar(50),
#scdtype char(1),
#dbschema nvarchar(25) = 'dbo'
as
begin
declare #already_exists int;
if ( #scdtype = '1' or #scdtype = '2' )
begin
select #already_exists = count(1)
from sys.columns
inner join sys.extended_properties
on extended_properties.major_id = columns.object_id
and extended_properties.minor_id = columns.column_id
and extended_properties.name = 'ScdType'
where object_id = (select sysobjects.id from sys.sysobjects where sysobjects.name = #tablename)
and columns.name = #fieldname
if ( #already_exists = 0 )
begin
exec sys.sp_addextendedproperty
#name = N'Scd_Type',
#value = #scdtype,
#level0type = N'SCHEMA',
#level0name = #dbschema,
#level1type = N'TABLE',
#level1name = #tablename,
#level2type = N'COLUMN',
#level2name = #fieldname
end
else
begin
exec sys.sp_updateextendedproperty
#name = N'Scd_Type',
#value = #scdtype,
#level0type = N'SCHEMA',
#level0name = #dbschema,
#level1type = N'TABLE',
#level1name = #tablename,
#level2type = N'COLUMN',
#level2name = #fieldname
end
end
end
Thanks again