Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Вставка по Top (1000) SQL 2012  [new]
Гулин Федор
Member

Откуда: МИНСК
Сообщений: 1240
Добрый день всем.

SQL 2012

Операция РАЗОВАЯ (конвертация данных)
в этот момент я буду один на БД

Надо разбить один инсерт из темп. таблицы ##RR2 на батчи
потому что целевая таблица реплицируется на кучу (> 20) филиалов
( в реальности таких таблиц будет 3-4 )

в ##RR2 скажем 1 000 000 записей
( без репликации это копейки <5 секунд )


Есть ли гарантия что в 1- м Select и во 2-м DELETE TOP будет одинаковый набор данных ???

WHILE 1=1
BEGIN 
	
	BEGIN TRAN 
		Insert into d3
			(  )
		SELECT  TOP (1000)
		
		FROM  ##RR2   
		
		SET @rc1 =  @@ROWCOUNT
		-- print @@TRANCOUNT
		
	COMMIT 	
	
	IF @rc1 = 0 BREAK ;
	
	DELETE TOP (1000)  FROM  ##RR2
	
	PRINT @i
	Set @i = @i + 1
END 	 


Если нет гаратнии

то Как воркарвунд ?
вставлять в ##RR2 - доп. поле счетчика Id1
и делать то же самое

SELECT  TOP (1000) ORDER BY  id1
DELETE TOP (1000)  FROM  ##RR2 ORDER BY  id1


или другой воркарунд проще ?
PK в таблице ##RR2 не очевиден ( т.е в каждом случае он м.б разным для разных таблиц )
18 окт 19, 17:41    [21997643]     Ответить | Цитировать Сообщить модератору
 Re: Вставка по Top (1000) SQL 2012  [new]
Гулин Федор
Member

Откуда: МИНСК
Сообщений: 1240
зы добавлю что кусок кода я вроде как протестировал
несколько раз
и у меня вроде как все получается ок в 1-м варианте
но все равно меня смущает сей момент
потому и спрашиваю
18 окт 19, 17:42    [21997646]     Ответить | Цитировать Сообщить модератору
 Re: Вставка по Top (1000) SQL 2012  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 7780
Гулин Федор,

гарантии даст только использование output предложение, по которому можно сохранить в таблицу список вставленных ключей и использовать эти ключи для удаления.
18 окт 19, 17:56    [21997657]     Ответить | Цитировать Сообщить модератору
 Re: Вставка по Top (1000) SQL 2012  [new]
iap
Member

Откуда: Москва
Сообщений: 46983
Гулин Федор,

нет никакой гарантии.
ORDER BY - для SELECT.

