将行插入同一个表并存储旧/新标识列

时间:2014-02-25 20:38:55

标签: sql sql-server-2008 tsql

我正在尝试将表A中的行插回到表A中,同时保留旧的和新的标识列。

这是我的基本示例:

t_course_media 
  course_media_id (PK, int, not null) -- identity column
  course_id (int, not null)
  media_id (int, null),
  ...

t_media 
  media_id (PK, int, not null), -- this is the identity column
  ...

我被要求将课程媒体从3门课程复制到单一的现有课程中。诀窍是现有的课程需要新的media_id,以便每个课程都有唯一的t_media子行。如何从插入中维护新的media_id,以便插入与刚刚插入t_media的新t_media行相关的正确t_course_media行?

到目前为止,我的研究使我得到了MERGE和OUTPUT声明。我发现的样本的问题是合并声明了一个新表。我可以让样本正常工作,但新的media_id值从1开始(而不是来自t_media表的xxxxx)。这是我找到的例子 - http://sqlblog.com/blogs/jamie_thomson/archive/2010/01/06/merge-and-output-the-swiss-army-knife-of-t-sql.aspx

DECLARE @source TABLE (
  [id] INT PRIMARY KEY,
  [name] VARCHAR(10)
);

INSERT @source VALUES(1000,'Harold'),(2000,'Madge');

DECLARE @destination TABLE (
  [id] INT PRIMARY KEY IDENTITY(1,1),
  NAME VARCHAR(10)
);

MERGE  @destination
USING  (SELECT [id], [name] FROM @source) AS [source]
ON     (1=0) --arbitrary join condition
WHEN   NOT MATCHED THEN
   INSERT (name)
   VALUES  (source.Name)
   OUTPUT  INSERTED.id AS NEWID,[source].[id] AS OldId,INSERTED.name; 

NewID    OldID    name
1        1000     Harold
2        2000     Madge

那么当源表和目标表相同时,如何存储旧的和新的t_media media_id?有数百行,最后我想创建一个简化流程的过程。

2 个答案:

答案 0 :(得分:1)

假设表 设置为自动缩进:

,此解决方案可以正常工作
-- This solution assumes that all tables have
-- auto-identity on, as per your recent comment
BEGIN TRANSACTION insertNewCourse

    -- For capturing newly inserted course ID
    declare @newCourseID int 

    -- Insert new course
    INSERT INTO [dbo].[t_course]
               ([CourseInfo])  -- Example of other field
         VALUES
               ('extra field data')

    -- Capture new ID of course
    select  @newCourseID =  @@IDENTITY

    -- INSERT new data based on selection of 3 courses by their Course ID.
    INSERT INTO t_course_media
    SELECT  @newCourseID, media_id, SomeData
    FROM t_course_media
    WHERE course_id IN (2, 3, 4) -- IDs of existing 3 courses to copy


COMMIT transaction insertNewCourse

答案 1 :(得分:0)

假设表未设置为auto-ident:

,此解决方案可以正常工作
-- This solution assumes that none of these tables have 
-- auto-identity on, as per your example
BEGIN TRANSACTION insertNewCourse

    -- Capture max course ID
    declare @newCourseID int 
    select  @newCourseID = (max(course_id) + 1) from t_course

    -- Insert new course
    INSERT INTO [dbo].[t_course]
               ([course_id]
               ,[CourseInfo])  -- Example of other field
         VALUES
               (@newCourseID
               ,'extra field data')

    -- Capture max course_media_id
    declare @maxCourseMediaID int 
    select  @maxCourseMediaID = max(course_media_id) from t_course_media;

    -- Use CTE to get existing data on 3 courses
    WITH MatchingCourses_CTE (RowNum, course_id, media_id, SomeData)
    AS
    -- Common Table Expression (CTE) query.
    (
        select ROW_NUMBER()
        OVER (ORDER BY t_course_media.course_id) , course_id ,  media_id,    SomeData -- example additional data field
        from t_course_media     
    )
    -- INSERT new data based on that selected from CTE
    INSERT INTO t_course_media
    SELECT  RowNum + @maxCourseMediaID, -- Ensure that non-auto-ident PK doesn't conflict
            @newCourseID, media_id, SomeData
    FROM MatchingCourses_CTE
    WHERE course_id IN (2, 3, 4) -- IDs of existing 3 courses to copy

COMMIT transaction insertNewCourse