I want to update a table on one server with data from a table on another server. The tables have the same columns and I just want to sync the data. I have earlier made a script that creates insert statements for these tables (put out a question to SO and answered it myself…) but the seemingly simpler task of creating UPDATE
statements now eludes me. Maybe because I’m just back from holiday.
For reference, here’s my “INSERT question”: Creating “Not Exists”/Insert Into Statements – Stumped by nothing (NULL)
I’m trying to use my INSERT
statements code but I’m either not getting multiple rows or just getting hard-to-debug error messages (Error close to NULL)
So, what I want to do is creating statements like this, one for each row in the table:
UPDATE WorkflowError SET [ErrorDescription] = 'Error creating email' WHERE [TargetSystem]='Fullmaktsnoden' AND [ErrorCode]='999' AND [ErrorText]='Error creating email' AND [ErrorDescription] IS NULL
I could use some general pointers like "Since you're now creating UPDATE statements instead of INSERT you need to think about..."
This is a table used for integration of several systems. We “collect” messages we get from other systems and record them in ErrorDescription. If it’s too long or misleading we put a shorter explanation in Errortext to show for the user. (in this example I happened to use the same text, “error creating email”, but in the real system the error description we get is much longer)
One try is a code like this:
USE FullmaktsnodenProcess GO SET NOCOUNT ON DECLARE @QUOTED_DATA VARCHAR(MAX), @DOES_EXIST VARCHAR(MAX), @SQL_KOD VARCHAR(MAX), @TABLE_NAME VARCHAR(MAX), @FIRST_COL INT, @LAST_COL INT, @THE_COLUMN VARCHAR(MAX) /* INPUT DATA */ SELECT @TABLE_NAME = 'WorkflowError' SELECT @FIRST_COL = 2 -- First column for Exists check SELECT @LAST_COL = 4 -- Last column for Exists check SELECT @THE_COLUMN = 'ErrorDescription' /* */ SELECT @QUOTED_DATA=STUFF ( ( SELECT ' ISNULL('''''''' + REPLACE('+COLUMN_NAME+','''''''','''''''''''') + '''''''','''+'NULL'''+''+')+'',''+' FROM information_schema.columns WHERE table_name = @TABLE_NAME AND COLUMN_NAME = @THE_COLUMN FOR XML PATH('') ),1,1,'' ) SELECT @QUOTED_DATA=SUBSTRING(@QUOTED_DATA,1,LEN(@QUOTED_DATA)-5) SELECT @QUOTED_DATA SELECT @DOES_EXIST=STUFF ( ( SELECT ' ['+ COLUMN_NAME +']='' + ', 'ISNULL('''''''' + REPLACE('+COLUMN_NAME+','''''''','''''''''''') + '''''''','''+'NULL'''+''+')+'' AND ' FROM information_schema.columns WHERE table_name = @TABLE_NAME AND ordinal_position BETWEEN @FIRST_COL AND @LAST_COL FOR XML PATH('') ),1,1,'' ) SELECT @DOES_EXIST SELECT @SQL_KOD='SELECT ''UPDATE ' + @TABLE_NAME + ' SET ' + QUOTENAME(@THE_COLUMN) + ' = ' + @QUOTED_DATA + ' WHERE ' + @DOES_EXIST + @THE_COLUMN + ' IS NULL''' SELECT @SQL_KOD EXECUTE (@SQL_KOD) SET NOCOUNT OFF GO
Trying to execute @SQL_KOD gives: “Msg 156, Level 15, State 1, Line 3 Incorrect syntax near the keyword ‘NULL’.”
From test run, with EXECUTE (@SQL_KOD) commented out:
@QUOTED_DATA = ISNULL('''' + REPLACE(ErrorDescription,'''','''''') + '''','NULL') @DOES_EXIST = [TargetSystem]=' + ISNULL('''' + REPLACE(TargetSystem,'''','''''') + '''','NULL')+' AND [ErrorCode]=' + ISNULL('''' + REPLACE(ErrorCode,'''','''''') + '''','NULL')+' AND [ErrorText]=' + ISNULL('''' + REPLACE(ErrorText,'''','''''') + '''','NULL')+' AND @SQL_KOD = SELECT 'UPDATE WorkflowError SET [ErrorDescription] = ISNULL('''' + REPLACE(ErrorDescription,'''','''''') + '''','NULL') WHERE [TargetSystem]=' + ISNULL('''' + REPLACE(TargetSystem,'''','''''') + '''','NULL')+' AND [ErrorCode]=' + ISNULL('''' + REPLACE(ErrorCode,'''','''''') + '''','NULL')+' AND [ErrorText]=' + ISNULL('''' + REPLACE(ErrorText,'''','''''') + '''','NULL')+' AND ErrorDescription IS NULL'
Advertisement
Answer
This seems to fit the bill. Qutation marks in data are now correctly doubled and the end result is one UPDATE statement for each row in the table, as I wanted. As I mentioned, reading from information_schema.columns is unnecessary when I’m here just working with one known column, but maybe when I’m modyfying this script for another table it’s not so…
USE FullmaktsnodenProcess GO SET NOCOUNT ON DECLARE @QUOTED_DATA VARCHAR(MAX), @DOES_EXIST VARCHAR(MAX), @SQL_KOD VARCHAR(MAX), @TABLE_NAME VARCHAR(MAX), @FIRST_COL INT, @LAST_COL INT, @THE_COLUMN VARCHAR(MAX) /* INPUT DATA */ SELECT @TABLE_NAME = 'WorkflowError' SELECT @FIRST_COL = 2 -- First column for Exists check SELECT @LAST_COL = 4 -- Last column for Exists check SELECT @THE_COLUMN = 'ErrorDescription' /* */ SELECT @QUOTED_DATA=STUFF ( ( SELECT ' ISNULL(REPLACE('+QUOTENAME(COLUMN_NAME)+','''''''','''''''''''') + '''''''','''+'NULL'''+''+')+'',''+' FROM information_schema.columns WHERE table_name = @TABLE_NAME AND COLUMN_NAME = @THE_COLUMN FOR XML PATH('') ),1,1,'' ) SELECT @QUOTED_DATA=SUBSTRING(@QUOTED_DATA,1,LEN(@QUOTED_DATA)-5) --SELECT @QUOTED_DATA SELECT @DOES_EXIST=STUFF ( ( SELECT ' '+ QUOTENAME(COLUMN_NAME) +'='''''' + ', 'ISNULL(REPLACE('+QUOTENAME(COLUMN_NAME)+','''''''','''''''''''') + '''''''','''+'NULL'''+''+')+'' AND ' FROM information_schema.columns WHERE table_name = @TABLE_NAME AND ordinal_position BETWEEN @FIRST_COL AND @LAST_COL FOR XML PATH('') ),1,1,'' ) -- SELECT @DOES_EXIST SELECT @SQL_KOD='SELECT ''UPDATE ' + @TABLE_NAME + ' SET ' + QUOTENAME(@THE_COLUMN) + ' = ' + ''''''' + ' + @QUOTED_DATA + ' + ' + ''' WHERE ' + @DOES_EXIST + @THE_COLUMN + ' IS NULL ' + ''' Update_Script ' + 'FROM ' + @TABLE_NAME -- SELECT @SQL_KOD EXECUTE (@SQL_KOD) SET NOCOUNT OFF GO