I am new to the forum and am looking for help with my SQL trigger.
The trigger monitors the table tbl_adresse whether something has changed or a new data line has been added.
My SQL trigger should collect data and write it in a new table.
This works so far with this code:
CREATE TRIGGER [tgr_TEST] ON [dbo].[tbl_adresse]
AFTER INSERT, UPDATE
AS
BEGIN
MERGE [dbo].[WAWIDL_ADRESSKORREKTUR_RECHNUNGSADRESSE] AS WDL
USING (SELECT d.* FROM tbl_adresse AS d JOIN inserted AS i ON i.kAdresse = d.kAdresse) AS WWW
ON TBL.XML_tadresse_kAdresse = WWW.kAdresse
AND TBL.XML_tadresse_kKundenID = WWW.kKundenID
WHEN MATCHED
AND (
ISNULL(TBL.XML_tadresse_cFirma,0) != ISNULL(WWW.cFirma,0) OR
ISNULL(TBL.XML_tadresse_cZusatz,0) != ISNULL(WWW.cZusatz,0) OR
ISNULL(TBL.XML_tadresse_cTitel,0) != ISNULL(WWW.cTitel,0) OR
ISNULL(TBL.XML_tadresse_cVorname,0) != ISNULL(WWW.cVorname,0) OR
ISNULL(TBL.XML_tadresse_cName,0) != ISNULL(WWW.cName,0) OR
ISNULL(TBL.XML_tadresse_cStrasse,0) != ISNULL(WWW.cStrasse,0) OR
ISNULL(TBL.XML_tadresse_cPLZ,0) != ISNULL(WWW.cPLZ,0) OR
ISNULL(TBL.XML_tadresse_cOrt,0) != ISNULL(WWW.cOrt,0) OR
ISNULL(TBL.XML_tadresse_cAdressZusatz,0) != ISNULL(WWW.cAdressZusatz,0)
)
THEN
UPDATE
SET
TBL.WDL_cKundenNr = '',
TBL.WDL_cBestellNr = '',
TBL.XML_tadresse_cFirma = ISNULL(WWW.cFirma,''),
TBL.XML_tadresse_cZusatz = ISNULL(WWW.cZusatz,''),
TBL.XML_tadresse_cTitel = ISNULL(WWW.cTitel,''),
TBL.XML_tadresse_cVorname = ISNULL(WWW.cVorname,''),
TBL.XML_tadresse_cName = ISNULL(WWW.cName,''),
TBL.XML_tadresse_cStrasse = ISNULL(WWW.cStrasse,''),
TBL.XML_tadresse_cPLZ = ISNULL(WWW.cPLZ,''),
TBL.XML_tadresse_cOrt = ISNULL(WWW.cOrt,''),
TBL.XML_tadresse_cAdressZusatz = ISNULL(WWW.cAdressZusatz,'')
WHEN NOT MATCHED BY TARGET
THEN
INSERT (
XML_tadresse_kAdresse,
XML_tadresse_kKundenID,
WDL_cKundenNr,
WDL_cBestellNr,
XML_tadresse_cFirma,
XML_tadresse_cZusatz,
XML_tadresse_cTitel,
XML_tadresse_cVorname,
XML_tadresse_cName,
XML_tadresse_cStrasse,
XML_tadresse_cPLZ,
XML_tadresse_cOrt,
XML_tadresse_cAdressZusatz
)
VALUES (
WWW.kAdresse,
WWW.kKundenID,
'',
'',
ISNULL(WWW.cFirma,''),
ISNULL(WWW.cZusatz,''),
ISNULL(WWW.cTitel,''),
ISNULL(WWW.cVorname,''),
ISNULL(WWW.cName,''),
ISNULL(WWW.cStrasse,''),
ISNULL(WWW.cPLZ,''),
ISNULL(WWW.cOrt,''),
ISNULL(WWW.cAdressZusatz,'')
);
END
GO
Unfortunately I am now missing more information, which I only get from a second table called tbl_orders.
I have now tried to make another JOIN, but it does not work, I get the error message that the connection is already busy, there are probably 2 queries being made at the same time.
"Die Verbindung ist mit Ergebnissen von einem anderen hstmt belegt."
CREATE TRIGGER [tgr_TEST] ON [dbo].[tbl_adresse]
AFTER INSERT, UPDATE
AS
BEGIN
MERGE [dbo].[WAWIDL_ADRESSKORREKTUR_RECHNUNGSADRESSE] AS WDL
USING (SELECT d.* FROM tbl_adresse AS d JOIN inserted AS i ON i.kAdresse = d.kAdresse) AS WWW JOIN tbl_orders AS o ON WWW.kAdresse = o.kAdresse
ON TBL.XML_tadresse_kAdresse = WWW.kAdresse
AND TBL.XML_tadresse_kKundenID = WWW.kKundenID
WHEN MATCHED
AND (
ISNULL(TBL.XML_tadresse_cFirma,0) != ISNULL(WWW.cFirma,0) OR
ISNULL(TBL.XML_tadresse_cZusatz,0) != ISNULL(WWW.cZusatz,0) OR
ISNULL(TBL.XML_tadresse_cTitel,0) != ISNULL(WWW.cTitel,0) OR
ISNULL(TBL.XML_tadresse_cVorname,0) != ISNULL(WWW.cVorname,0) OR
ISNULL(TBL.XML_tadresse_cName,0) != ISNULL(WWW.cName,0) OR
ISNULL(TBL.XML_tadresse_cStrasse,0) != ISNULL(WWW.cStrasse,0) OR
ISNULL(TBL.XML_tadresse_cPLZ,0) != ISNULL(WWW.cPLZ,0) OR
ISNULL(TBL.XML_tadresse_cOrt,0) != ISNULL(WWW.cOrt,0) OR
ISNULL(TBL.XML_tadresse_cAdressZusatz,0) != ISNULL(WWW.cAdressZusatz,0)
)
THEN
UPDATE
SET
TBL.WDL_cKundenNr = ISNULL(WWW.cKundenNr,''),
TBL.WDL_cBestellNr = ISNULL(WWW.cBestellNr,''),
TBL.XML_tadresse_cFirma = ISNULL(WWW.cFirma,''),
TBL.XML_tadresse_cZusatz = ISNULL(WWW.cZusatz,''),
TBL.XML_tadresse_cTitel = ISNULL(WWW.cTitel,''),
TBL.XML_tadresse_cVorname = ISNULL(WWW.cVorname,''),
TBL.XML_tadresse_cName = ISNULL(WWW.cName,''),
TBL.XML_tadresse_cStrasse = ISNULL(WWW.cStrasse,''),
TBL.XML_tadresse_cPLZ = ISNULL(WWW.cPLZ,''),
TBL.XML_tadresse_cOrt = ISNULL(WWW.cOrt,''),
TBL.XML_tadresse_cAdressZusatz = ISNULL(WWW.cAdressZusatz,'')
WHEN NOT MATCHED BY TARGET
THEN
INSERT (
XML_tadresse_kAdresse,
XML_tadresse_kKundenID,
WDL_cKundenNr,
WDL_cBestellNr,
XML_tadresse_cFirma,
XML_tadresse_cZusatz,
XML_tadresse_cTitel,
XML_tadresse_cVorname,
XML_tadresse_cName,
XML_tadresse_cStrasse,
XML_tadresse_cPLZ,
XML_tadresse_cOrt,
XML_tadresse_cAdressZusatz
)
VALUES (
WWW.kAdresse,
WWW.kKundenID,
ISNULL(WWW.cKundenNr,''),
ISNULL(WWW.cBestellNr,''),
ISNULL(WWW.cFirma,''),
ISNULL(WWW.cZusatz,''),
ISNULL(WWW.cTitel,''),
ISNULL(WWW.cVorname,''),
ISNULL(WWW.cName,''),
ISNULL(WWW.cStrasse,''),
ISNULL(WWW.cPLZ,''),
ISNULL(WWW.cOrt,''),
ISNULL(WWW.cAdressZusatz,'')
);
What am I doing wrong?
Can't you add any more JOIN tables at INSERTED?
Thank You!
I have a job that I am currenlty running to sync data between two databases on different internal servers. The one server is the backend database for the HEAT product from FrontRange. The second is our own reporting database we are using for report writing and other internal uses.
Our first approach at the job went something like this:
Query all the data from the HEAT database tables we wanted and populate local temp tables. Then copy that data out to the appropriate table. That would work but they use to TRUNCATE the table every time and repopulate without doing anything for indexes or fragmentation. So I thought well this could be a good candidate to use the SQL merge statement.
So our second approach used a merge statement for each of the tables. It greatly improved the speed of the process but it seems to be locking the source table up so that users are noticing 15-30 second delays when they try to save information. To make the merge only handle records that have had changes or are new I added the BINARY_CHECKSUM function on the select and store it on my side so that I can avoid updating records that haven't changed. Seems expensive though to call that for every record. This table has about ~300k records.
I am wondering is there a better approach to try and synchronize these two tables that I am overlooking. My only constraint is that I really do not want to change anything on the source tables because it is a third party application.
Here is my mege statement I am using for the CallLog table:
-- Merge CallLog
MERGE INTO [CallLog] AS T
USING (
SELECT
[CallID], [CustID], [CustType], [CallType], [Tracker], [CallStatus], [Priority], [CDuration], [CallCount], [StopWatch], [ClosedBy],
[ClosedDate], [ClosedTime], [Cause], [CallDesc], [CloseDesc], [RecvdBy], [RecvdDate], [RecvdTime], [ModBy], [ModDate], [ModTime],
[DTLastMod], [CallSource], [PriorityName], [QuickCall], [Category], [TotalAsgnmntTime], [CatHeading], [TotalJournalTime],
[TotalTime], [SL_Warn_Goal], [SL_Warn_Date], [SL_Warn_Time], [SL_Complete_Goal], [SL_Complete_Date], [SL_Complete_Time],
[SL_Clock_Status], [SL_Button_Status], [FirstResolution], [SL_Complete_Status], [SubCallType], [ImpactValue], [ImpactName],
[UrgencyValue], [UrgencyName], [LinkedToProblem], [LinkedToProblemCustID], [LinkedToProblemName], [LinkedToProblemBy],
[LinkedToProblemDate], [LinkedToProblemTime], [SLAStatus], [issue_text], [issue_number], [ResCheck], [AsgnAckBy], [AsgnAckDate],
[AsgnAckTime], [Resolvedby], [ResolvedDate], [ResolvedTime], [ACheck], [ACKEmail], [LinkedToChange], [LinkedToChangeCustID],
[LinkedToChangeName], [LinkedToChangeBy], [LInkedToChangeDate], [LinkedToChangeTime], [IssueTypeProblem], [IssueTypeChange],
[RespWarningD], [RespWarningT], [RespMissedD], [RespMissedT], [ResoWarningD], [ResoWarningT], [ResoMissedD], [ResoMissedT],
[IssueType], [SubCategory], [Diagnosis], [HSSAlert], [ErrorMessage], [ProblemType], [diagnosising], [KB], [CloseStatus],
[SuggestedAssignGrp], [DefaultGrp], [DefaultGrpTF], [OtherAssign], [WorkAround], [ChangeReason], [CloseProblem], [AssgnApp],
[AssgnAppRes], [DenyChk], [ImplementationApp], [ImplementationAppRes], [WorkAroundChk], [NoDenyChk], [ImpNoDenyChk],
[ImpDenyChk], [ChangeStatus], [ReadyToClose], [ResolveOrReAssign], [TicketLabel], [CatCallType], [IssueType_PK], [Category_PK],
[SubCategory_PK], [CallType_PK], [SubCallType_PK], BINARY_CHECKSUM(*) AS [Checksum]
FROM
[CHLA-HEATDB].SDIT.dbo.calllog
) AS S
ON (T.[CallID] = S.[CallID])
WHEN MATCHED AND T.[Checksum] <> S.[Checksum] THEN
UPDATE SET
T.[CallID] = S.[CallID], T.[CustID] = S.[CustID], T.[CustType] = S.[CustType], T.[CallType] = S.[CallType],
T.[Tracker] = S.[Tracker], t.[CallStatus] = S.[CallStatus], T.[Priority] = S.[Priority], T.[CDuration] = S.[CDuration],
T.[CallCount] = S.[CallCount], T.[StopWatch] = S.[StopWatch], T.[ClosedBy] = S.[ClosedBy],
T.[ClosedDate] = S.[ClosedDate], T.[ClosedTime] = S.[ClosedTime], T.[Cause] = S.[Cause], T.[CallDesc] = S.[CallDesc],
T.[CloseDesc] = S.[CloseDesc], T.[RecvdBy] = S.[RecvdBy], T.[RecvdDate] = S.[RecvdDate], T.[RecvdTime] = S.[RecvdTime],
T.[ModBy] = S.[ModBy], T.[ModDate] = S.[ModDate], T.[ModTime] = S.[ModTime], T.[DTLastMod] = S.[DTLastMod],
T.[CallSource] = S.[CallSource], T.[PriorityName] = S.[PriorityName], T.[QuickCall] = S.[QuickCall],
T.[Category] = S.[Category], T.[TotalAsgnmntTime] = S.[TotalAsgnmntTime], T.[CatHeading] = S.[CatHeading],
T.[TotalJournalTime] = S.[TotalJournalTime], T.[TotalTime] = S.[TotalTime], T.[SL_Warn_Goal] = S.[SL_Warn_Goal],
T.[SL_Warn_Date] = S.[SL_Warn_Date], T.[SL_Warn_Time] = S.[SL_Warn_Time], T.[SL_Complete_Goal] = S.[SL_Complete_Goal],
T.[SL_Complete_Date] = S.[SL_Complete_Date], T.[SL_Complete_Time] = S.[SL_Complete_Time],
T.[SL_Clock_Status] = S.[SL_Clock_Status], T.[SL_Button_Status] = S.[SL_Button_Status],
T.[FirstResolution] = S.[FirstResolution], T.[SL_Complete_Status] = S.[SL_Complete_Status],
T.[SubCallType] = S.[SubCallType], T.[ImpactValue] = S.[ImpactValue], T.[ImpactName] = S.[ImpactName],
T.[UrgencyValue] = S.[UrgencyValue], T.[UrgencyName] = S.[UrgencyName], T.[LinkedToProblem] = S.[LinkedToProblem],
T.[LinkedToProblemCustID] = S.[LinkedToProblemCustID], T.[LinkedToProblemName] = S.[LinkedToProblemName],
T.[LinkedToProblemBy] = S.[LinkedToProblemBy], T.[LinkedToProblemDate] = S.[LinkedToProblemDate],
T.[LinkedToProblemTime] = S.[LinkedToProblemTime], T.[SLAStatus] = S.[SLAStatus], T.[issue_text] = S.[issue_text],
T.[issue_number] = S.[issue_number], T.[ResCheck] = S.[ResCheck], T.[AsgnAckBy] = S.[AsgnAckBy],
T.[AsgnAckDate] = S.[AsgnAckDate], T.[AsgnAckTime] = S.[AsgnAckTime], T.[Resolvedby] = S.[Resolvedby],
T.[ResolvedDate] = S.[ResolvedDate], T.[ResolvedTime] = S.[ResolvedTime], T.[ACheck] = S.[ACheck],
T.[ACKEmail] = S.[ACKEmail], T.[LinkedToChange] = S.[LinkedToChange], T.[LinkedToChangeCustID] = S.[LinkedToChangeCustID],
T.[LinkedToChangeName] = S.[LinkedToChangeName], T.[LinkedToChangeBy] = S.[LinkedToChangeBy],
T.[LInkedToChangeDate] = S.[LInkedToChangeDate], T.[LinkedToChangeTime] = S.[LinkedToChangeTime],
T.[IssueTypeProblem] = S.[IssueTypeProblem], T.[IssueTypeChange] = S.[IssueTypeChange],
T.[RespWarningD] = S.[RespWarningD], T.[RespWarningT] = S.[RespWarningT], T.[RespMissedD] = S.[RespMissedD],
T.[RespMissedT] = S.[RespMissedT], T.[ResoWarningD] = S.[ResoWarningD], T.[ResoWarningT] = S.[ResoWarningT],
T.[ResoMissedD] = S.[ResoMissedD], T.[ResoMissedT] = S.[ResoMissedT], T.[IssueType] = S.[IssueType],
T.[SubCategory] = S.[SubCategory], T.[Diagnosis] = S.[Diagnosis], T.[HSSAlert] = S.[HSSAlert],
T.[ErrorMessage] = S.[ErrorMessage], T.[ProblemType] = S.[ProblemType], T.[diagnosising] = S.[diagnosising],
T.[KB] = S.[KB], T.[CloseStatus] = S.[CloseStatus], T.[SuggestedAssignGrp] = S.[SuggestedAssignGrp],
T.[DefaultGrp] = S.[DefaultGrp], T.[DefaultGrpTF] = S.[DefaultGrpTF], T.[OtherAssign] = S.[OtherAssign],
T.[WorkAround] = S.[WorkAround], T.[ChangeReason] = S.[ChangeReason], T.[CloseProblem] = S.[CloseProblem],
T.[AssgnApp] = S.[AssgnApp], T.[AssgnAppRes] = S.[AssgnAppRes], T.[DenyChk] = S.[DenyChk],
T.[ImplementationApp] = S.[ImplementationApp], T.[ImplementationAppRes] = S.[ImplementationAppRes],
T.[WorkAroundChk] = S.[WorkAroundChk], T.[NoDenyChk] = S.[NoDenyChk], T.[ImpNoDenyChk] = S.[ImpNoDenyChk],
T.[ImpDenyChk] = S.[ImpDenyChk], T.[ChangeStatus] = S.[ChangeStatus], T.[ReadyToClose] = S.[ReadyToClose],
T.[ResolveOrReAssign] = S.[ResolveOrReAssign], T.[TicketLabel] = S.[TicketLabel], T.[CatCallType] = S.[CatCallType],
T.[IssueType_PK] = S.[IssueType_PK], T.[Category_PK] = S.[Category_PK], T.[SubCategory_PK] = S.[SubCategory_PK],
T.[CallType_PK] = S.[CallType_PK], T.[SubCallType_PK] = S.[SubCallType_PK], T.[Checksum] = S.[Checksum]
WHEN NOT MATCHED
THEN INSERT VALUES
(
S.[CallID], S.[CustID], S.[CustType], S.[CallType], S.[Tracker], S.[CallStatus], S.[Priority], S.[CDuration],
S.[CallCount], S.[StopWatch], S.[ClosedBy], S.[ClosedDate], S.[ClosedTime], S.[Cause], S.[CallDesc], S.[CloseDesc],
S.[RecvdBy], S.[RecvdDate], S.[RecvdTime], S.[ModBy], S.[ModDate], S.[ModTime], S.[DTLastMod], S.[CallSource],
S.[PriorityName], S.[QuickCall], S.[Category], S.[TotalAsgnmntTime], S.[CatHeading], S.[TotalJournalTime], S.[TotalTime],
S.[SL_Warn_Goal], S.[SL_Warn_Date], S.[SL_Warn_Time], S.[SL_Complete_Goal], S.[SL_Complete_Date], S.[SL_Complete_Time],
S.[SL_Clock_Status], S.[SL_Button_Status], S.[FirstResolution], S.[SL_Complete_Status], S.[SubCallType], S.[ImpactValue],
S.[ImpactName], S.[UrgencyValue], S.[UrgencyName], S.[LinkedToProblem], S.[LinkedToProblemCustID], S.[LinkedToProblemName],
S.[LinkedToProblemBy], S.[LinkedToProblemDate], S.[LinkedToProblemTime], S.[SLAStatus], S.[issue_text], S.[issue_number],
S.[ResCheck], S.[AsgnAckBy], S.[AsgnAckDate], S.[AsgnAckTime], S.[Resolvedby], S.[ResolvedDate], S.[ResolvedTime], S.[ACheck],
S.[ACKEmail], S.[LinkedToChange], S.[LinkedToChangeCustID], S.[LinkedToChangeName], S.[LinkedToChangeBy],
S.[LInkedToChangeDate], S.[LinkedToChangeTime], S.[IssueTypeProblem], S.[IssueTypeChange], S.[RespWarningD],
S.[RespWarningT], S.[RespMissedD], S.[RespMissedT], S.[ResoWarningD], S.[ResoWarningT], S.[ResoMissedD], S.[ResoMissedT],
S.[IssueType], S.[SubCategory], S.[Diagnosis], S.[HSSAlert], S.[ErrorMessage], S.[ProblemType], S.[diagnosising], S.[KB],
S.[CloseStatus], S.[SuggestedAssignGrp], S.[DefaultGrp], S.[DefaultGrpTF], S.[OtherAssign], S.[WorkAround], S.[ChangeReason],
S.[CloseProblem], S.[AssgnApp], S.[AssgnAppRes], S.[DenyChk], S.[ImplementationApp], S.[ImplementationAppRes],
S.[WorkAroundChk], S.[NoDenyChk], S.[ImpNoDenyChk], S.[ImpDenyChk], S.[ChangeStatus], S.[ReadyToClose],
S.[ResolveOrReAssign], S.[TicketLabel], S.[CatCallType], S.[IssueType_PK], S.[Category_PK], S.[SubCategory_PK],
S.[CallType_PK], S.[SubCallType_PK], S.[Checksum]
);
GO
Since you're on SQL 2008, how about Change Data Capture? You can get the net changes over a period of time and deal only with that (as opposed to replication which pushes every change, even if you update the same data 10 times).
I think you can improve performance by figuring out what rows to modify/insert before the merge statement.
You can create a temp table that contains the CallID's that should be affected.
Perhaps something like this.
;with cteSource as
(
select
S.CallID,
binary_checksum(*) as [CheckSum]
from [CHLA-HEATDB].SDIT.dbo.calllog
)
select
S.CallID,
S.[CheckSum]
into #TmpSource
from cteSource as S
left outer join CallLog as T
on S.CallID = T.CallID and
S.[CheckSum] = T.[CheckSum]
where T.CallID is null
Then you can use that table in your using select statement.
MERGE INTO [CallLog] AS T
USING (
SELECT
[CallID],
-- A lot of fields
T.[CheckSum] AS [Checksum]
FROM
[CHLA-HEATDB].SDIT.dbo.calllog as C
inner join #TmpSource as Tmp
on C.CallID = Tmp.CallID
) AS S
ON (T.[CallID] = S.[CallID])
WHEN MATCHED THEN -- Probably don't need this AND T.[Checksum] <> S.[Checksum] THEN
UPDATE SET
T.[CallID] = S.[CallID],
-- More fields here
WHEN NOT MATCHED
THEN INSERT VALUES
(
S.[CallID],
-- More fields here
);