2016-07-29 1 views
2

У меня есть две таблицы, TableA и TableB так:INSERT в таблицу и UPDATE внешнего ключа в другой таблице (SQL Server 2008)

TableA 
------------------------------------------- 
| id | some_data | new_FK_column_on_B | 
| ---- | ----------- | ------------------ | 
| 1 |  ...  |  null  | 
| ... |  ...  |  null  | 
| 999 |  ...  |  null  | 
------------------------------------------- 

TableB 
---------------------- 
| id | some_data | 
| ---- | ----------- | 
|  |    | 
---------------------- 

На данный момент TableB пуст, и FK колонки в TableA является null для всех строк. Мне нужно написать одноразовый инициализирующий скрипт, чтобы заполнить TableB и инициализировать столбец FK для некоторых строк (критерий, не для всех) в TableA с помощью идентификаторов из строк, вставленных в TableB.

Я знаю два способа сделать это:

1) с использованием while и scope_identity(), вставляя новую строку в TableB и обновление TableA на каждой итерации, в то время как существует строки в TableA, которые должны быть обновлены

while (exists (select 1 from TableA where [condition])) 
begin 
    insert into TableB (some_data) values ('some_data') 

    update TableA set new_FK_column_on_B 
    where id = (select top 1 id from TableA where [condition]) 
end 

2) создать колонку temp в TableB, сохраняя id строки в TableA, для которой она была вставлена, а затем обновить TableA, используя join

alter table TableB add temp int 
go 

insert into TableB (some_data, temp) select 'some_data', id from TableA where [condition] 

update TableA 
set new_FK_column_on_B = b.id 
from TableB as b 
join TableA as a on a.id = b.temp 

alter table TableB drop column temp 

Кроме того, я пытался как-то использовать output из insert, как это, но это синтаксис неверен:

update TableA 
set new_FK_column_on_B = 
(
    select insertedId from 
    (
     insert into TableB (some_data) 
     output inserter.id as insertedId 
     values ('some_data') 
    ) 
) 
where [condition] 

Есть ли более простой способ сделать это Whithout с помощью while или модификации любой таблицы?

ответ

0

Вы можете сделать все это, как набор операций:

insert into b(some_data) 
    select distinct some_data 
    from a; 

update a 
    set new_FK_column_on_B = b.id 
    from a join 
     b 
     on a.some_data = b.some_data; 

Это предполагает, что id столбец b объявлен как identity(), поэтому он получает назначается автоматически. Это хорошая идея, но если вы хотите сделать это вручную, то первый запрос будет что-то вроде:

insert into b(some_data) 
    select row_number() over (order by (select null)), some_data 
    from (select distinct some_data 
      from a 
     ) a; 

Там нет необходимости для while цикла.

+0

Это не случай, потому что 'some_data' не то же самое для' TableA' и 'TableB'. Это может быть различное количество столбцов, разных типов, и оно не уникально в таблице, оно может повторяться. – user2123532

+0

Я думаю, что это не полный ответ, как сказал @ user2123532. – roll

0

ПРЕДУПРЕЖДЕНИЕ: Это не тестируется на всех, я это написал в блокноте:

DECLARE @TableAValues TABLE (IdTableA int, SomeData varchar) 

INSERT INTO @TableAValues(IdTableA, SomeData) 
    SELECT id, 'some_data' FROM TableA  

DECLARE @TableBIds TABLE (IdTableB int) 

INSERT INTO TableB(SomeData) 
OUTPUT INSERTED.ID INTO @TableBIds 
SELECT SomeData FROM @TableAValues 

UPDATE ta 
SET ta.new_FK_column_on_B = tbi.IdTableB 
FROM dbo.TableA AS ta 
INNER JOIN @TableAValues AS tav ON ta.id = tav.IdTableA -- used in case more records were added to table in the interim. 
LEFT OUTER JOIN @TableBIds tbi On tav.RowNum = tbi.RowNum 

Примечание: Я использую в таблицах памяти, но если вы были обеспокоены использованием памяти, вы, вероятно, просто переключитесь тех для временных таблиц на диске.

Идея я шел здесь:

  1. захватить строки из таблицы A (ID + данные), которые мы будем использовать для заполнения B и сохранить их (я использую в таблице памяти)
  2. Вставьте эти строки в B и сохраните соответствующий идентификатор B (снова в таблице памяти)
  3. Я предполагаю, что порядок строк в обеих таблицах памяти теперь будет соответствовать, поэтому идея состоит в том, что мы можем присоединиться как к памяти таблицы вместе на номер строки, чтобы получить таблицу A Id с ее таблицей B Id - которую мы используем для обновления внешнего ключа таблицы A.

Я был бы очень удивлен, если мой пример кода работает так, как есть, но, надеюсь, идея будет полезна, если не мое исполнение.