SQL Server: Aynı anda iki tabloya eklemek mümkün mü?


144

Veritabanım Object_Table, Data_Tableve adlı üç tablo içeriyor Link_Table. Bağlantı tablosu yalnızca iki sütun içerir: bir nesne kaydının kimliği ve bir veri kaydının kimliği.

Ben verileri kopyalamak istediğiniz DATA_TABLEo tek bir nesne kimliğine ve içine kayıtları karşılık gelen uç bağlantılıdır nerede Data_Tableve Link_Tablefarklı bir verilen nesne kimliği için.

Ben yapabilirsiniz bir tablo değişkeni seçme ve her yineleme için iki ekler yaparak bir döngü ile bunu.

Bunu yapmanın en iyi yolu bu mu?

Düzenleme : İki nedenden dolayı bir döngü önlemek istiyorum, ilk tembel olduğum ve bir döngü / temp tablo daha fazla kod gerektirir, daha fazla kod bir hata yapmak için daha fazla yer anlamına gelir ve ikinci nedeni performans hakkında bir endişe.

Tüm verileri tek bir ekte kopyalayabilirim, ancak her kaydın yeni bir kimliğe sahip olduğu yeni veri kayıtlarına bağlantı oluşturmak için bağlantı tablosunu nasıl alabilirim?


2 uç ile yaparken mükemmel bir şekilde iyi çalışır, bir uç ile yapmaya çalışıyorum ilgi almıyorum. Yani her iki ucun da tamamlandığından emin olmak istiyor musunuz? Ardından bu işleme / geri alma talimatını kontrol etmeniz gerekir.
Philippe Grondier

2
İki ek ile mutlu olurum, sadece bağlantı tablosuna eklenmesi gereken kimlikler ilk ekte oluşturulan kimliklerdir.
tpower

Yanıtlar:


220

Bir açıklamada : Hayır.

Bir işlemde : Evet

BEGIN TRANSACTION
   DECLARE @DataID int;
   INSERT INTO DataTable (Column1 ...) VALUES (....);
   SELECT @DataID = scope_identity();
   INSERT INTO LinkTable VALUES (@ObjectID, @DataID);
COMMIT

İyi haber, yukarıdaki kodun da atomik olması garanti edilir ve tek bir işlev çağrısında bir deyimmiş gibi tek bir işlev çağrısında bir istemci uygulamasından sunucuya gönderilebilir. Ayrıca, tek bir eklemenin etkisini elde etmek için bir tabloya tetikleyici uygulayabilirsiniz. Ancak, sonuçta hala iki ifade vardır ve muhtemelen her ekleme için tetikleyiciyi çalıştırmak istemezsiniz .


2
Uzun zamandır aradığım şey bu. Teşekkürler :)
nandu.com

33
@Joel, harika bir soru. Muhtemelen birisi alternatif bir gerçeklik diledi ve kötü haberlerin taşıyıcısıydınız. ;)
Kirk Woll

2
Bu bugün benim gün kurtardı :) thanx
Shekhar_Pro

12
Bu sorunu çözmez. Object_Table'dan okunan veri eklemek istiyor. Yani bir insert into ... select ...açıklama. Yukarıdaki kod Object_Table verilerini nasıl okur veya döngüye alır. Yine de, askerin yapmak istemediği bir tablo değişkeni kullanmanız gerekir.
hofnarwillie

8
Elbette bu sorunu çözer. Belki bunun için tüm kodları yazmadım , ama OP de kopyalamak istediği tüm sütunları paylaşmadı. Bu cevapta gösterilen özellikler OP'nin istediği şeyi yapmasına izin verecek ... bir kayıt oluşturmak, yeni kaydın kimliğini almak ve bu kimliği atomik bir şekilde ikinci bir kayıt için kullanmak için bir sorgu çalıştırmak. OP zaten bir kesici uç / seçim yapmayı biliyor. Bu onun kaçırdığı parçadır.
Joel Coehoorn


18

Aşağıdakiler tablo değişkenlerini kullanarak yaşadığım durumu ayarlar.

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

Beni ÇIKTI yantümcesine işaret eden başka bir cevap sayesinde bir çözüm gösterebilirim:

