Цель
Перемещение полей в новую базу данных в группы строк, основанных на фиксированном количестве строк, итерация до тех пор, пока общее количество строк в исходной таблице связанного сервера не станет равным количеству строк в таблице назначения нового сервера.
Процедура
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;