Вложенная вставка SQL Server 2017 или использование результатов одной вставки в другой вставке - PullRequest
0 голосов
/ 15 сентября 2018

Моя проблема может быть обобщена с помощью следующего надуманного примера. У меня есть несколько таблиц:

AUTOMOBILE
AutoId Make Model Color

BATCH
BatchId SaleDate

INVENTORY
InventoryId AutoId BatchId CustomerName(string) ParkingSlipId

PARKING
ParkingSlipId SlipStatus(String)

В настоящее время в таблице INVENTORYtable или BATCH нет строк. Я хотел бы, с помощью запроса или хранимой процедуры в SQL Server Management Studio, создать некоторые поддельные данные в INVENTORY. Для этого я просто возьму первые 10 строк таблицы AUTOMOBILE и использую AutoId из AUTOMOBILE как INVENTORY.AutoId. Мне также нужно создать новую строку в пакетном режиме для каждой записи в инвентаризации. Я буду использовать BATCH.BatchId в качестве INVENTORY.BatchId. На данный момент CustomerName может быть просто словом «Фред». Для ParkingSlipId я могу взять любую строку из PARKING, где SlipStatus равен «Empty», использовать этот ParkingSlipId и изменить статус на «Full».

Я играл с этой проблемой с ограниченным успехом. Я могу, например, использовать что-то вроде:

INSERT  [BATCH] 
VALUES (GETDATE())   
DECLARE @tempLoadBatchId bigint
 SELECT @tempLoadBatchId = @@IDENTITY

Я могу использовать tempLoadBatchId в моей следующей вставке (в ИНВЕНТАРЬ)

    INSERT  [INVENTORY] (AutoId BatchId CustomerName ParkingSlipId)
VALUES (3,  @tempLoadBatchId, "Fred",77);

UPDATE [PARKING] set SlipStatus= 'FullBoat' where SlipId = 77

Обратите внимание, что это только для одной строки И я просто жестко запрограммировал AutoId.

Я бы хотел автоматизировать это. Использование курсоров кажется одним из способов сделать это, и это, безусловно, вариант (это крошечные таблицы и производительность не будет проблемой), но я также хотел бы знать, как это сделать без курсоров. Спасибо, Дэйв

БОЛЬШЕ ФОНА И ЖЕЛАЕМЫХ РЕЗУЛЬТАТОВ В ответ на комментарии я добавил еще немного информации. Я могу сделать резервную копию и прикрепить всю БД, если она используется. Я предполагаю, что StackOverflow позволит это.

Вот текущая таблица AUTO

AutoId  Make    Model   Colour
1   Ford    Taurus  White
2   GM  Cadilac Silver
3   Toyota  Prius   Blue
4   Honda   Pilot   Green
5   Kia Sonata  Yellow

Вот текущая таблица парковки

ParkingSlipId SlipStatus 1 пусто
2 Пусто
3 Пусто
4 Пусто
5 Пусто
6 Пусто
7 Пусто
8 Пусто

Для каждой строки в AUTO я хотел бы создать новую запись в BATCH, а затем использовать этот BatchId для создания новой записи INVENTORY. В этой новой записи INVENTORY я хотел бы использовать строку из AUTO и назначить parkingId и изменить соответствующий парковочный идентификатор в PARKING TO FULL. Когда все это будет сделано, таблицы BATCH, INVENTORY и PARKING должны выглядеть следующим образом:

PARKING
ParkingSlipId   SlipStatus
 1  Full      
2   Full      
3   Full      
4   Full      
5   Full      
6   Empty     
7   Empty     
8   Empty     

BATCH
BatchId SaleDate
  1 2018-09-15 00:00:00.000
2   2018-08-20 00:00:00.000
3   2018-06-22 00:00:00.000
4   2018-09-12 00:00:00.000
5   2018-07-01 00:00:00.000


INVENTORY
InventoryId AutoId  BatchId ParkingId   CustomerName
1   1   1   1   Fred
2   2   2   2   Mary
3   3   3   3   Fred
4   4   4   4   Ted
5   5   5   5   James

Могу ли я предоставить больше информации? Или в другом формате? Большое спасибо!

1 Ответ

0 голосов
/ 17 сентября 2018

Вот одно из решений поставленной проблемы. Однако я использую «курсор», чего я пытался избежать. Я был бы заинтересован в операциях на основе множеств, как предложил Кседни в

    /****** Script  ******/

DECLARE @tempLoadBatchId bigint
DECLARE @tempAutoId int
DECLARE @tempParkingId int
DECLARE @counter bigint
SET @counter = 0

--- AUTOMOBILE STUFF
DECLARE cur CURSOR FOR 
SELECT AutoId
FROM [CarExample].[dbo].[AUTOMOBILE] 

OPEN cur
FETCH NEXT FROM cur INTO @tempAutoId

--- PARKING stuff
DECLARE curParking CURSOR FOR 
SELECT ParkingSlipId
FROM [CarExample].[dbo].[PARKING] where SlipStatus = 'Empty' 

OPEN curParking
FETCH NEXT FROM curParking INTO @tempParkingId
-----
WHILE @counter < 10
BEGIN
    INSERT  [CarExample].[dbo].[BATCH] 
     VALUES (GETDATE())   
    SELECT @tempLoadBatchId = @@IDENTITY

    INSERT  CarExample.[dbo].INVENTORY (AutoId, BatchId, ParkingId, CustomerName)
VALUES (@tempAutoId, @tempLoadBatchId, @tempParkingId, 'Sally');
    SET @counter = @counter + 1

UPDATE [CarExample].[dbo].[PARKING] Set SlipStatus = 'Full' where ParkingSlipId = @tempParkingId
FETCH NEXT FROM cur INTO @tempAutoId 
FETCH NEXT FROM curParking INTO @tempParkingId
END

CLOSE cur
DEALLOCATE cur
CLOSE curParking
DEALLOCATE curParking
...