-- 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

Ancak şu hata nedeniyle gerçek hayatta bu kadar basit olmadığı ortaya çıktı

OUTPUT INTO yan tümcesi (birincil anahtar, yabancı anahtar) ilişkisinin her iki tarafında olamaz

Hala OUTPUT INTOgeçici bir masa ve sonra normal insert ile bitirebilirim. Bu yüzden döngümü önleyebilirim ama geçici tablodan kaçınamıyorum.



6

Bağ tablosunun birçok şeyi yakaladığı anlaşılıyor: Nesne tablosu ve Veri tablosu arasındaki birçok ilişki.

Benim önerim işlemleri yönetmek için saklı bir yordam kullanmaktır. Nesneye veya Veri tablosuna eklemek istediğinizde, eklerinizi gerçekleştirin, yeni kimlikleri alın ve bunları Bağlantı tablosuna ekleyin.

Bu, tüm mantığınızın çağrılabilir kolay bir sproc içinde kapsüllenmiş kalmasını sağlar.


Neden başkası seni onaylamadı? Saklı yordam açık ve en iyi yoldur. Cevabınızı Joel Coehoorn'un cevabı ile birleştirin ve en iyi yanıtı alın!
Rhyous

4

Eylemlerin az ya da çok atomik olmasını istiyorsanız, bunları bir işlemde tamamladığınızdan emin olurum. Bu şekilde, her ikisinin de gerçekleştiğinden veya her ikisinin de gerektiği gibi olmadığından emin olabilirsiniz.


2
İşlemler "az ya da çok" atomik değil, bir işlemle sarılmışsa atomiktir. Mutlaka garanti edilmeyen şey, siz belirtmedikçe, izolasyon düzeyidir.
Dave Markle

4

Insert deyiminizin gerektirdiği sütun adlarını seçerek bir Görünüm oluşturabilir, INSTEAD OF INSERT Tetikleyicisi ekleyebilir ve bu görünüme ekleyebilirsiniz.


4

Kullanımı üzerinde vurgu yapmak istiyorum

SET XACT_ABORT ON;

birden çok sql ifadesi ile MSSQL işlemi için.

Bkz. Https://msdn.microsoft.com/en-us/library/ms188792.aspx Çok iyi bir örnek veriyorlar.

Bu nedenle, son kod aşağıdaki gibi görünmelidir:

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

2

Ekleme her seferinde sadece bir masada çalışabilir. Birden Fazla Ek'in birden çok ifadesi olmalıdır.

Bir tablo değişkeni ile döngü yapmanız gerektiğini bilmiyorum - sadece bir tabloya bir toplu ekleme kullanamazsınız, o zaman diğer içine toplu ekleme?

Bu arada - Tahmin ediyorum ki Object_Table veri kopyalamak demek; aksi halde soru mantıklı değildir.


2

Oracle'da çok değişkenli bir insert yapabilmek için, insertleri gerçekleştirmek için üzerinde INSTEAD OF tetikleyicisi olan bir görünüme insert eklemek için bir hile kullanabilirsiniz. Bu SQL Server'da yapılabilir mi?


-1
-- ================================================
-- 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

Bazı açıklamalar ekleyebilir misiniz?
Kyll

-2

// ilk tabloyla aynı eklemek istiyorsanız

$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);

// veya birinci tablonun belirli bölümlerini eklemek istiyorsanız

 $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);

// doğru olamayacak kadar iyi göründüğünü biliyorum, ama işe yarıyor ve sorgu eklemeye devam edebilirsiniz.

    "$qry"-number and number in @mysql_query($qry"")

Bu çalışmış 17 tablo var.


kesici uçların ortasında bir şeyler ters giderse? Ek belgeleriniz eksik olacak. sağ? Bunu yapıyorsanız .. tedavi etmek için bir geri alma fonksiyonunuz var mı? Değilse .. veri bütünlüğünüzle ilgili bir sorununuz var.
deepcell

7
-1. Bu yanıt PHP'de MySQL yöntemlerini kullanıyor gibi görünüyor. Soru, MySQL veya PHP'den bahsetmeden sql ve sql-server olarak etiketlenir .
mskfisher
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.