Trigger after insert on two tables - tsql

I have the following trigger right now but I now have the requirement to only kick off the trigger if ANOTHER table Facility has a record inserted into it with a LocationID = 'ER'-
As per the comment I've updated the trigger -
ALTER TRIGGER [dbo].[VoceraOeOrders] ON [dbo].[OeOrders]
FOR INSERT
AS
IF NOT EXISTS (
SELECT *
FROM dbo.Facility
WHERE LocationID = 'ER'
)
RETURN
DECLARE #priority VARCHAR(50)
DECLARE #cat VARCHAR(50)
DECLARE #order VARCHAR(50)
DECLARE #procedure VARCHAR(50)
DECLARE #orderid VARCHAR(50)
DECLARE #locationid VARCHAR(10)
DECLARE #roomid VARCHAR(10)
DECLARE #visitid VARCHAR(50)
SELECT #visitid = VisitID
,#priority = Priority
,#cat = Category
,#procedure = OrderedProcedureName
,#order = OrderDateTime
,#orderid = OrderNumber
,#locationid = (
SELECT LocationID
FROM dbo.Facility
WHERE VisitID = #visitid
)
,#roomid = (
SELECT CASE
WHEN RoomTreatmentID IS NULL
THEN 'No Room#'
ELSE RoomTreatmentID
END
FROM dbo.Facility
WHERE VisitID = #visitid
)
FROM insterted
WHERE #priority = 'STAT'
AND #cat IN (
'CT'
,'MRI'
,'XRAY'
,'US'
,'RT'
,'NUC'
,'ECHO'
)
BEGIN
DECLARE #msg VARCHAR(500)
DECLARE #subject VARCHAR(500)
SET #msg = #procedure + ' - ' + #locationid + ' ' + #roomid + '-' + ' Priority ' + #priority + '.' + 'Order DateTime/Number ' + #order + '/' + #orderid
SET #subject = 'Vocera Group Name Here'
EXEC msdb.dbo.sp_send_dbmail #recipients = N'some_email'
,#body = #msg
,#subject = #subject
,#profile_name = 'Alert'
END

Just add in the beginning of you trigger:
if not exists(select * from facilities where FacilityID = 'ER')
return
You can't stop kicking trigger. You can check for some condition and return from trigger.

Related

Error converting data type varchar to numeric in standard audit trigger

