SQL Server: можно ли вставить в две таблицы одновременно?
моя база данных содержит три таблицы, называемые Object_Table,Data_Table и Link_Table. Таблица ссылок содержит только два столбца: идентификатор записи объекта и идентификатор записи данных.
Я хочу скопировать данные из DATA_TABLE где он связан с одним заданным идентификатором объекта и вставляет соответствующие записи в Data_Table и Link_Table для другой заданной идентичности объекта.
Я можете сделайте это, выбрав в переменную таблицы и цикл через выполнение двух вставок для каждой итерации.
это лучший способ сделать это?
Edit: я хочу избежать цикла по двум причинам, первая из которых заключается в том, что я ленив, а таблица loop/temp требует больше кода, больше кода означает больше мест для совершения ошибки, а вторая причина-беспокойство о производительности.
Я могу скопировать все данные в один вставить, но как это сделать в таблице ссылку на новые записи данных, где каждая запись имеет новый удостоверение?
11 ответов:
в одном сообщении: нет.
в одном сделки: Да
BEGIN TRANSACTION DECLARE @DataID int; INSERT INTO DataTable (Column1 ...) VALUES (....); SELECT @DataID = scope_identity(); INSERT INTO LinkTable VALUES (@ObjectID, @DataID); COMMITхорошая новость заключается в том, что приведенный выше код также гарантируется atomic, и может быть отправлен на сервер из клиентского приложения с одной строкой sql в одном вызове функции, как если бы это был один оператор. Вы также можете применить триггер к одной таблице, чтобы получить эффект одной вставки. Тем не менее, это в конечном счете еще два заявления, и вы, вероятно не хочу запускать триггер для каждый вставить.
вам все еще нужно два
INSERTзаявления, но похоже, что вы хотите получитьIDENTITYиз первой вставки и использовать его во втором, в этом случае, вы можете посмотреть вOUTPUTилиOUTPUT INTO: http://msdn.microsoft.com/en-us/library/ms177564.aspx
следующее устанавливает ситуацию, которую я имел, используя переменные таблицы.
DECLARE @Object_Table TABLE ( Id INT NOT NULL PRIMARY KEY ) DECLARE @Link_Table TABLE ( ObjectId INT NOT NULL, DataId INT NOT NULL ) DECLARE @Data_Table TABLE ( Id INT NOT NULL Identity(1,1), Data VARCHAR(50) NOT NULL ) -- create two objects '1' and '2' INSERT INTO @Object_Table (Id) VALUES (1) INSERT INTO @Object_Table (Id) VALUES (2) -- create some data INSERT INTO @Data_Table (Data) VALUES ('Data One') INSERT INTO @Data_Table (Data) VALUES ('Data Two') -- link all data to first object INSERT INTO @Link_Table (ObjectId, DataId) SELECT Objects.Id, Data.Id FROM @Object_Table AS Objects, @Data_Table AS Data WHERE Objects.Id = 1спасибо другому ответ это указало мне на предложение вывода, которое я могу продемонстрировать решение:
получается, что это не так просто в реальной жизни из-за следующей ошибки-- now I want to copy the data from from object 1 to object 2 without looping INSERT INTO @Data_Table (Data) OUTPUT 2, INSERTED.Id INTO @Link_Table (ObjectId, DataId) SELECT Data.Data FROM @Data_Table AS Data INNER JOIN @Link_Table AS Link ON Data.Id = Link.DataId INNER JOIN @Object_Table AS Objects ON Link.ObjectId = Objects.Id WHERE Objects.Id = 1предложение OUTPUT INTO не может быть включено обе стороны (первичный ключ, внешний ключ) отношения
Я могу и все же
OUTPUT INTOтаблица temp и после этого заканчивает с нормальной вставкой. Поэтому я могу избежать моего цикла, но я не могу избежать временной таблицы.
похоже, что таблица ссылок захватывает связь "многие: многие" между таблицей объектов и таблицей данных.
Я предлагаю использовать хранимую процедуру для управления транзакциями. Если вы хотите вставить в объект или таблицу данных выполните свои вставки, получите новые идентификаторы и вставьте их в таблицу ссылок.
Это позволяет всей вашей логике оставаться инкапсулированной в один простой вызов sproc.
Если вы хотите, чтобы действия были более или менее атомарными, я бы обязательно обернул их в транзакцию. Таким образом, вы можете быть уверены, что оба произошли или оба не произошло по мере необходимости.
можно создать представление, выбрав имена столбцов, необходимые для инструкции insert, добавить триггер INSTEAD OF INSERT и вставить в это представление.
вставка может работать только на одной таблице одновременно. Несколько вставок должны иметь несколько операторов.
Я не знаю, что вам нужно сделать цикл через переменную таблицы - не можете ли вы просто использовать массовую вставку в одну таблицу, а затем массовую вставку в другую?
кстати-я предполагаю, что вы имеете в виду скопировать данные из Object_Table; в противном случае вопрос не имеет смысла.
перед тем, как сделать многопозиционную вставку в Oracle, вы можете использовать трюк, связанный с вставкой в представление, в котором был определен триггер INSTEAD OF для выполнения вставок. Можно ли это сделать в SQL Server?
Я хочу подчеркнуть, используя
SET XACT_ABORT ON;для транзакции MSSQL с несколькими инструкциями sql.
см.:https://msdn.microsoft.com/en-us/library/ms188792.aspx Они дают очень хороший пример.
Итак, окончательный код должен выглядеть следующим образом:
SET XACT_ABORT ON; BEGIN TRANSACTION DECLARE @DataID int; INSERT INTO DataTable (Column1 ...) VALUES (....); SELECT @DataID = scope_identity(); INSERT INTO LinkTable VALUES (@ObjectID, @DataID); COMMIT
-- ================================================ -- Template generated from Template Explorer using: -- Create Procedure (New Menu).SQL -- -- Use the Specify Values for Template Parameters -- command (Ctrl-Shift-M) to fill in the parameter -- values below. -- -- This block of comments will not be included in -- the definition of the procedure. -- ================================================ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE InsetIntoTwoTable ( @name nvarchar(50), @Email nvarchar(50) ) AS BEGIN SET NOCOUNT ON; insert into dbo.info(name) values (@name) insert into dbo.login(Email) values (@Email) END GO
//Если вы хотите вставить то же самое, что и первая таблица
$qry = "INSERT INTO table (one, two, three) VALUES('$one','$two','$three')"; $result = @mysql_query($qry); $qry2 = "INSERT INTO table2 (one,two, three) VVALUES('$one','$two','$three')"; $result = @mysql_query($qry2);
//или если вы хотите вставить некоторые части стола
$qry = "INSERT INTO table (one, two, three) VALUES('$one','$two','$three')"; $result = @mysql_query($qry); $qry2 = "INSERT INTO table2 (two) VALUES('$two')"; $result = @mysql_query($qry2);//Я знаю, что это выглядит слишком хорошо, чтобы быть правым, но это работает, и вы можете продолжать добавлять запрос просто изменить
"$qry"-number and number in @mysql_query($qry"")
у меня есть 17 таблиц, в которых это сработало.
Comments