Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Вставка данных из врем. таблиц в постоянные  [new]
Black Queen
Member

Откуда:
Сообщений: 10
Имеются след. постоянные таблицы:
table1 с полями [id], [pole1], первичный ключ [id] identity(1,1)
table2 c полями [id], [pole2], [pole3], первичный ключ {[id], [pole2]}
Они связаны через [id] один (из table1) ко многим (table2)
И временные:
#table1 с полями [id], [pole1]
#table2 c полями [id], [pole2], [pole3]

Проблема: нужно вставить данные из временных таблиц в постоянные. После вставки строк из #table1 в table1, у них изменятся значения поля [id] и я не узнаю, с каким [id] вставлять строки из #table2.
Может ли кто-нибудь предложить решение, кроме курсоров?
24 дек 05, 15:15    [2206379]     Ответить | Цитировать Сообщить модератору
 Re: Вставка данных из врем. таблиц в постоянные  [new]
saint
Member

Откуда: Архангельск
Сообщений: 2262
например:

SET IDENTITY_INSERT table1 OFF

insert table1 select * from #table1

SET IDENTITY_INSERT table1 ON

insert table2 select * from #table2


если вы точно знаете, что id не пересекутся
24 дек 05, 15:55    [2206438]     Ответить | Цитировать Сообщить модератору
 Re: Вставка данных из врем. таблиц в постоянные  [new]
Black Queen
Member

Откуда:
Сообщений: 10
Спасибо за ответ, но в том что они не пересекутся, я не уверен, скорее даже наооборот.
24 дек 05, 16:03    [2206456]     Ответить | Цитировать Сообщить модератору
 Re: Вставка данных из врем. таблиц в постоянные  [new]
saint
Member

Откуда: Архангельск
Сообщений: 2262
begin tran

Update table1 with (tablockx) set pole1=1 where 1=2
declare @last1 int
declare @last2 int
set @last=IDENT_CURRENT('table1')
insert table1(pole1) select pole1 from #table1 order by id asc

insert table2 
select c.cnt+@last, pole2, pole3
from
(
select a.id, count (b.id) as cnt
from #table1 as a inner join #table1 as b on a.id>=b.id
group by a.id
) as c
inner join #table2 as d on c.id=d.id

commit tran
так попробуйте. работоспособность не проверял. могут быть синтаксические ошибки.
with (tablockx) 

- это полная блокировка таблицы. так что др соединения не смогут сней в момент вставки работать
24 дек 05, 17:13    [2206583]     Ответить | Цитировать Сообщить модератору
 Re: Вставка данных из врем. таблиц в постоянные  [new]
user007
Guest
1. Для того чтобы сделать вставку в несколько таблиц существует понятие ТРАНЗАКЦИЯ.
2. Изменять ключи в таблицах - плохой стиль.
24 дек 05, 17:34    [2206594]     Ответить | Цитировать Сообщить модератору
 Re: Вставка данных из врем. таблиц в постоянные  [new]
Black Queen
Member

Откуда:
Сообщений: 10
Спасибо большое, идею я по-моему понял. Но не могли бы вы пояснить зачем нужна 2 строка (Update table1 with (tablockx) set pole1=1 where 1=2) и почему нельзя использовать with (tablockx) в insert table1(pole1) select pole1 from #table1 order by id asc?
24 дек 05, 17:35    [2206595]     Ответить | Цитировать Сообщить модератору
 Re: Вставка данных из врем. таблиц в постоянные  [new]
Black Queen
Member

Откуда:
Сообщений: 10
user007, извините, а вы не могли бы предложить хотя бы принципиальное решение данной проблемы?
24 дек 05, 17:56    [2206613]     Ответить | Цитировать Сообщить модератору
 Re: Вставка данных из врем. таблиц в постоянные  [new]
ayam
Member

Откуда: SPb
Сообщений: 133
пара вариантов

declare @max int select @max=max(isnull(id,0)) from table1
set identity_insert table1 on
insert table1 select id+@max,pole1 from #table1
set identity_insert table1 off
insert table2 select id+@max,pole2,pole3 from #table2

alter table table1 add idtmp int
insert table1(idtmp,pole1) select id,pole1 from #table1
insert table2
select t1.id,t2.pole2,t2.pole3 from #table2 t2
join table1 t1 on t1.idtmp=t2.id
alter table table1 drop column idtmp
24 дек 05, 18:50    [2206652]     Ответить | Цитировать Сообщить модератору
 Re: Вставка данных из врем. таблиц в постоянные  [new]
ayam
Member