I have been using a standard block of TSQL for auditing of various tables for some time now. However I now have a problem when running the trigger on a new table: "Error converting data type varchar to numeric". This occurs when running the EXEC (#sql) line. I've determined that the code for #sql is:
insert Audit_AppointmentsWS
(Type,
TableName,
PK,
FieldName,
OldValue,
NewValue,
UpdateDate,
UserName)
SELECT 'U',
'AppointmentsWorkshop',
+convert(varchar(100), coalesce(i.UniqueID,d.UniqueID)),
'[JobHours]',
convert(varchar(1000),d.[JobHours]),
convert(varchar(1000),i.[JobHours]),
'20220816 12:32:43:410',
'DELLXPS\ian'
from #ins i full outer join #del d on i.UniqueID = d.UniqueID where ISNULL(i.JobHours],'') <> ISNULL(d.[JobHours],'')
I've tried deleting the trigger & the audit table and then recreating them but no joy. I've also tried copying an existing trigger and just changing the table details but I still get the same error. I'm completely stumped on this and would appreciate some feedback. Many thanks in advance!
Here is the trigger:
/****** Object: Trigger [dbo].[tr_AppointmentsWS] Script Date: 16/08/2022 12:02:10 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
create TRIGGER [dbo].[tr_AppointmentsWS] ON [dbo].AppointmentsWorkshop FOR UPDATE, DELETE
AS
DECLARE #bit INT ,
#field INT ,
#maxfield INT ,
#char INT ,
#fieldname VARCHAR(128) ,
#TableName VARCHAR(128) ,
#AuditTable VARCHAR(128) ,
#PKCols VARCHAR(MAX) ,
#sql VARCHAR(2000),
#UpdateDate VARCHAR(21) ,
#UserName VARCHAR(128) ,
#Type CHAR(1) ,
#PKSelect VARCHAR(MAX)
--Changes required:
-- 1. Change the name of the trigger and the table, above
-- 2. Change #TableName to match the table to be audited
-- 3. Change the #AuditTable to the table holding the changes
SELECT #TableName = 'AppointmentsWorkshop'
SELECT #AuditTable = 'Audit_AppointmentsWS'
-- date and user
SELECT #UserName = SYSTEM_USER ,
#UpdateDate = CONVERT(VARCHAR(8), GETDATE(), 112) + ' ' + CONVERT(VARCHAR(12), GETDATE(), 114)
-- Action
IF EXISTS (SELECT * FROM inserted)
IF EXISTS (SELECT * FROM deleted)
SELECT #Type = 'U'
ELSE
SELECT #Type = 'I'
ELSE
SELECT #Type = 'D'
-- get list of columns
SELECT * INTO #ins FROM inserted
SELECT * INTO #del FROM deleted
-- Get primary key columns for full outer join
SELECT #PKCols = COALESCE(#PKCols + ' and', ' on') + ' i.' + c.COLUMN_NAME + ' = d.' + c.COLUMN_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk, INFORMATION_SCHEMA.KEY_COLUMN_USAGE c
WHERE pk.TABLE_NAME = #TableName
AND CONSTRAINT_TYPE = 'PRIMARY KEY'
AND c.TABLE_NAME = pk.TABLE_NAME
AND c.CONSTRAINT_NAME = pk.CONSTRAINT_NAME
-- Get primary key select for insert
SELECT #PKSelect = COALESCE(#PKSelect+'+','') + '+convert(varchar(100), coalesce(i.' + COLUMN_NAME +',d.' + COLUMN_NAME + '))'
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS pk, INFORMATION_SCHEMA.KEY_COLUMN_USAGE c
WHERE pk.TABLE_NAME = #TableName
AND CONSTRAINT_TYPE = 'PRIMARY KEY'
AND c.TABLE_NAME = pk.TABLE_NAME
AND c.CONSTRAINT_NAME = pk.CONSTRAINT_NAME
IF #PKCols IS NULL
BEGIN
RAISERROR('no PK on table %s', 16, -1, #TableName)
RETURN
END
SELECT #field = 0, #maxfield = MAX(COLUMNPROPERTY(OBJECT_ID(TABLE_SCHEMA + '.' + #Tablename),COLUMN_NAME, 'ColumnID'))
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = #TableName
WHILE #field < #maxfield
BEGIN
SELECT #field = MIN(COLUMNPROPERTY(OBJECT_ID(TABLE_SCHEMA + '.' + #Tablename),COLUMN_NAME, 'ColumnID'))
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = #TableName
AND COLUMNPROPERTY(OBJECT_ID(TABLE_SCHEMA + '.' + #Tablename),COLUMN_NAME, 'ColumnID') > #field
SELECT #bit = (#field - 1 )% 8 + 1
SELECT #bit = POWER(2,#bit - 1)
SELECT #char = ((#field - 1) / 8) + 1
IF SUBSTRING(COLUMNS_UPDATED(),#char, 1) & #bit > 0 OR #Type IN ('I','D')
BEGIN
SELECT #fieldname = COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = #TableName
AND COLUMNPROPERTY(OBJECT_ID(TABLE_SCHEMA + '.' + #Tablename),COLUMN_NAME, 'ColumnID') = #field
SELECT #sql = 'insert ' + #AuditTable + '
(Type,
TableName,
PK,
FieldName,
OldValue,
NewValue,
UpdateDate,
UserName)
SELECT ''' + #Type + ''','''
+ #TableName + ''',' + #PKSelect
+ ',''[' + #fieldname + ']'''
+ ',convert(varchar(1000),d.[' + #fieldname + '])'
+ ',convert(varchar(1000),i.[' + #fieldname + '])'
+ ',''' + #UpdateDate + ''''
+ ',''' + #UserName + ''''
+ ' from #ins i full outer join #del d'
+ #PKCols
+ ' where ISNULL(i.[' + #fieldname + '],'''') <> ISNULL(d.[' + #fieldname + '],'''')' --Skip identical values and excludes NULLS vs empty strings
EXEC (#sql)
END
END
Well I finally figured it out. The error is being generated with columns of data type 'decimal' and it is down to the ISNULL section of the last SELECT. I've fixed it by checking for the decimal type and then using the following code (which included a zero rather than an empty sting):
+ ' where ISNULL(i.[' + #fieldname + '],''0'') <> ISNULL(d.[' + #fieldname + '],''0'')' --Skip identical values and excludes NULLS vs empty strings

Loop through a table without using a cursor or temp table finding records over 30 days old

Using SQL Server 2012. I need to loop through my table without using a cursor or a temp table. Also, I know the debate re: cursors... :) AND I have script at the bottom of this question using sys.databases and msdb.dbo.restorehistory getting the last restored, but this doesn't fix my immediate need for this specific table.
Scenario: I have a table that I created for restore tests:
CREATE Table RestoreTests (
RestoreTestID int Not NULL,
ServerName varchar (255) Not NULL,
DatabaseName varchar (255) Not NULL,
RestoreDate datetime Not NULL,
BackupFile varchar (1000) Not NULL)
I inserted 8 records with:
2 servers - 4 records/server,
.bak and .trn for each DatabaseName, and
dates < 30 days and dates > 30 days - 4 records each.
I want to identify all records on my table that are > 30 days.
SELECT * FROM RestoreTests WHERE RestoreDate DATEDIFF(Day,RestoreDate, GETDATE()) > 30
My syntax:
declare #RestoreTestID int
declare #ServerName varchar(255)
declare #DatabaseName varchar(255)
declare #RestoreDate datetime
declare #BackupFile varchar(1000)
declare #id int
set #id = 0
select top 1 #RestoreTestID = RestoreTestID,
#ServerName = ServerName,
#DatabaseName = DatabaseName,
#RestoreDate = RestoreDate,
#BackupFile = BackupFile
from dbo.RestoreTests
where RestoreTestID > #id and DATEDIFF(DAY,RestoreDate, GETDATE()) > 30
order by RestoreTestID asc
while ##ROWCOUNT > 0
begin
print 'loop RestoreTestID=' + cast(#RestoreTestID as varchar(255)) +
', ServerName=' + #ServerName +
', DatabaseName' + #DatabaseName +
', RestoreDate' + CAST(#RestoreDate as varchar(255)) +
', BackupFile' + #BackupFile
set #id = #RestoreTestID
select top 1 #RestoreTestID = RestoreTestID
from dbo.RestoreTests
where RestoreTestID > #id and DATEDIFF(DAY,RestoreDate, GETDATE()) > 30
order by RestoreTestID
end
I'm getting error message:
Msg 137, Level 15, State 1, Line 1
Must declare the scalar variable "#RestoreTestID".
Msg 137, Level 15, State 2, Line 13
Must declare the scalar variable "#RestoreTestID".
Msg 137, Level 15, State 2, Line 19
Must declare the scalar variable "#RestoreTestID".
Msg 137, Level 15, State 1, Line 21
Must declare the scalar variable "#RestoreTestID".
When I was dinking around earlier I did get a result set with all eight records and not the 4 that are over 30 days. Any assistance offered is greatly appreciated!!
Last Restore Syntax:
WITH LastRestores AS
(
SELECT
DatabaseName = [d].[name] ,
[d].[create_date] ,
[d].[compatibility_level] ,
[d].[collation_name] ,
r.*,
RowNum = ROW_NUMBER() OVER (PARTITION BY d.Name ORDER BY r.[restore_date] DESC)
FROM master.sys.databases d
LEFT OUTER JOIN msdb.dbo.[restorehistory] r ON r.[destination_database_name] = d.Name
)
SELECT *
FROM [LastRestores]
WHERE [RowNum] = 1
select * from [dbo].[RestoreTests]
Ok, I figured out what I needed. Here's the syntax I arrived at:
declare #RestoreTestID int
declare #id int
declare #ServerName varchar(255);
declare #DatabaseName varchar (255);
declare #RestoreDate datetime;
declare #BackupFile varchar (1000);
set #id = 0
select top 1
#RestoreTestID = RestoreTestID,
#ServerName = ServerName,
#DatabaseName = DatabaseName,
#RestoreDate = RestoreDate,
#BackupFile = BackupFile
from dbo.RestoreTests
where RestoreTestID > #id and RestoreDate <= DATEADD(day,-31,getdate())
order by RestoreTestID
while ##ROWCOUNT = 1
begin
print 'RestoreTestID = ' + cast(#RestoreTestID as varchar(255)) +
', ServerName = ' + #ServerName +
', Databasename = ' + #DatabaseName +
', RestoreDate = ' + cast(#RestoreDate as varchar (255)) +
', BackupFile = ' + #BackupFile
set #id = #RestoreTestID
select top 1 #RestoreTestID = RestoreTestID
from dbo.RestoreTests
where RestoreTestID > #id and RestoreDate <= DATEADD(day,-31,getdate())
order by RestoreTestID
end

I cannot manage to insert multiple rows when having multiple fields to get data from

I ran into a problem with regards to trying to insert multiple rows in a table at once. I know it sounds easy, but here is the twist. The procedure itself gets data from a trigger, and the trigger returns a number of rows. So i need to make 1 insert statement to insert those rows and some other data. here is the code:
CREATE PROCEDURE [a01].[usp_raiseFriendAlerts]
(#AccountA UNIQUEIDENTIFIER, #AccountB UNIQUEIDENTIFIER)
AS
BEGIN
DECLARE #typeID TINYINT;
DECLARE #notificationID UNIQUEIDENTIFIER = NEWID();
DECLARE #accountAName NVARCHAR(356);
DECLARE #accountBName NVARCHAR(356);
SET #typeID = ( SELECT typeID
FROM [a01].[tbl_notificationTypes]
WHERE typeName = 'Added friend');
SET #accountAName = ( SELECT accountUsername
FROM [a01].[tbl_userAccounts]
WHERE accountID = #AccountA);
SET #accountBName = ( SELECT accountUsername
FROM [a01].[tbl_userAccounts]
WHERE accountID = #AccountB);
DECLARE #AccountIDZZ UNIQUEIDENTIFIER;
SET #AccountIDZZ = (SELECT friendAccountID
FROM [a01].[udf_getAddedFriendContacts](#AccountA, #AccountB)
EXCEPT
SELECT targetAccountID
FROM [a01].[tbl_blockedAccounts]);
INSERT INTO [a01].[tbl_notificationsInbox] (notificationID, notificationMessage, notificationDate, accountID, typeId)
VALUES (#notificationID, #accountAName + ' is now friends with ' + #accountBName, SYSDATETIMEOFFSET(), #AccountIDZZ , #typeID)
END;
GO
Try this:
CREATE PROCEDURE [a01].[usp_raiseFriendAlerts]
(
#AccountA UNIQUEIDENTIFIER
, #AccountB UNIQUEIDENTIFIER
)
AS
BEGIN
DECLARE #typeID TINYINT
, #notificationID UNIQUEIDENTIFIER = NEWID()
, #accountAName NVARCHAR(356)
, #accountBName NVARCHAR(356)
, #AccountIDZZ UNIQUEIDENTIFIER;
SELECT #typeID = typeID
FROM [a01].[tbl_notificationTypes]
WHERE typeName = 'Added friend';
SELECT #accountAName = accountUsername
FROM [a01].[tbl_userAccounts]
WHERE accountID = #AccountA;
SELECT #accountBName = accountUsername
FROM [a01].[tbl_userAccounts]
WHERE accountID = #AccountB;
INSERT INTO [a01].[tbl_notificationsInbox]
(
notificationID
, notificationMessage
, notificationDate
, accountID
, typeId
)
SELECT #notificationID
, #accountAName + ' is now friends with ' + #accountBName
, SYSDATETIMEOFFSET()
, AIDZZ.accountID
, #typeID
FROM (
SELECT friendAccountID AS 'accountID'
FROM [a01].[udf_getAddedFriendContacts](#AccountA, #AccountB)
EXCEPT
SELECT targetAccountID AS 'accountID'
FROM [a01].[tbl_blockedAccounts]
) AS AIDZZ
END;
GO

MS SQL Server 2012 Trigger Syntax

I am working on HW assignment learning about triggers and am having problems with syntax on both insert and delete DML ForTriggers as follows:
CREATE TRIGGER tr_PERSON_ForInsert
ON PERSON
FOR INSERT
AS
BEGIN
DECLARE #SSN CHAR(9)
SELECT #SSN = SSN FROM inserted
DECLARE #NAME VARCHAR(50)
SELECT #NAME = NAME FROM inserted
DECLARE #USERNAME VARCHAR(50)
SELECT #USERNAME USERNAME FROM INSERTED
declare #time time(7)
select #time = time from inserted
insert into PERSON_DEL_LOG
VALUES ('New person with SSN = ' +
Cast(#SSN as NVARchar(9)) +
CAST(#NAME AS NVARCHAR(50)) +
cast(#username as nvarchar(50)) +
cast(#time as nvarchar(20))
)
END
INSERT INTO PERSON('012675543', 'MIKE', '5467896543', 'MUSEUM', 'INTEL',
'BLUECROSS', '987654321')
CREATE TRIGGER tr_PERSON_ForDELETE
ON PERSON
FOR DELETE
AS
BEGIN
DECLARE #SSN CHAR(9)
SELECT #SSN = SSN FROM DELETED
DECLARE #NAME VARCHAR(50)
SELECT #NAME = NAME FROM DELETED
insert into PERSON_DEL_LOG
VALUES ('New person with SSN = ' +
Cast(#SSN as nvarchar(9)) +
Cast(#NAME as VARCHAR(50)) + 'is added at ' +
cast(Getdate() as nvarchar(20))
)
END
DELETE FROM PERSON WHERE NAME = 987654321
SELECT * FROM PERSON_DEL_LOG
My PERSON_DEL_LOG table structure:
SSN, NAME, USERNAME, TIME
I need to know where exactly is my problem/s

Inherit values from previous records

I have the following table where all fields except Value as a part of a unique index on the table. I'd like to inherit the Value from a record with Value<>NULL to the next revision record only if that record has a NULL value (See example below):
Var[n]Value fields ate varchar and there maybe 1-n number of Var[n]value fields in my table.
Source:
Document# Revision Project# config# Var1Value Var2Value
1744 1 2 1 NULL NULL
1744 2 2 1 NULL NULL
1744 3 2 1 Tit1 ABC
1744 4 2 1 Tit2 ABD
1744 5 2 1 NULL NULL
1744 6 2 1 NULL SDC
1744 7 2 1 AS
1744 8 2 1 Tit3 NULL
Needed result (notice change for revision records 5 and 6 var1value and 5,8 for var2value):
Document# Revision Project# config# Var1Value Var2Value
1744 1 2 1 NULL NULL
1744 2 2 1 NULL NULL
1744 3 2 1 Tit1 ABC
1744 4 2 1 Tit2 ABD
1744 5 2 1 Tit2 ABD
1744 6 2 1 Tit2 SDC
1744 7 2 1 AS
1744 8 2 1 Tit3 AS
Any idea how to handle it by SQL?
Please advise.
I tried the following:
declare #TableName as VarChar(32) = 'MYTABLE'
declare #SetClause as VarChar(1024)
declare #LWhereClause as VarChar(1024)
declare #RWhereClause as VarChar(1024)
-- Get the column names.
select Column_Name
into #Columns
from Information_Schema.Columns
where Table_Name = #TableName and Column_Name like 'Var%'
--select * from #Columns
-- Assemble the clauses we'll need for the UPDATE statement.
declare #ColumnName as VarChar(32)
while ( ##RowCount > 0 )
begin
select top 1 #ColumnName = Column_Name
from #Columns
order by Column_Name
set #SetClause = case when #SetClause is NULL then '' else #SetClause + ', ' end +
#ColumnName + ' = Coalesce( L.' + #ColumnName + ', R.' + #ColumnName + ' )'
set #LWhereClause = case when #LWhereClause is NULL then '' else #LWhereClause + ' or ' end +
'L.' + #ColumnName + ' is NULL'
set #RWhereClause = case when #RWhereClause is NULL then '' else #RWhereClause + ' or ' end +
'R.' + #ColumnName + ' is not NULL'
delete from #Columns
where Column_Name = #ColumnName
end
--select #SetClause, #LWhereClause, #RWhereClause
-- Put together the UPDATE statement.
declare #Update as nVarChar(max)
set #Update=''
set #Update=#Update +
'update L set ' + #SetClause + ' from ' + #TableName +
' as L inner join ' + #TableName + ' as R on R.DocId = L.DocId and R.Rev = L.Rev - 1 and R.Proj = L.Proj and R.Conf = L.Conf' +
' where ( ' + #LWhereClause + ' ) and ( ' + #RWhereClause + ' )'
-- Put together the entire loop. This needs work.
declare #Loop as nVarChar(max)
set #Loop =''
set #Loop=#Loop+
'#declare Eleanor as Int = 42;
while ( #Eleanor > 0 ) '
+ #Update + '
set #Eleanor = ##RowCount
end'
--select #Loop
-- Execute it.
exec #Loop
drop table #Columns
and I get the following error on exec loop. Why it is truncating the nvarchar string?
Msg 203, Level 16, State 2, Line 53
The name '#declare Eleanor as Int = 42;
while ( #Eleanor > 0 ) update L set variable104 = Coalesce( L.variable104, R.variable104 ), variable105 = Coalesce( L.variable105, R.variable105 ), variable106 = Coalesce( L.variable106, R.variable106 ), variable107 = Coalesce( L.variable107, R.variable107 ), variable112 = Coalesce( L.variable112, R.variable112 ), variable116 = Coalesce( L.variable116, R.variable116 ), variable119 = Coalesce( L.variable119, R.variable119 ), variable120 = Coalesce( L.variable120, R.variable120 ), variable121 = Coalesce( L.variable121, R.variable121 ), variable122 = Coalesce( L.variable122, R.variable122 ), variable124 = Co' is not a valid identifier.
exact duplicate of :
SQL QUERY replace NULL value in a row with a value from the previous known value
p.s:i don't have privilege to comment.so i wrote as answer.
EDIT: Begging your pardon, but I failed to consider the variable columns.
This query will retrieve the columns defined in YourTable:
select Column_Name from Information_Schema.Columns where Table_Name = 'YourTable'
Thereafter, you need to build a dynamic query and EXEC it. You could craft code like that shown below for each individual column, or to process all of the columns in one go.
Building the query dynamically is a somewhat tedious process. The following should get you well on your way.
declare #TableName as VarChar(32) = 'YourTable'
declare #SetClause as VarChar(1024)
declare #LWhereClause as VarChar(1024)
declare #RWhereClause as VarChar(1024)
-- Get the column names.
select Column_Name
into #Columns
from Information_Schema.Columns
where Table_Name = #TableName and Column_Name like 'Var%'
select * from #Columns
-- Assemble the clauses we'll need for the UPDATE statement.
declare #ColumnName as VarChar(32)
while ( ##RowCount > 0 )
begin
select top 1 #ColumnName = Column_Name
from #Columns
order by Column_Name
set #SetClause = case when #SetClause is NULL then '' else #SetClause + ', ' end +
#ColumnName + ' = Coalesce( L.' + #ColumnName + ', R.' + #ColumnName + ' )'
set #LWhereClause = case when #LWhereClause is NULL then '' else #LWhereClause + ' or ' end +
'L.' + #ColumnName + ' is NULL'
set #RWhereClause = case when #RWhereClause is NULL then '' else #RWhereClause + ' or ' end +
'R.' + #ColumnName + ' is not NULL'
delete from #Columns
where Column_Name = #ColumnName
end
select #SetClause, #LWhereClause, #RWhereClause
-- Put together the UPDATE statement.
declare #Update as VarChar(4096) =
'update L set ' + #SetClause + ' from ' + #TableName +
' as L inner join ' + #TableName + ' as R on R.DocId = L.DocId and R.Rev = L.Rev - 1 and R.Proj = L.Proj and R.Conf = L.Conf' +
' where ( ' + #LWhereClause + ' ) and ( ' + #RWhereClause + ' )'
-- Put together the entire loop. This needs work.
declare #Loop as VarChar(4096) =
'#declare Eleanor as Int = 42; ...' + #Update + '...'
select #Loop
-- Execute it.
exec #Loop
drop table #Columns
Here's one dreadful way that is based on revision numbers being dense:
declare #Docs as Table ( DocId Int, Rev Int, Proj Int, Conf Int, Var1 VarChar(10) Null, Var2 VarChar(10) Null )
insert into #Docs ( DocId, Rev, Proj, Conf, Var1, Var2 ) values
( 1744, 1, 2, 1, NULL, NULL ),
( 1744, 2, 2, 1, NULL, NULL ),
( 1744, 3, 2, 1, 'Tit1', 'ABC' ),
( 1744, 4, 2, 1, 'Tit2', 'ABD' ),
( 1744, 5, 2, 1, NULL, NULL ),
( 1744, 6, 2, 1, NULL, 'SDC' ),
( 1744, 7, 2, 1, '', 'AS' ), -- The example data for this row is unclear.
( 1744, 8, 2, 1, 'Tit3', NULL )
select * from #Docs
declare #Eleanor as Int = 42
while ( #Eleanor > 0 )
begin
update L
set Var1 = Coalesce( L.Var1, R.Var1 ), Var2 = Coalesce( L.Var2, R.Var2 )
from #Docs as L inner join
#Docs as R on R.DocId = L.DocId and R.Rev = L.Rev - 1 and R.Proj = L.Proj and R.Conf = L.Conf
where ( L.Var1 is NULL or L.Var2 is NULL ) and ( R.Var1 is not NULL or R.Var2 is not NULL )
set #Eleanor = ##RowCount
end
select * from #Docs