ИСПОЛЬЗУЯ ROW_NUMBER и WHILE для разделения строк с помощью SELECT INSERT INTO со связанного сервера на новый сервер - PullRequest
0 голосов
/ 23 марта 2020

Цель

Перемещение полей в новую базу данных в группы строк, основанных на фиксированном количестве строк, итерация до тех пор, пока общее количество строк в исходной таблице связанного сервера не станет равным количеству строк в таблице назначения нового сервера.

Процедура

1- В temptbl определить количество строк и минимальный / максимальный идентификатор первичного ключа исходной таблицы

SELECT
   [Source_total_rows]   =   COUNT(invoice_id)
,  [Source_Min_ID]       =   MIN(invoice_id)
,  [Source_Max_ID]       =   MAX(invoice_id)

INTO #Source_Ctrl
FROM [LinkedServer].[DB].[dbo].[Invoices]
--results: Distance between Min & Max IDs is 399,150,000‬ but actual count of ids is 730,000

Source_total_rows | Source_Min_ID | Source_Max_ID
730000            | 850000        | 400000000

2- Используя локальные переменные, установить этаж , потолок и размер куска для обхода пропусков в идентификаторах

DECLARE @tbl_row_count          bigint

DECLARE @row_floor              bigint
DECLARE @row_ceiling            bigint
DECLARE @row_chunks             int

SET @row_chunks         =   2500000     
SET @row_floor          =   0
SET @row_ceiling        =   @row_floor + @row_chunks 
SET @tbl_row_count      =   (SELECT Source_total_rows FROM #SourceCtrl)           

3 - Использование оператора WHILE l oop - SELECT INTO с использованием локальных переменных в WHERE для итерации по оператору

WHILE   @row_ceiling < @tbl_row_count


BEGIN
   (
   WITH cte_transfer_rows(Row_Nbr, Invoice_Group, Invoice_Status, Invoice_ID)
   AS
   (SELECT
       [Row_Nbr]       =   ROW_NUMBER() OVER(ORDER BY Invoice_ID)
   ,   [Invoice_Group]
   ,   [Invoice_Status]
   ,   [Invoice_ID]

   FROM [LinkedServer].[DB].[dbo].[Invoices])

   SELECT
       [Invoice_Group]
   ,   [Invoice_Status]
   ,   [Invoice_ID]

   INTO [NewDB].[dbo].Stg_Invoices
   FROM cte_transfer_rows
   WHERE Row_Nbr BETWEEN @row_floor AND @row_ceiling
   )
   ;
   SET @row_floor   = @row_ceiling + 1
   SET @row_ceiling = @row_floor + @row_chunks
   ;
   DROP TABLE [NewDB].[dbo].Stg_Invoices
   ;
END;

Проблема

В столбце первичного ключа есть пробелы между идентификаторами. Используйте ROW_NUMBER(), чтобы получить отражающее число строк таблицы по идентификатору первичного ключа. Ошибка связана с использованием CTE вместе с WHILE. Исследования показывают, что использование табличных переменных или временных таблиц не позволяет хранить полное табличное выражение в базе данных tempdb из-за ограничений размера и базы данных tempdb.

Полный сценарий

DROP TABLE #SourceCtrl
SELECT
   [Source_total_rows]   =   COUNT(invoice_id)
,  [Source_Min_ID]       =   MIN(invoice_id)
,  [Source_Max_ID]       =   MAX(invoice_id)

INTO #Source_Ctrl
FROM [LinkedServer].[DB].[dbo].[Invoices]

WHILE   @row_ceiling < @tbl_row_count

DECLARE @tbl_row_count          bigint

DECLARE @row_floor              bigint
DECLARE @row_ceiling            bigint
DECLARE @row_chunks             int

SET @row_chunks         =   2500000     
SET @row_floor          =   0
SET @row_ceiling        =   @row_floor + @row_chunks 
SET @tbl_row_count      =   (SELECT Source_total_rows FROM #SourceCtrl)    

WHILE   @row_ceiling < @tbl_row_count


BEGIN
   (
   WITH cte_transfer_rows(Row_Nbr, Invoice_Group, Invoice_Status, Invoice_ID)
   AS
   (SELECT
       [Row_Nbr]       =   ROW_NUMBER() OVER(ORDER BY Invoice_ID)
   ,   [Invoice_Group]
   ,   [Invoice_Status]
   ,   [Invoice_ID]

   FROM [LinkedServer].[DB].[dbo].[Invoices]
   )
   SELECT
       [Invoice_Group]
   ,   [Invoice_Status]
   ,   [Invoice_ID]

   INTO [NewDB].[dbo].Stg_Invoices
   FROM cte_transfer_rows
   WHERE Row_Nbr BETWEEN @row_floor AND @row_ceiling
   )
   ;
   SET @row_floor   = @row_ceiling + 1
   SET @row_ceiling = @row_floor + @row_chunks
   ;
   DROP TABLE [NewDB].[dbo].Stg_Invoices
   ;
END;
...