2013-01-31 5 views
2

J'ai besoin de copier le contenu d'une table à elle-même et les tables connexes ... Laissez-moi schématiser le problème. Disons que j'ai deux tables:Copier le contenu dans TSQL

Order 
OrderID : int 
CustomerID : int 
OrderName : nvarchar(32) 

OrderItem 
OrderItemID : int 
OrderID : int 
Quantity : int 

Avec le PK étant auto-incrémenté. Disons que je veux dupliquer le contenu d'un client à un autre. Comment est-ce que je fais cela efficacement?

Le problème sont les PK. Je devrais mapper les valeurs de OrderIDs de l'ensemble de données original à la copie afin de créer des références appropriées dans OrderItem. Si je sélectionne simplement-Insérer, je ne serai pas en mesure de créer cette carte.

Suggestions?

+1

vous pouvez utiliser la table temporaire et stocker proc fais le problème. – Hiten004

+1

Quelle version de SQL Server/Sybase? –

+0

Le OrderName est-il unique par client? Donc, un client a-t-il déjà plusieurs commandes avec le même OrderName? – Jacco

Répondre

0

Avez-vous besoin d'avoir les clés primaires du tableau A comme primaires dans le tableau B? Sinon, vous pouvez faire une déclaration select avec un insert dans. Les clés primaires sont généralement des int qui partent d'une graine toujours croissante (identité). Contourner cela et déclarer une insertion de ces mêmes données de manière problématique a l'inconvénient de quelqu'un qui pense que c'est une clé distincte définie sur cette table et non une valeur de «relation» ou de clé étrangère.

Vous pouvez sélectionner les clés primaires pour les insertions dans d'autres tables, mais pas elles-mêmes .... À MOINS que vous ne définissiez l'indice 'identity insert on'. Ne faites pas cela à moins de savoir ce que cela fait car vous pouvez créer plus de problèmes que cela en vaut la peine si vous ne comprenez pas les ramifications.

Je voudrais juste faire le ole:

insert dans TableB select * de TableA où (critères)

Exemple simple (Ceci suppose SQL Server 2008 ou supérieur). Mon mauvais je ne vous ai pas vu n'a pas énuméré le cadre de TSQL. Je ne sais pas si cela fonctionnera sur Oracle ou MySql.

declare @Order Table (OrderID int identity primary key, person varchar(8)); 

insert into @Order values ('Brett'),('John'),('Peter'); 

declare @OrderItem Table (orderItemID int identity primary key, OrderID int, OrderInfo varchar(16)); 

insert into @OrderItem 
select 
    OrderID -- I can insert a primary key just fine 
, person + 'Stuff' 
from @Order 

select * 
from @Order 

Select * 
from @OrderItem 
0
  • Ajouter une colonne d'aide supplémentaire à l'ordre appelé OldOrderID
  • Copiez tous les de l'Ordre du @OldCustomerID au @NewCustomerID
  • Copiez tous les OrderItems à l'aide de la colonne OldOrderID pour aider à faire la relation
  • Retirez la colonne d'aide supplémentaire de commande

    TABLE ALTER commande Ajouter OldOrderID INT NULL

    INSERT INTO commande (CustomerID, OrderName, OldOrderID) SELECT @NewCustomerID, OrderName, ORDERID DÉCRET OU = CustomerID @OldCustomerID

    INSERT INTO OrderItem (OrderID, quantité) SELECT o.OrderID, i. Quantité FROM Commande o INNER JOIN OrderItem i ON o.OldOrderID = i.OrderID O WH o.CustomerID = @NewCustomerID

    MISE A JOUR SET ordre OldOrderID = null OÙ OldOrderID IS NOT NULL

    ALTER TABLE DROP COLUMN OldOrderID ordre

+0

J'ai oublié de mentionner que ce n'était pas un événement unique mais un événement «normal» (bien qu'un peu rare) dans une application. Je pourrais laisser la colonne là mais c'est un peu poluant sur le schéma. –

+0

@ Vincent-Philippe Lauzon - Le code dans la réponse DROP (supprime) la colonne supplémentaire. Vous pouvez utiliser une table temporaire au lieu de modifier la table, mais c'est la solution la plus simple. –

0

SI le OrderName est unique par client, vous pouvez simplement faire :

INSERT INTO [Order] ([CustomerID], [OrderName]) 
    SELECT 
    2 AS [CustomerID], 
    [OrderName] 
    FROM [Order] 
    WHERE [CustomerID] = 1 

INSERT INTO [OrderItem] ([OrderID], [Quantity]) 
    SELECT 
    [o2].[OrderID], 
    [oi1].[Quantity] 
    FROM [OrderItem] [oi1] 
    INNER JOIN [Order] [o1] ON [oi1].[OrderID] = [o1].[OrderID] 
    INNER JOIN [Order] [o2] ON [o1].[OrderName] = [o2].[OrderName] 
    WHERE [o1].[CustomerID] = 1 AND [o2].[CustomerID] = 2 

Sinon, vous devrez utiliser une table temporaire ou modifier la table existante Order comme @LastCoder suggéré.

1

Pour dupliquer un parents et beaucoup d'enfants avec des identités comme les clés, je pense que la clause OUTPUT peut rendre les choses assez propre (SqlFiddle here):

-- Make a duplicate of parent 1, including children 

-- Setup some test data 
create table Parents (
     ID int not null primary key identity 
    , Col1 varchar(10) not null 
    , Col2 varchar(10) not null 
) 
insert into Parents (Col1, Col2) select 'A', 'B' 
insert into Parents (Col1, Col2) select 'C', 'D' 
insert into Parents (Col1, Col2) select 'E', 'F' 

create table Children (
     ID int not null primary key identity 
    , ParentID int not null references Parents (ID) 
    , Col1 varchar(10) not null 
    , Col2 varchar(10) not null 
) 
insert into Children (ParentID, Col1, Col2) select 1, 'g', 'h' 
insert into Children (ParentID, Col1, Col2) select 1, 'i', 'j' 
insert into Children (ParentID, Col1, Col2) select 2, 'k', 'l' 
insert into Children (ParentID, Col1, Col2) select 3, 'm', 'n' 

-- Get one parent to copy 
declare @oldID int = 1 

-- Create a place to store new ParentID 
declare @newID table (
    ID int not null primary key 
) 

-- Create new parent 
insert into Parents (Col1, Col2) 
output inserted.ID into @newID -- Capturing the new ParentID 
select Col1, Col2 
from Parents 
where ID = @oldID -- Only one parent 

-- Create new children using the new ParentID 
insert into Children (ParentID, Col1, Col2) 
select n.ID, c.Col1, c.Col2 
from Children c 
    cross join @newID n 
where c.ParentID = @oldID -- Only one parent 

-- Show some output 
select * from Parents 
select * from Children 
+0

Bingo! C'est ce que je cherchais pour construire la cartographie à la volée. Jamais entendu parler de cette «clause de sortie» avant. Jamais vu le violon SQL non plus! Merci! –

+0

Content d'entendre. S'il vous plaît upvote et/ou marquer comme réponse pour aider les futurs visiteurs. En outre, @MikaelEriksson a un excellent lien pour travailler avec plusieurs parents. –

Questions connexes