Откуда: SPb
Сообщений: 133
вот так
declare @max int select @max=isnull(max(id),0) from table1
24 дек 05, 18:52    [2206655]     Ответить | Цитировать Сообщить модератору
 Re: Вставка данных из врем. таблиц в постоянные  [new]
saint
Member

Откуда: Архангельск
Сообщений: 2262
почему нельзя использовать with (tablockx) в insert table1(pole1) select pole1 from #table1 order by id asc?
потому что вам нужно предварительно считать последнее IDENTITY
между этими командами:
set @last=IDENT_CURRENT('table1')
insert table1(pole1) select pole1 from #table1 order by id asc
может быть вставка в таблицу из другого соединения. Поэтому мы в самом начале блокируем таблицу.
24 дек 05, 19:02    [2206663]     Ответить | Цитировать Сообщить модератору
 Re: Вставка данных из врем. таблиц в постоянные  [new]
Black Queen
Member

Откуда:
Сообщений: 10
Спасибо Saint. А что если так:
begin tran

insert table1 with (tablockx) (pole1) 
    select pole1 from #table1 order by id asc

set @last=IDENT_CURRENT('table1') - (select count(*) from #table1)

insert table2 
select c.cnt+@last, pole2, pole3
from
(
select a.id, count (b.id) as cnt
from #table1 as a inner join #table1 as b on a.id>=b.id
group by a.id
) as c
inner join #table2 as d on c.id=d.id

commit tran
24 дек 05, 20:53    [2206760]     Ответить | Цитировать Сообщить модератору
 Re: Вставка данных из врем. таблиц в постоянные  [new]
M0us
Member

Откуда: Moscow
Сообщений: 883
тут все пишут куски какого-то кода... я вот думаю - тоже какую-нибудь фигню вставить из BOL-а )

про курсоры - это тоже сильно... :)

только у меня есть встречный вопрос: а нахрена надо знать старые id?
если их нужно знать всегда - то завести еще столбец типа "id_old int"...
если их нужно знать на момент перегона данных в table, тогда я понимаю потуги "фирумян" и все перечисленные ниже десятки вариантов решения...

ЗЫ серьезно не воспринимать - видимо пиво начало действовать :)
24 дек 05, 21:08    [2206776]     Ответить | Цитировать Сообщить модератору
 Re: Вставка данных из врем. таблиц в постоянные  [new]
saint
Member

Откуда: Архангельск
Сообщений: 2262
черной королеве:
теоретически так будет медленнее, тк
Update table1 with (tablockx) set pole1=1 where 1=2
быстрее, чем
select count(*) from #table1
по крайней мере на какието доли милисекунды :-)
и разница в скорости зависит от размеров #table1

Если вам так уж не нравится UPDATE, можно воспользоваться
select * from table1 with (tablockx) where 1=2
25 дек 05, 13:54    [2207238]     Ответить | Цитировать Сообщить модератору
 Re: Вставка данных из врем. таблиц в постоянные  [new]
Black Queen
Member

Откуда:
Сообщений: 10
Еще раз спасибо. И последний вопрос. Почему бы здесь не использовать вместо IDENT_CURRENT('table1') функцию scope_identity?
BOL
SCOPE_IDENTITY returns the last identity value generated for any table in the current session and the current scope
Тогда не нужно будет беспокоиться, вставлялись ли данные из другого соединения.
А размер #table1 предположительно десятки записей.
25 дек 05, 15:27    [2207339]     Ответить | Цитировать Сообщить модератору
 Re: Вставка данных из врем. таблиц в постоянные  [new]
saint
Member

Откуда: Архангельск
Сообщений: 2262
SCOPE_IDENTITY returns the last identity value generated for any table in the current session and the current scope 
Тогда не нужно будет беспокоиться, вставлялись ли данные из другого соединения.
во-первых, SCOPE_IDENTITY Вам возвращает результат некоторой операции в вашей же сессии. Те чтоб получить SCOPE_IDENTITY(), Вам нужно сначала в table1 что-то вставить.
Во-вторых, даже если б мы получили SCOPE_IDENTITY(), нам все равно нужно беспокоиться о других соединениях, тк скрипт расчитан на то, что никто кроме вас во время транзакции не добавит в таблицу записей с id>SCOPE_IDENTITY(). Те по любому надо блокировать таблицу. А в этом случае IDENT_CURRENT предпочтительнее. (причина 1)

чтобы не блокировать таблицу - можно пойти на изменение схемы table1, добавив на постоянной основе столбец, например типа uniqueidentifier, и идентифицировать родительскую запись по этому полю.
25 дек 05, 15:56    [2207362]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить