Well, I would NOT claim that this is the way this should be done, but it was some fun to ticker it down:
Disclaimer: This is a demonstration why TSQL is the wrong tool for this
I added some more GO-separated statements and used quotes within to get it even more tricky:
DECLARE @sql NVARCHAR(1000) =
'DECLARE @table AS TABLE(
[Id] INT,
[Info] NVARCHAR(100)
);
INSERT INTO @table
([Id],[Info])
VALUES
(1,''Info''),
(2,''Show must go on''),
(3,''This includes a GO and some "quoted" text''),
(4,''GO'');
SELECT * FROM @table;
GO
SELECT TOP 10 * FROM sys.objects
GO
PRINT ''Each GO will be used to have separate patches''';
--let's start by removing various kinds of line breaks
SET @sql = REPLACE(REPLACE(STRING_ESCAPE(@sql,'json'),'\r','\n'),'\n\n','\n');
--Using a CS_AS
-collation will avoid to take "go" as we (hopefully!) can rely on "GO":
DECLARE @json NVARCHAR(MAX) = CONCAT('["',REPLACE(REPLACE(@sql COLLATE Latin1_General_CS_AS,'GO' COLLATE Latin1_General_CS_AS,'","GO'),'\n','","'),'"]');
--Above I used each upper-case "GO" and each line break to separate the string.
--Doing so we transform your string into a json array
--Now we can fill this into a table using OPENJSON
to read the json-array (ommitting empty lines)
DECLARE @tbl TABLE(RowIndex INT IDENTITY,fragment NVARCHAR(MAX));
INSERT INTO @tbl(fragment)
SELECT STRING_ESCAPE(A.[value],'json')
FROM OPENJSON(@json) A
WHERE LEN(TRIM(A.[value]))>0 AND TRIM(A.[value])!=NCHAR(9);
--We need these variable for the cursor
DECLARE @patch NVARCHAR(MAX);
--Now I open a cursor
--We do this by running down a recursive CTE once again building up a json array.
--This time we will separate the strings when the upper-case "GO" is sitting alone in its line.
DECLARE cur CURSOR FOR
WITH cte AS
(
SELECT RowIndex, CAST(CONCAT('["',fragment) AS NVARCHAR(MAX)) growingString
FROM @tbl WHERE RowIndex=1
UNION ALL
SELECT n.RowIndex
,CONCAT(cte.growingString,CASE WHEN TRIM(n.fragment) COLLATE Latin1_General_CS_AS=N'GO' THEN N'","' ELSE n.fragment END)
FROM @tbl n
INNER JOIN cte ON n.RowIndex=cte.RowIndex+1
)
,thePatches AS
(
SELECT TOP 1 CONCAT(growingString,'"]') AS jsonArray
FROM cte ORDER BY RowIndex DESC
)
SELECT A.[value] AS patch
FROM thePatches p
CROSS APPLY OPENJSON(p.jsonArray) A;
--we can - finally - walk down the patches and execute them one by one
OPEN cur;
FETCH NEXT FROM cur INTO @patch;
WHILE @@FETCH_STATUS=0
BEGIN
PRINT @patch; --PRINT out for visual control before execution!
--EXEC(@patch);
FETCH NEXT FROM cur INTO @patch;
END
CLOSE cur;
DEALLOCATE cur;
There are millions of things (e.g. line-breaks within content, commented sections, max recursion) which can destroy this approach. So clearly DO NOT follow this suggestion :-)