2010-06-16 4 views
1

J'ai 3 tables similaires à l'sctructure ci-dessousSplit table et insérer avec lien d'identité

CREATE TABLE [dbo].[EmpBasic](
     [EmpID] [int] IDENTITY(1,1) NOT NULL Primary Key, 
     [Name] [varchar](50), 
     [Address] [varchar](50) 
     ) 


    CREATE TABLE [dbo].[EmpProject](
     [EmpID] [int] NOT NULL primary key, // referencing column with EmpBasic 
     [EmpProject] [varchar](50) ) 



    CREATE TABLE [dbo].[EmpFull_Temp](
     [ObjectID] [int] IDENTITY(1,1) NOT NULL Primary Key, 
     [T1Name] [varchar](50) , 
     [T1Address] [varchar](50) , 
     [T1EmpProject] [varchar](50) 
      ) 

Le tableau EmpFull_Temp a les enregistrements avec un objet fictif colonne ID ... Je veux remplir les 2 premières tables avec les enregistrements dans cette table ... Mais avec EmpID comme référence entre les 2 premières tables.

J'ai essayé dans une procédure stockée ...

Create Table #IDSS (EmpID bigint, objID bigint) 

    Insert into EmpBasic 
     output Inserted.EmpID, EmpFull_Temp.ObjectID 
     into #IDSS 
     Select T1Name, T1Address from EmpFull_Temp 
      Where ObjectID < 106 


    Insert into EmpProject 
     Select A.EmpID, B.T1EmpProject from #IDSS as A, EmpFull_Temp as B 
      Where A.ObjID = B.ObjectID 

Mais il est dit .. L'identifiant multi-partie « EmpFull_Temp.ObjectID » ne pouvait pas être lié.

Pourriez-vous s'il vous plaît me aider à atteindre cet ...

Edit: Il n'y a aucune garantie que le tableau

Répondre

2

Avec votre EmpProject se joindre à la table, vous ne voulez probablement pas la contrainte de clé primaire sur ne la colonne EmpID

 
DECLARE @Count   int 
DECLARE @NextEmpID  int 
DECLARE @StartObjectID int 
DECLARE @EndObjectID int 

-- range of IDs to transfer (inclusive) 
SET @StartObjectID = 1 
SET @EndObjectID = 105 

BEGIN TRAN 
    -- lock tables so IDENT_CURRENT is valid 
    SELECT @Count = COUNT(*) FROM [EmpBasic] WITH (TABLOCKX, HOLDLOCK) 
    SELECT @Count = COUNT(*) FROM [EmpProject] WITH (TABLOCKX, HOLDLOCK) 

    SELECT @NextEmpID = IDENT_CURRENT('EmpBasic') 

    SET IDENTITY_INSERT [EmpBasic] ON 
    INSERT [EmpBasic] ([EmpID], [Name], [Address]) 
    SELECT @NextEmpID + ROW_NUMBER() OVER(ORDER BY ObjectID), [T1Name], [T1Address] 
    FROM [EmpFull_Temp] 
    WHERE [ObjectID] BETWEEN @StartObjectID AND @EndObjectID 
    SET IDENTITY_INSERT [EmpBasic] OFF 

    INSERT [EmpProject]([EmpID], [EmpProject]) 
    SELECT @NextEmpID + ROW_NUMBER() OVER(ORDER BY ObjectID), [T1EmpProject] 
    FROM [EmpFull_Temp] 
    WHERE [ObjectID] BETWEEN @StartObjectID AND @EndObjectID 

COMMIT TRAN 

+1

Merci .. une très bonne réponse ... Surtout pour mentionner la serrure ... –

1

[Nom] + [adresse] serait unique dans [EmpBasic] La solution ce problème dépend de si la table "parent" (celle avec la colonne IDENTITY) a une clé naturelle (ie un ou plusieurs champs qui, une fois combinés, sont garantis uniques, autre que la clé primaire de substitution).

Par exemple, dans ce cas, la combinaison des noms et des adresses va-t-elle être unique?

Si la réponse est oui alors vous pouvez simplement insérer dans EmpBasic sans prendre la peine de sortir et de stocker les ID générés. Vous pouvez ensuite insérer dans EmpProject revenir à EmpBasic en utilisant la clé naturelle (par exemple, le nom et l'adresse) pour trouver l'EmpID correct.

Insert into EmpBasic 
    Select T1Name, T1Address from EmpFull_Temp 
     Where ObjectID < 106 

Insert into EmpProject 
    Select A.EmpID, B.T1EmpProject from EmpBasic as A, EmpFull_Temp as B 
     Where A.Name = B.Name And A.Address = B.Address 

Si la réponse est non, alors il n'y a pas de solution facile que je connaisse - dans SQL Server 2005 (Je ne sais pas si cela est différent en 2008), il est impossible de valeurs de sortie qui ne sont pas inséré. J'ai contourné ce problème dans le passé en utilisant l'un des autres champs (par exemple Name) pour stocker temporairement l'ID d'origine (dans ce cas, ObjectID), l'utiliser pour joindre lors de l'insertion des enregistrements enfants comme décrit ci-dessus retour pour mettre à jour les enregistrements parents o supprimer/remplacer les valeurs temporaires. Ce n'est pas gentil mais je n'ai pas trouvé de meilleur moyen.

Insert into EmpBasic 
    Select cast(ObjectID as varchar(50)) as name, T1Address from EmpFull_Temp 
     Where ObjectID < 106 

Insert into EmpProject 
    Select A.EmpID, B.T1EmpProject from EmpBasic as A, EmpFull_Temp as B 
     Where A.Name = cast(B.ObjectID as varchar(50)) 

Update EmpBasic 
    Set Name = B.T1Name 
    from EmpBasic as A, EmpFull_Temp as B 
     Where A.Name = cast(B.ObjectID as varchar(50)) 

S'il vous plaît noter: Je ne l'ai pas testé l'échantillon SQL donnée ci-dessus, mais je l'espère vous donne une idée de la façon dont vous pourriez aborder ce sujet.

+0

Ma situation est la deuxième ... Merci pour votre temps ... –

1

Ajoutez une colonne ObjectID à la table EmpBasic pour faciliter le transfert de données, puis déposez-la lorsque vous avez terminé. Je suppose qu'il s'agit d'une opération ponctuelle, je ne recommande pas d'ajouter et de supprimer une colonne si elle est en cours

+0

Ceci est une opération en cours ... –

1

J'ai utilisé l'Explorateur de données d'échange Stack pour examiner d'autres solutions. Le seul avec promesse pour le moment est affiché here. Il s'agit effectivement de la réponse de ScotHauder, excepté l'utilisation d'une table temporaire qui a la colonne ObjectID et l'utilisation de IDENTITY_INSERT pour déplacer les valeurs EmpId générées dans EmpBasic.

Si vous devez le faire plusieurs fois, vous devez obtenir la valeur de départ EmpBasic_TempEmpId IDENTITY pour qu'elle soit Max(EmpBasic.EmpID)+1.