Может так?
WITH T AS(SELECT TOP(1000) * FROM ##RR2 ORDER BY id1)
DELETE T;
По крайней мере порядок записей в SELECTе гарантируется, если поле сортировки уникально.
18 окт 19, 17:57    [21997659]     Ответить | Цитировать Сообщить модератору
 Re: Вставка по Top (1000) SQL 2012  [new]
iap
Member

Откуда: Москва
Сообщений: 46983
Чего-то не понимаю. В названии темы - про INSERT, а в скрипте - DELETE ??
18 окт 19, 18:01    [21997668]     Ответить | Цитировать Сообщить модератору
 Re: Вставка по Top (1000) SQL 2012  [new]
a_voronin
Member

Откуда: Москва
Сообщений: 4740
Гулин Федор,

По чему вы решили, что DELETE удалит именно те записи, которые вставил INSERT? Естественно нет такой гарантии

		Insert into d3
		(  )
		OUTPUT INSERTED.<ключ> INTO @Keys

		SELECT  TOP (1000)
		FROM  ##RR2   


		DELETE TOP (1000)  FROM  ##RR2
		WHERE <Ключ>  IN (SEELCT * FROM @Keys) -- лучше INNER JOIN 




Insert into d3( )
SELECT TOP (1000)
FROM ##RR2
18 окт 19, 18:36    [21997694]     Ответить | Цитировать Сообщить модератору
 Re: Вставка по Top (1000) SQL 2012  [new]
invm
Member

Откуда: Москва
Сообщений: 9351
Гулин Федор,

DELETE TOP (1000) FROM ##RR2 output deleted.field1, ..., deleted.fieldN into d3(...)
18 окт 19, 18:37    [21997696]     Ответить | Цитировать Сообщить модератору
 Re: Вставка по Top (1000) SQL 2012  [new]
Гулин Федор
Member

Откуда: МИНСК
Сообщений: 1240
Всем СПАСИБО
да буду делать правильно
в моем случае проще добавить id1 во временную таблицу

WITH T AS(SELECT TOP(1000) * FROM ##RR2 ORDER BY id1)
DELETE T;
21 окт 19, 10:14    [21998656]     Ответить | Цитировать Сообщить модератору
 Re: Вставка по Top (1000) SQL 2012  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 7780
Гулин Федор,

сортировка заметно дороже использования OUTPUT, это не оптимальное решение. Можно использовать триггер после вставки. В таблице inserted получите список ключей, которые надо удалить из источника. При этом не потребуется временная таблица и размер пачки может задавать произвольно запросом и гарантируется целостность переноса.
21 окт 19, 13:17    [21998948]     Ответить | Цитировать Сообщить модератору
 Re: Вставка по Top (1000) SQL 2012  [new]
Гулин Федор
Member

Откуда: МИНСК
Сообщений: 1240
Владислав Колосов,
это разовая задача
в данном случае мин. затраты как раз с id1
Времен.таблица уже есть и там куча логики по ее созданию

зы м.б еще я мало output юзал мало - понимать да понимаю
+ я еще писал что там ПК НЕ очевиден ( в 4 случаях )
а тут я единообзрано вставил 4 куска и все
- а так бы пришлось жойнить по ПК - а поля то разные

Alter Table  ##RR2 Add id1 int  identity ;

WHILE 1=1
BEGIN 

BEGIN TRAN 
Insert into 
		SELECT  TOP (1000)
		...
		FROM  ##RR2   
		ORDER BY id1 

SET @rc1 =  @@ROWCOUNT
		-- print @@TRANCOUNT
	COMMIT 	
	
	IF @rc1 = 0 BREAK ;		
WITH T1 AS( SELECT TOP(1000) * FROM ##RR2 ORDER BY id1 )
	DELETE T1;
END 	 
21 окт 19, 14:18    [21999027]     Ответить | Цитировать Сообщить модератору
 Re: Вставка по Top (1000) SQL 2012  [new]
Артем Falcon
Member

Откуда: Россия
Сообщений: 4
Гулин Федор,


/*
Кидал данные из table1(mssql) в table2(postgree) через Linkserver. Объем большой, требовалось кидать по небольшим пакетам, иначе ( если больше 40000 строк за раз) связь обрывалась.
Написал вот так
*/
declare @a table(id_pg_max int);
declare @b int;
declare @c table(id int);
set @b=10000;

--------------------------------------------------ЦИКЛ------------------------------------------------------------------

	WHILE 
		(select case when max(id) is null then 0 else max(id) end from table2) < (select max(id) from  table1) 
		
		BEGIN
							 ----------------------BREAK------------------------- созданная таблица, для  прерывание цикла
							 IF EXISTS (SELECT * FROM break_point WHERE point=1)	
							 BEGIN
							 BREAK;
							 END
							 ----------------------------------------------------			  

				insert into @a (id_pg_max)								----диапозон ID от @a
				select  case when max(id) is null then 0 else max(id)end +1 as id
				from  table2;
				
				insert into @c (id)										----диапозон ID до @с
				select case when max(id) is null then 0 else max(id) end+@b as id 
				from  table2;
						

				insert into table2		----вставка значений из диапозона от @a до @с
				(
					id, fam, im, ot
				)
				select												 
					id, fam, im, ot
				from test..table1 
				where id between (select * from @a) and  (select * from @c)
				order by id;

				delete from @a	--чищу переменную
				delete from @c	--чищу переменную

		END


Сообщение было отредактировано: 30 окт 19, 16:51
30 окт 19, 16:08    [22006199]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить