Разделить таблицу и вставить с идентификационной ссылкой - PullRequest
1 голос
/ 16 июня 2010

У меня есть 3 таблицы, похожие на структуру ниже

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

Таблица EmpFull_Temp содержит записи со столбцом идентификатора фиктивного объекта ... Я хочу заполнить первые 2 таблицы записями в этой таблице ... Но с помощью EmpID в качестве ссылки между первыми 2 таблицами.

Я пробовал это в хранимой процедуре ...

    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

Но он говорит ... Не удалось связать идентификатор из нескольких частей "EmpFull_Temp.ObjectID".

Не могли бы вы помочь мне в достижении этого ...

Редактировать: Нет никакой гарантии, что [Имя] + [Адрес] будет уникальным для таблицы [EmpBasic]

Ответы [ 4 ]

2 голосов
/ 17 июня 2010

С вашей таблицей соединений EmpProject вы, вероятно, не хотите, чтобы ограничение первичного ключа было только на столбец 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 голос
/ 17 июня 2010

Добавьте столбец ObjectID в таблицу EmpBasic, чтобы упростить передачу данных, а затем удалите его, когда закончите.Я предполагаю, что это однократная операция, я не рекомендую добавлять и удалять столбец, если это происходит

1 голос
/ 17 июня 2010

Я использовал Stack Exchange Data Explorer для поиска альтернативных решений. Единственный с обещанием на данный момент показан здесь . Это фактически ответ @ ScotHauder, за исключением использования временной таблицы со столбцом ObjectID и использования IDENTITY_INSERT для перемещения сгенерированных значений EmpId в EmpBasic.

Если вам нужно сделать это несколько раз, вам нужно получить начальное значение EmpBasic_Temp EmpId IDENTITY, равное Max(EmpBasic.EmpID)+1.

1 голос
/ 16 июня 2010

Решение этой проблемы зависит от того, имеет ли «родительская» таблица (т. Е. Таблица с столбцом IDENTITY) естественный ключ (т. Е. Одно или несколько полей, которые при объединении гарантированно являются уникальными, другиечем суррогатный первичный ключ ).

Например, в этом случае сочетание имен и адресов всегда будет уникальным?

Если ответ да, тогда вы можетепросто вставьте в EmpBasic, не потрудившись вывести и сохранить сгенерированные идентификаторы.Затем вы можете вставить в EmpProject присоединение к EmpBasic, используя естественный ключ (например, имя и адрес), чтобы найти правильный EmpID.

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

Если ответ «нет», то нет простого решения, о котором я знаю- в SQL Server 2005 (я не знаю, отличается ли он в 2008 году), невозможно вывести значения OUTPUT, которые не были вставлены.Я обошел эту проблему в прошлом, используя одно из других полей (например, Имя), чтобы временно сохранить исходный идентификатор (в данном случае, ObjectID), использовать его для присоединения при вставке дочерних записей, как описано выше, а затем ушелвернуться к обновлению родительских записей o удалить / заменить временные значения.Это нехорошо, но я не нашел лучшего способа.

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

Обратите внимание: я не тестировал приведенный выше пример SQL, но я надеюсь, что он даст вам представление о том, как вы можете подойти к этому.

...