MSSQL export data

Exports data rows from a SQL Server database as executable SQL statements.

This is useful for

  • Portable snapshots - move selected data between environments
  • Targeted migrations - prepare payloads for specific tables
  • Pre-execution review - inspect generated SQL before running it
  • Zero tooling install - runs with SQL scripts in restricted environments
  • Readable output - generated statements are easy to inspect and review
  • Repeatable process - same scripts can be rerun consistently across environments
  • Safer migrations - you can validate and version-control the export result
  • Works with existing data - supports delete/replace workflows when target rows already exist
  • Selective usage - supports targeted export scenarios instead of full backups

Adjust variables and execute

SET QUOTED_IDENTIFIER ON;
SET NOCOUNT ON;

DECLARE @table NVARCHAR(255) = 'dbo.YourTableName';
DECLARE @where NVARCHAR(MAX) = '1=1';
DECLARE @includeBinaryColumns BIT = 0;
DECLARE @includeDelete BIT = 1;
DECLARE @excludeColumns TABLE (ColumnName NVARCHAR(255));
-- INSERT INTO @excludeColumns (ColumnName) VALUES ('PasswordHash'), ('SecurityStamp');

DECLARE @ChunkSize INT = 50000;
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @RowCount INT = 0;

BEGIN TRY
    -- Merge statement format should be:
    -- MERGE <target_table> AS target
    -- USING (VALUES (<row_expression>), (<row_expression>)) AS source
    -- ON (<pk_where_clause>)
    -- WHEN MATCHED THEN UPDATE SET <update_clause>
    -- WHEN NOT MATCHED THEN INSERT (<column_list>) VALUES (<insert_values_clause>);

    -- Get primary key columns
    DECLARE @PKColumns TABLE (
        ColumnName NVARCHAR(255),
        OrdinalPosition INT,
        DataType NVARCHAR(255)
    );

    INSERT INTO @PKColumns (ColumnName, OrdinalPosition, DataType)
    SELECT
        kcu.COLUMN_NAME,
        kcu.ORDINAL_POSITION,
        c.DATA_TYPE
    FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
    INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu
        ON tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME
        AND tc.TABLE_SCHEMA = kcu.TABLE_SCHEMA
        AND tc.TABLE_NAME = kcu.TABLE_NAME
    INNER JOIN INFORMATION_SCHEMA.COLUMNS c
        ON kcu.TABLE_SCHEMA = c.TABLE_SCHEMA
        AND kcu.TABLE_NAME = c.TABLE_NAME
        AND kcu.COLUMN_NAME = c.COLUMN_NAME
    WHERE tc.CONSTRAINT_TYPE = 'PRIMARY KEY'
        AND tc.TABLE_SCHEMA = (CASE WHEN CHARINDEX('.', @table) > 0 THEN LEFT(@table, CHARINDEX('.', @table) - 1) ELSE 'dbo' END)
        AND tc.TABLE_NAME = (CASE WHEN CHARINDEX('.', @table) > 0 THEN SUBSTRING(@table, CHARINDEX('.', @table) + 1, LEN(@table)) ELSE @table END)
    ORDER BY kcu.ORDINAL_POSITION;

    IF NOT EXISTS (SELECT 1 FROM @PKColumns)
    BEGIN
        SET @ErrorMessage = 'Table ' + @table + ' does not have a primary key.';
        RAISERROR(@ErrorMessage, 16, 1);
        RETURN;
    END

    -- Get all columns
    DECLARE @Columns TABLE (
        ColumnName NVARCHAR(255),
        DataType NVARCHAR(255),
        IsNullable BIT,
        OrdinalPosition INT,
        IsBinary BIT,
        ColumnDefault NVARCHAR(MAX),
        CharacterMaxLength INT,
        NumericPrecision INT,
        NumericScale INT
    );

    INSERT INTO @Columns (ColumnName, DataType, IsNullable, OrdinalPosition, IsBinary, ColumnDefault, CharacterMaxLength, NumericPrecision, NumericScale)
    SELECT
        c.COLUMN_NAME,
        c.DATA_TYPE,
        CASE WHEN c.IS_NULLABLE = 'YES' THEN 1 ELSE 0 END,
        c.ORDINAL_POSITION,
        CASE
            WHEN c.DATA_TYPE IN ('image', 'varbinary', 'binary') OR
                 (c.DATA_TYPE = 'varbinary' AND c.CHARACTER_MAXIMUM_LENGTH = -1) OR
                 (c.DATA_TYPE = 'binary' AND c.CHARACTER_MAXIMUM_LENGTH = -1)
            THEN 1
            ELSE 0
        END,
        c.COLUMN_DEFAULT,
        c.CHARACTER_MAXIMUM_LENGTH,
        c.NUMERIC_PRECISION,
        c.NUMERIC_SCALE
    FROM INFORMATION_SCHEMA.COLUMNS c
    WHERE c.TABLE_SCHEMA = (CASE WHEN CHARINDEX('.', @table) > 0 THEN LEFT(@table, CHARINDEX('.', @table) - 1) ELSE 'dbo' END)
        AND c.TABLE_NAME = (CASE WHEN CHARINDEX('.', @table) > 0 THEN SUBSTRING(@table, CHARINDEX('.', @table) + 1, LEN(@table)) ELSE @table END)
    ORDER BY c.ORDINAL_POSITION;

    -- Filter columns based on binary handling
    DECLARE @SelectedColumns TABLE (
        ColumnName NVARCHAR(255),
        DataType NVARCHAR(255),
        IsNullable BIT,
        OrdinalPosition INT,
        ColumnDefault NVARCHAR(MAX),
        CharacterMaxLength INT,
        NumericPrecision INT,
        NumericScale INT
    );

    INSERT INTO @SelectedColumns (ColumnName, DataType, IsNullable, OrdinalPosition, ColumnDefault, CharacterMaxLength, NumericPrecision, NumericScale)
    SELECT c.ColumnName, c.DataType, c.IsNullable, c.OrdinalPosition, c.ColumnDefault, c.CharacterMaxLength, c.NumericPrecision, c.NumericScale
    FROM @Columns c
    WHERE (@includeBinaryColumns = 1 OR c.IsBinary = 0)
        AND NOT EXISTS (SELECT 1 FROM @excludeColumns e WHERE e.ColumnName = c.ColumnName);

    -- Build column lists
    DECLARE @ColumnList NVARCHAR(MAX);
    DECLARE @PKWhereClause NVARCHAR(MAX);
    DECLARE @PKSelectClause NVARCHAR(MAX);
    DECLARE @UpdateClause NVARCHAR(MAX);
    DECLARE @InsertValuesClause NVARCHAR(MAX);

    SELECT @ColumnList = STUFF((
        SELECT ', ' + QUOTENAME(ColumnName)
        FROM @SelectedColumns
        ORDER BY OrdinalPosition
        FOR XML PATH(''), TYPE
    ).value('.', 'NVARCHAR(MAX)'), 1, 2, '');

    SELECT @PKWhereClause = STUFF((
        SELECT ' AND ' + 'target.' + QUOTENAME(pk.ColumnName) + ' = source.' + QUOTENAME(pk.ColumnName)
        FROM @PKColumns pk
        WHERE EXISTS (SELECT 1 FROM @SelectedColumns s WHERE s.ColumnName = pk.ColumnName)
        ORDER BY pk.OrdinalPosition
        FOR XML PATH(''), TYPE
    ).value('.', 'NVARCHAR(MAX)'), 1, 5, '');

    SELECT @PKSelectClause = STUFF((
        SELECT ', ' + QUOTENAME(pk.ColumnName)
        FROM @PKColumns pk
        WHERE EXISTS (SELECT 1 FROM @SelectedColumns s WHERE s.ColumnName = pk.ColumnName)
        ORDER BY pk.OrdinalPosition
        FOR XML PATH(''), TYPE
    ).value('.', 'NVARCHAR(MAX)'), 1, 2, '');

    IF @PKWhereClause IS NULL OR LTRIM(RTRIM(@PKWhereClause)) = ''
    BEGIN
        SET @ErrorMessage = 'At least one primary key column must be included (cannot exclude all PK columns).';
        RAISERROR(@ErrorMessage, 16, 1);
        RETURN;
    END

    SELECT @UpdateClause = STUFF((
        SELECT ', ' + QUOTENAME(ColumnName) + ' = source.' + QUOTENAME(ColumnName)
        FROM @SelectedColumns
        WHERE ColumnName NOT IN (SELECT ColumnName FROM @PKColumns)
        ORDER BY OrdinalPosition
        FOR XML PATH(''), TYPE
    ).value('.', 'NVARCHAR(MAX)'), 1, 2, '');

    IF @UpdateClause IS NULL OR LTRIM(RTRIM(@UpdateClause)) = ''
        SELECT @UpdateClause = (SELECT TOP 1 QUOTENAME(ColumnName) + ' = source.' + QUOTENAME(ColumnName) FROM @SelectedColumns ORDER BY OrdinalPosition);

    SELECT @InsertValuesClause = STUFF((
        SELECT ', ' + 'source.' + QUOTENAME(ColumnName)
        FROM @SelectedColumns
        ORDER BY OrdinalPosition
        FOR XML PATH(''), TYPE
    ).value('.', 'NVARCHAR(MAX)'), 1, 2, '');

    -- Build value formatter expression per column (for literal VALUES)
    DECLARE @VarCharType NVARCHAR(20) = 'var' + 'char';
    DECLARE @CharType NVARCHAR(20) = 'c' + 'har';
    DECLARE @ValueFormats TABLE (
        OrdinalPosition INT,
        ValueExpression NVARCHAR(MAX)
    );

    INSERT INTO @ValueFormats (OrdinalPosition, ValueExpression)
    SELECT
        OrdinalPosition,
        CASE
            WHEN DataType = 'bit' THEN 'CASE WHEN t.' + QUOTENAME(ColumnName) + ' IS NULL THEN ''NULL'' WHEN t.' + QUOTENAME(ColumnName) + ' = 1 THEN ''1'' ELSE ''0'' END'
            WHEN DataType = 'int' THEN 'CASE WHEN t.' + QUOTENAME(ColumnName) + ' IS NULL THEN ''NULL'' ELSE CAST(t.' + QUOTENAME(ColumnName) + ' AS NVARCHAR(MAX)) END'
            WHEN DataType = 'bigint' THEN 'CASE WHEN t.' + QUOTENAME(ColumnName) + ' IS NULL THEN ''NULL'' ELSE CAST(t.' + QUOTENAME(ColumnName) + ' AS NVARCHAR(MAX)) END'
            WHEN DataType = 'smallint' THEN 'CASE WHEN t.' + QUOTENAME(ColumnName) + ' IS NULL THEN ''NULL'' ELSE CAST(t.' + QUOTENAME(ColumnName) + ' AS NVARCHAR(MAX)) END'
            WHEN DataType = 'tinyint' THEN 'CASE WHEN t.' + QUOTENAME(ColumnName) + ' IS NULL THEN ''NULL'' ELSE CAST(t.' + QUOTENAME(ColumnName) + ' AS NVARCHAR(MAX)) END'
            WHEN DataType = 'decimal' THEN 'CASE WHEN t.' + QUOTENAME(ColumnName) + ' IS NULL THEN ''NULL'' ELSE CAST(t.' + QUOTENAME(ColumnName) + ' AS NVARCHAR(MAX)) END'
            WHEN DataType = 'numeric' THEN 'CASE WHEN t.' + QUOTENAME(ColumnName) + ' IS NULL THEN ''NULL'' ELSE CAST(t.' + QUOTENAME(ColumnName) + ' AS NVARCHAR(MAX)) END'
            WHEN DataType = 'float' THEN 'CASE WHEN t.' + QUOTENAME(ColumnName) + ' IS NULL THEN ''NULL'' ELSE CAST(t.' + QUOTENAME(ColumnName) + ' AS NVARCHAR(MAX)) END'
            WHEN DataType = 'real' THEN 'CASE WHEN t.' + QUOTENAME(ColumnName) + ' IS NULL THEN ''NULL'' ELSE CAST(t.' + QUOTENAME(ColumnName) + ' AS NVARCHAR(MAX)) END'
            WHEN DataType = 'money' THEN 'CASE WHEN t.' + QUOTENAME(ColumnName) + ' IS NULL THEN ''NULL'' ELSE CAST(t.' + QUOTENAME(ColumnName) + ' AS NVARCHAR(MAX)) END'
            WHEN DataType = 'smallmoney' THEN 'CASE WHEN t.' + QUOTENAME(ColumnName) + ' IS NULL THEN ''NULL'' ELSE CAST(t.' + QUOTENAME(ColumnName) + ' AS NVARCHAR(MAX)) END'
            WHEN DataType = 'date' THEN 'CASE WHEN t.' + QUOTENAME(ColumnName) + ' IS NULL THEN ''NULL'' ELSE CHAR(39) + CONVERT(NVARCHAR(50), t.' + QUOTENAME(ColumnName) + ', 121) + CHAR(39) END'
            WHEN DataType = 'datetime' THEN 'CASE WHEN t.' + QUOTENAME(ColumnName) + ' IS NULL THEN ''NULL'' ELSE CHAR(39) + CONVERT(NVARCHAR(50), t.' + QUOTENAME(ColumnName) + ', 121) + CHAR(39) END'
            WHEN DataType = 'datetime2' THEN 'CASE WHEN t.' + QUOTENAME(ColumnName) + ' IS NULL THEN ''NULL'' ELSE CHAR(39) + CONVERT(NVARCHAR(50), t.' + QUOTENAME(ColumnName) + ', 121) + CHAR(39) END'
            WHEN DataType = 'smalldatetime' THEN 'CASE WHEN t.' + QUOTENAME(ColumnName) + ' IS NULL THEN ''NULL'' ELSE CHAR(39) + CONVERT(NVARCHAR(50), t.' + QUOTENAME(ColumnName) + ', 121) + CHAR(39) END'
            WHEN DataType = 'time' THEN 'CASE WHEN t.' + QUOTENAME(ColumnName) + ' IS NULL THEN ''NULL'' ELSE CHAR(39) + CONVERT(NVARCHAR(50), t.' + QUOTENAME(ColumnName) + ', 121) + CHAR(39) END'
            WHEN DataType = 'uniqueidentifier' THEN 'CASE WHEN t.' + QUOTENAME(ColumnName) + ' IS NULL THEN ''NULL'' ELSE CHAR(39) + CAST(t.' + QUOTENAME(ColumnName) + ' AS NVARCHAR(36)) + CHAR(39) END'
            WHEN DataType IN ('nvarchar', 'nchar') THEN 'CASE WHEN t.' + QUOTENAME(ColumnName) + ' IS NULL THEN ''NULL'' ELSE NCHAR(78) + CHAR(39) + REPLACE(REPLACE(REPLACE(REPLACE(CAST(t.' + QUOTENAME(ColumnName) + ' AS NVARCHAR(MAX)), CHAR(13), CHAR(32)), CHAR(10), CHAR(32)), CHAR(9), CHAR(32)), CHAR(39), CHAR(39)+CHAR(39)) + CHAR(39) END'
            WHEN DataType IN (@VarCharType, @CharType) THEN 'CASE WHEN t.' + QUOTENAME(ColumnName) + ' IS NULL THEN ''NULL'' ELSE CHAR(39) + REPLACE(REPLACE(REPLACE(REPLACE(CAST(t.' + QUOTENAME(ColumnName) + ' AS NVARCHAR(MAX)), CHAR(13), CHAR(32)), CHAR(10), CHAR(32)), CHAR(9), CHAR(32)), CHAR(39), CHAR(39)+CHAR(39)) + CHAR(39) END'
            ELSE 'CASE WHEN t.' + QUOTENAME(ColumnName) + ' IS NULL THEN ''NULL'' ELSE NCHAR(78) + CHAR(39) + REPLACE(REPLACE(REPLACE(REPLACE(CAST(t.' + QUOTENAME(ColumnName) + ' AS NVARCHAR(MAX)), CHAR(13), CHAR(32)), CHAR(10), CHAR(32)), CHAR(9), CHAR(32)), CHAR(39), CHAR(39)+CHAR(39)) + CHAR(39) END'
        END
    FROM @SelectedColumns;

    DECLARE @RowExpression NVARCHAR(MAX) = '';
    DECLARE @ValExpr NVARCHAR(MAX);
    DECLARE @First BIT = 1;
    DECLARE row_cursor CURSOR LOCAL FAST_FORWARD FOR
        SELECT ValueExpression FROM @ValueFormats ORDER BY OrdinalPosition;
    OPEN row_cursor;
    FETCH NEXT FROM row_cursor INTO @ValExpr;
    WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @RowExpression = @RowExpression + CASE WHEN @First = 1 THEN '' ELSE ' + '', '' + ' END + @ValExpr;
        SET @First = 0;
        FETCH NEXT FROM row_cursor INTO @ValExpr;
    END;
    CLOSE row_cursor;
    DEALLOCATE row_cursor;

    DECLARE @PKRowExpression NVARCHAR(MAX) = '';
    DECLARE pk_cursor CURSOR LOCAL FAST_FORWARD FOR
        SELECT v.ValueExpression
        FROM @ValueFormats v
        INNER JOIN @SelectedColumns s ON v.OrdinalPosition = s.OrdinalPosition
        INNER JOIN @PKColumns pk ON pk.ColumnName = s.ColumnName
        ORDER BY pk.OrdinalPosition;
    OPEN pk_cursor;
    SET @First = 1;
    FETCH NEXT FROM pk_cursor INTO @ValExpr;
    WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @PKRowExpression = @PKRowExpression + CASE WHEN @First = 1 THEN '' ELSE ' + '', '' + ' END + @ValExpr;
        SET @First = 0;
        FETCH NEXT FROM pk_cursor INTO @ValExpr;
    END;
    CLOSE pk_cursor;
    DEALLOCATE pk_cursor;

    -- Get row count and build MERGE with literal VALUES via dynamic SQL
    DECLARE @CountSql NVARCHAR(MAX) = 'SELECT @cnt = COUNT(*) FROM ' + @table + ' WHERE ' + @where;
    EXEC sp_executesql @CountSql, N'@cnt INT OUTPUT', @cnt = @RowCount OUTPUT;

    DECLARE @DeleteSql NVARCHAR(MAX) = NULL;

    DECLARE @ChunkOutput TABLE (
        ChunkNumber INT,
        TableName NVARCHAR(255),
        SqlStatement NVARCHAR(MAX),
        ChunkRowCount INT,
        StatementSize INT,
        StatementType NVARCHAR(50)
    );

    IF @RowCount = 0
    BEGIN
        INSERT INTO @ChunkOutput (ChunkNumber, TableName, SqlStatement, ChunkRowCount, StatementSize, StatementType)
        SELECT
            1,
            @table,
            '-- No rows to export from ' + @table + ' WHERE ' + @where,
            0,
            0,
            'MERGE';
    END
    ELSE
    BEGIN
        DECLARE @BuildSql NVARCHAR(MAX) = 'SELECT @out = STUFF((SELECT '', '' + ''('' + ' + @RowExpression + ' + '')'' FROM ' + @table + ' t WHERE ' + @where + ' FOR XML PATH(''''), TYPE).value(''.'', ''NVARCHAR(MAX)''), 1, 2, '''')';
        DECLARE @ValuesResult NVARCHAR(MAX) = NULL;
        EXEC sp_executesql @BuildSql, N'@out NVARCHAR(MAX) OUTPUT', @out = @ValuesResult OUTPUT;

        IF @includeDelete = 1
        BEGIN
            DECLARE @BuildPKSql NVARCHAR(MAX) = 'SELECT @out = STUFF((SELECT '', '' + ''('' + ' + @PKRowExpression + ' + '')'' FROM ' + @table + ' t WHERE ' + @where + ' FOR XML PATH(''''), TYPE).value(''.'', ''NVARCHAR(MAX)''), 1, 2, '''')';
            DECLARE @PKValuesResult NVARCHAR(MAX) = NULL;
            EXEC sp_executesql @BuildPKSql, N'@out NVARCHAR(MAX) OUTPUT', @out = @PKValuesResult OUTPUT;
            SET @DeleteSql = 'DELETE FROM ' + @table + ' WHERE ' + @where + ' AND (' + @PKSelectClause + ') NOT IN (VALUES ' + ISNULL(@PKValuesResult, '') + ')';
        END

        DECLARE @CRLF NCHAR(2) = NCHAR(13) + NCHAR(10);
        DECLARE @MergePrefix NVARCHAR(MAX) = 'MERGE ' + @table + ' AS target' + @CRLF + 'USING (VALUES ';
        DECLARE @MergeSuffix NVARCHAR(MAX) = ') AS source(' + @ColumnList + ')' + @CRLF + 'ON (' + @PKWhereClause + ')' + @CRLF + 'WHEN MATCHED THEN UPDATE SET ' + ISNULL(@UpdateClause, '') + @CRLF + 'WHEN NOT MATCHED THEN INSERT (' + @ColumnList + ') VALUES (' + @InsertValuesClause + ');';
        DECLARE @MaxValuesLen INT = @ChunkSize - LEN(@MergePrefix) - LEN(@MergeSuffix);

        IF LEN(ISNULL(@ValuesResult, '')) <= @MaxValuesLen
        BEGIN
            INSERT INTO @ChunkOutput (ChunkNumber, TableName, SqlStatement, ChunkRowCount, StatementSize, StatementType)
            SELECT
                1,
                @table,
                @MergePrefix + ISNULL(@ValuesResult, '') + @MergeSuffix,
                @RowCount,
                LEN(@MergePrefix) + LEN(ISNULL(@ValuesResult, '')) + LEN(@MergeSuffix),
                'MERGE';
        END
        ELSE
        BEGIN
            DECLARE @Remaining NVARCHAR(MAX) = @ValuesResult;
            DECLARE @ChunkNum INT = 1;
            DECLARE @ChunkValues NVARCHAR(MAX);
            DECLARE @LastDelim INT;
            DECLARE @Pos INT;
            DECLARE @RowDelim NVARCHAR(10) = ', ';
            DECLARE @FullRowDelim NVARCHAR(20) = ')' + @RowDelim + '(';

            WHILE LEN(@Remaining) > 0
            BEGIN
                IF LEN(@Remaining) <= @MaxValuesLen
                BEGIN
                    SET @ChunkValues = @Remaining;
                    SET @Remaining = '';
                END
                ELSE
                BEGIN
                    SET @LastDelim = 0;
                    SET @Pos = 1;
                    WHILE @Pos <= @MaxValuesLen
                    BEGIN
                        SET @Pos = CHARINDEX(@FullRowDelim, @Remaining, @Pos);
                        IF @Pos = 0
                            BREAK;
                        IF @Pos - 1 <= @MaxValuesLen
                            SET @LastDelim = @Pos;
                        SET @Pos = @Pos + 1;
                    END;
                    IF @LastDelim > 0
                    BEGIN
                        SET @ChunkValues = SUBSTRING(@Remaining, 1, @LastDelim);
                        SET @Remaining = SUBSTRING(@Remaining, @LastDelim + LEN(@FullRowDelim) - 1, LEN(@Remaining));
                    END
                    ELSE
                    BEGIN
                        SET @Pos = CHARINDEX(@FullRowDelim, @Remaining);
                        IF @Pos > 0
                        BEGIN
                            SET @ChunkValues = SUBSTRING(@Remaining, 1, @Pos);
                            SET @Remaining = SUBSTRING(@Remaining, @Pos + LEN(@FullRowDelim) - 1, LEN(@Remaining));
                        END
                        ELSE
                        BEGIN
                            SET @ChunkValues = @Remaining;
                            SET @Remaining = '';
                        END;
                    END;
                END;

                INSERT INTO @ChunkOutput (ChunkNumber, TableName, SqlStatement, ChunkRowCount, StatementSize, StatementType)
                SELECT
                    @ChunkNum,
                    @table,
                    @MergePrefix + @ChunkValues + @MergeSuffix,
                    (LEN(@ChunkValues) - LEN(REPLACE(@ChunkValues, @FullRowDelim, ''))) / LEN(@FullRowDelim) + 1,
                    LEN(@MergePrefix) + LEN(@ChunkValues) + LEN(@MergeSuffix),
                    'MERGE';

                SET @ChunkNum = @ChunkNum + 1;
            END;
        END;
    END;

    IF @DeleteSql IS NOT NULL
        INSERT INTO @ChunkOutput (ChunkNumber, TableName, SqlStatement, ChunkRowCount, StatementSize, StatementType)
        SELECT
            (SELECT ISNULL(MAX(ChunkNumber), 0) + 1 FROM @ChunkOutput),
            @table,
            @DeleteSql,
            0,
            LEN(@DeleteSql),
            'DELETE';

    SELECT
        ChunkNumber,
        TableName,
        SqlStatement,
        ChunkRowCount AS [RowCount],
        StatementSize,
        StatementType
    FROM @ChunkOutput
    ORDER BY ChunkNumber;

END TRY
BEGIN CATCH
    SET @ErrorMessage = ERROR_MESSAGE();
    RAISERROR(@ErrorMessage, 16, 1);
    RETURN;
END CATCH