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
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.
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
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 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.
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