Pergunta

O meu banco de dados contém três tabelas chamadas Object_Table, Data_Table e Link_Table. A tabela de ligação contém apenas duas colunas, a identidade de um registro de objeto e uma identidade de um registro de dados.

Eu quero copiar os dados do DATA_TABLE onde ela está ligada a uma dada identidade de objeto e inserir registros correspondentes em Data_Table e Link_Table para uma dada identidade de objeto diferente.

I pode fazer isso selecionando em uma variável de tabela e o looping através de fazer duas inserções para cada iteração.

Esta é a melhor maneira de fazê-lo?

Editar : eu quero evitar um loop para dois motivos, o primeiro é que eu sou preguiçoso e uma mesa de loop / temp requer mais código, mais meios de código mais lugares para cometer um erro e a segunda razão é a preocupação com o desempenho.

Eu posso copiar todos os dados em um insert mas como obter a tabela de link para link para os novos registros de dados onde cada registro tem um novo id?

Foi útil?

Solução 3

Os seguintes sets a situação que eu tinha, usando variáveis ??de tabela.

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

Graças a outra resposta que apontou-me para a cláusula OUTPUT posso demonstrar uma solução:

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

Acontece, porém, que não é tão simples na vida real por causa do seguinte erro

a cláusula OUTPUT INTO não pode estar em ambos os lados de um (chave primária, estrangeira chave de relacionamento)

Ainda posso OUTPUT INTO uma tabela temporária e depois terminar com a inserção normal. Então eu posso evitar meu loop, mas não posso evitar a tabela temporária.

Outras dicas

Em um declaração :. Não

Em um transação : Sim

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

A boa notícia é que o código acima também é garantido para ser atômica , e pode ser enviado para o servidor de um aplicativo cliente com uma corda sql em uma única chamada de função como se fosse um declaração. Você também pode aplicar um gatilho para uma tabela para obter o efeito de uma única inserção. No entanto, é em última análise, ainda duas declarações e você provavelmente não quer correr o gatilho para todas Inserir.

Você ainda precisa de duas declarações INSERT, mas parece que você deseja obter o IDENTITY da primeira inserção e usá-lo no segundo, nesse caso, você pode querer olhar para OUTPUT ou OUTPUT INTO: http://msdn.microsoft.com/en-us/library/ms177564.aspx

Parece que a tabela capturas ligar os muitos:. Muitos relação entre a tabela de objeto e mesa de Dados

A minha sugestão é usar um procedimento armazenado para gerenciar as transações. Quando você deseja inserir o objeto ou a tabela de dados executar suas inserções, consiga as novas IDs e inseri-los para a mesa de ligação.

Isso permite que toda a sua lógica para permanecer encapsulados em um fácil de chamar sproc.

Se você quiser as ações a ser mais ou menos atômica, eu certifique-se de envolvê-los em uma transação. Dessa forma, você pode ter certeza que tanto aconteceu ou ambos não aconteceu conforme necessário.

Você pode criar uma visão selecionando os nomes das colunas exigidas pelo seu instrução de inserção, adicionar uma vez de Inserir Trigger, e inserir este ponto de vista.

Eu quero o estresse sobre o uso

SET XACT_ABORT ON;

para a transação MSSQL com várias instruções SQL.

Veja: https://msdn.microsoft.com/en-us/ biblioteca / ms188792.aspx Eles fornecem um bom exemplo.

Assim, o código final deverá ser parecido com o seguinte:

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

Inserir só pode operar em uma mesa ao mesmo tempo. Várias inserções tem que ter várias instruções.

Eu não sei o que você precisa para fazer o looping através de uma variável de tabela? - você não pode apenas usar uma inserção em massa em uma mesa, em seguida, a inserção em massa para o outro

Pela maneira - eu estou supondo que você quer dizer copiar os dados do Object_Table; caso contrário, a pergunta não faz sentido.

Antes de ser capaz de fazer uma inserção multitable no Oracle, você pode usar um truque que envolve uma inserção em uma visão que teve um disparador INSTEAD OF definido sobre ele para executar as inserções. isso pode ser feito em SQL Server?

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

// se você deseja inserir o mesmo que primeira tabela

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

// ou se você deseja inserir certas partes de uma tabela

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

// i sei que parece bom demais para ser certo, mas ele funciona e você pode continuar a acrescentar consulta é só mudar o

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

Eu tenho 17 tabelas Isso tem funcionado em.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top