I have to select the records from temptable
and insert or update to mastertable
. If a single field is changed, then I need to update my histo
Try this one -
Schema:
CREATE TABLE dbo.HistoryTable
(
HistoryTableID INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
PKRecordID INT NOT NULL,
ColumnChanged VARCHAR(50) NOT NULL,
OldValue VARCHAR(10) NOT NULL,
NewValue VARCHAR(10) NOT NULL,
ChangedDate DATETIME NOT NULL DEFAULT (GETDATE())
)
GO
CREATE TABLE dbo.ForeignKeyTableCOL2 (COL2 VARCHAR(10) PRIMARY KEY NOT NULL)
GO
CREATE TABLE dbo.ForeignKeyTableCOL1 (COL1 VARCHAR(10) PRIMARY KEY NOT NULL)
GO
CREATE TABLE dbo.ErrorTable
(
ErrorTableID INT IDENTITY(1,1) PRIMARY KEY NOT NULL,
PKRecordID INT NOT NULL,
TableName VARCHAR(50) NOT NULL,
TablePK INT NOT NULL,
ErrorDateTime DATETIME NOT NULL DEFAULT (GETDATE()),
ErrorCode INT NOT NULL,
ErrorMsg VARCHAR(2000) NOT NULL
)
GO
CREATE TABLE dbo.TempTable
(
TempTableID INT IDENTITY(1,1) NOT NULL,
PKRecordID INT NOT NULL,
COL1 VARCHAR(10) NOT NULL,
COL2 VARCHAR(10) NOT NULL,
COL3 VARCHAR(10) NOT NULL,
COL4 VARCHAR(10) NOT NULL,
COL5 VARCHAR(10) NOT NULL,
Success CHAR(1) NOT NULL DEFAULT ('N')
)
GO
CREATE TABLE dbo.MasterTable
(
PKRecordID INT NOT NULL,
COL1 VARCHAR(10) NOT NULL,
COL2 VARCHAR(10) NOT NULL,
COL3 VARCHAR(10) NOT NULL,
COL4 VARCHAR(10) NOT NULL,
COL5 VARCHAR(10) NOT NULL
)
GO
ALTER TABLE dbo.MasterTable WITH CHECK ADD CONSTRAINT FK_MasterTable_ForeignKeyTableCOL1 FOREIGN KEY(COL1)
REFERENCES dbo.ForeignKeyTableCOL1 (COL1)
ALTER TABLE dbo.MasterTable CHECK CONSTRAINT FK_MasterTable_ForeignKeyTableCOL1
ALTER TABLE dbo.MasterTable WITH CHECK ADD CONSTRAINT FK_MasterTable_ForeignKeyTableCOL2 FOREIGN KEY(COL2)
REFERENCES dbo.ForeignKeyTableCOL2 (COL2)
ALTER TABLE dbo.MasterTable CHECK CONSTRAINT FK_MasterTable_ForeignKeyTableCOL2
INSERT dbo.ForeignKeyTableCOL1 (COL1)
VALUES ('A'), ('B'), ('C')
INSERT dbo.ForeignKeyTableCOL2 (COL2)
VALUES ('A'), ('B'), ('C')
INSERT dbo.TempTable (PKRecordID, COL1, COL2, COL3, COL4, COL5)
VALUES
(1, 'A', 'A', 'A', 'A', 'A'),
(2, 'B', 'B', 'B', 'B', 'B'),
(3, 'C', 'C', 'C', 'C', 'C'),
(1, 'D', 'A', 'A', 'A', 'A'),
(1, 'A', 'D', 'A', 'A', 'A'),
(1, 'D', 'D', 'A', 'A', 'A'),
(2, 'A', 'B', 'B', 'B', 'B'),
(3, 'A', 'B', 'C', 'C', 'C'),
(4, 'D', 'D', 'D', 'D', 'D')
Query:
SET NOCOUNT ON;
DECLARE
@PKRecordID INT
, @COL1 VARCHAR(10)
, @COL2 VARCHAR(10)
, @COL3 VARCHAR(10)
, @COL4 VARCHAR(10)
, @COL5 VARCHAR(10)
, @TempTableID INT
, @New_Row XML
, @Old_Row XML
DECLARE cur CURSOR LOCAL FAST_FORWARD READ_ONLY FOR
SELECT
t.TempTableID
, t.PKRecordID
, t.COL1
, t.COL2
, t.COL3
, t.COL4
, t.COL5
, New_Row = CAST('' + t.COL1 + '' + t.COL2 + '' + t.COL3 + '' + t.COL4 + '' + t.COL5 + ' ' AS XML)
, Old_Row = CAST('' + m.COL1 + '' + m.COL2 + '' + m.COL3 + '' + m.COL4 + '' + m.COL5 + ' ' AS XML)
FROM dbo.TempTable t
LEFT JOIN dbo.MasterTable m ON t.PKRecordID = m.PKRecordID
OPEN cur
FETCH NEXT FROM cur INTO
@TempTableID
, @PKRecordID
, @COL1
, @COL2
, @COL3
, @COL4
, @COL5
, @New_Row
, @Old_Row
WHILE @@FETCH_STATUS = 0 BEGIN
BEGIN TRY
IF @Old_Row IS NOT NULL BEGIN
UPDATE dbo.MasterTable
SET
COL1 = @COL1
, COL2 = @COL2
, COL3 = @COL3
, COL4 = @COL4
, COL5 = @COL5
WHERE PKRecordID = @PKRecordID
INSERT dbo.HistoryTable
(
PKRecordID
, ColumnChanged
, OldValue
, NewValue
)
SELECT
@PKRecordID
, 'COL' + CAST(new_id AS VARCHAR(5))
, old_value
, new_value
FROM (
SELECT
new_value = n.value('(.)1', 'VARCHAR(10)')
, new_id = 1 + n.value('for $i in . return count(../*. << $i)', 'int')
, old_value = o.value('(.)1', 'VARCHAR(10)')
, old_id = 1 + o.value('for $i in . return count(../*. << $i)', 'int')
FROM (SELECT a = 1) d
CROSS APPLY @New_Row.nodes('/r/s') t(n)
CROSS APPLY @Old_Row.nodes('/r/s') k(o)
) data
WHERE new_id = old_id
AND NULLIF(new_value, '') != NULLIF(old_value, '')
UPDATE dbo.TempTable
SET Success = 'Y'
WHERE TempTableID = @TempTableID
END
ELSE BEGIN
INSERT dbo.MasterTable
(
PKRecordID
, COL1
, COL2
, COL3
, COL4
, COL5
)
SELECT
@PKRecordID
, @COL1
, @COL2
, @COL3
, @COL4
, @COL5
UPDATE dbo.TempTable
SET Success = 'Y'
WHERE TempTableID = @TempTableID
END
END TRY
BEGIN CATCH
INSERT dbo.ErrorTable
(
PKRecordID
, TableName
, TablePK
, ErrorDateTime
, ErrorCode
, ErrorMsg
)
SELECT
@PKRecordID
, 'TempTable'
, @TempTableID
, GETDATE()
, ERROR_NUMBER()
, ERROR_MESSAGE()
END CATCH
FETCH NEXT FROM cur INTO
@TempTableID
, @PKRecordID
, @COL1
, @COL2
, @COL3
, @COL4
, @COL5
, @New_Row
, @Old_Row
END
CLOSE cur
DEALLOCATE cur
And this possible be helpful for you:
CREATE TRIGGER ...
ON ...
INSTEAD OF INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
SET XACT_ABORT ON
DECLARE @DocumentUID UNIQUEIDENTIFIER
...
DECLARE cur CURSOR FORWARD_ONLY READ_ONLY LOCAL FOR
SELECT DocumentUID, ...
FROM INSERTED
OPEN cur
FETCH NEXT FROM cur INTO @DocumentUID, ...
WHILE @@FETCH_STATUS = 0 BEGIN
DECLARE
@BeforeChange NVARCHAR(MAX)
, @AfterChange NVARCHAR(MAX)
SELECT
@BeforeChange = (
SELECT *
FROM DELETED
WHERE DocumentUID = @DocumentUID
FOR XML RAW, ROOT
)
, @AfterChange = (
SELECT *
FROM INSERTED
WHERE DocumentUID = @DocumentUID
FOR XML RAW, ROOT
)
IF EXISTS(
SELECT 1
FROM dbo.Documents
WHERE DocumentUID = @DocumentUID
)
BEGIN
INSERT INTO ...
SELECT @BeforeChange, @AfterChange
END
ELSE BEGIN
...
END
FETCH NEXT FROM cur INTO @DocumentUID, ...
END
CLOSE cur
DEALLOCATE cur
END