【问题标题】:sql : duplicate row and all related rowssql:重复行和所有相关行
【发布时间】:2014-09-15 22:40:26
【问题描述】:

我有以下 3 个相关的表

Schools           Departments          Classes
---------------   ------------------   -----------------
ID                ID                   ID
School_Name       ID_Schools           ID_Departments
                  Department_Name      Class_Name

以及关于它们包含的内容的一些示例(我会尽可能地画出最好的)

---- Schools ---
ID   School_Name
----------------
 1   School_1  <----------------------\
 2   School_2                         |
 n   ........                         |
                                      |
---- Departments ----------------     |
ID   ID_Schools   Department_Name     |
---------------------------------     |
 1            1   Dept_1  <-----------/ -->--\
 2            1   Dept_2  <-----------/ -->--|------\
 3            2   Dept_1                     |      |
 n           ..   ......                     |      |
                                             |      |
---- Classes -------------------             |      |
ID   ID_Departments   Class_Name             |      |
--------------------------------             |      |
 1                1   Class_1  <-------------/      |
 2                1   Class_2  <-------------/      |
 3                1   Class_3  <-------------/      |
 4                2   Class_1  <--------------------/
 n               ..   .......

所有 ID 都是自动递增的

我正在寻找一种复制“School_1”层次结构的方法。问题是我如何维护新行之间的关系?

例如,要复制“School_1”层次结构,我将在 Schools 表中插入一个新的原始数据,最终将生成一个新 ID(例如 5)。

---- Schools ---
ID   School_Name
----------------
 5   School_1

属于“School_1”的部门“Dept_1”和“Dept_2”将获得新 ID

---- Departments ----------------
ID   ID_Schools   Department_Name
---------------------------------
16            5   Dept_1
17            5   Dept_2

类也将获得新的 ID

---- Classes -------------------
ID   ID_Departments   Class_Name
--------------------------------
56               16   Class_1
57               16   Class_2
58               16   Class_3
59               17   Class_1

我怎样才能以一种简单而聪明的方式实现这一点?

【问题讨论】:

  • 现在无法回答这个问题,但投票赞成问题的完美形式。我希望所有 SO 问题都像这个问题一样清晰易懂!

标签: sql sql-server sql-server-2012


【解决方案1】:

复制学校和部门很容易。要复制课程,我们需要一个函数,它可以根据新旧 school.id 值将旧部门 ID 转换为新部门 ID。

如果 Dept_id 和 Dept_name 的组合是唯一的,则可以采用以下方法:

DECLARE @old_id int; // set it 

DECLARE @school_id int;
DECLARE @school_name varchar(100); 

SET @school_name = (SELECT school_name from schools where id = @old_id);

INSERT into schools (school_name)
  OUTPUT Inserted.id into @school_id
  VALUES (@school_name);

INSERT into departments (id_schools, department_name)
  SELECT @school_id, department_name 
    FROM departments 
      WHERE id_schools = @old_id;

INSERT into classes (ID_Departments, Class_Name)
  SELECT
    (SELECT s.ID_Departments from departments s
       WHERE s.id_schools = @school_id and s.department_name = d.department_name),
    c.class_name
  FROM classes c, departments d
    WHERE c.ID_Departments = d.ID and d.ID_Schools = @old_id;

如果 (id_schools, department_name) 对不是唯一的,您可以将 department_id 值临时存储在 department_name 字段中并稍后更新(在创建课程之后)。

【讨论】:

    【解决方案2】:

    为此,我尝试编写一个简单的存储过程。我没有时间测试它的逻辑,但我认为它可以给出我对这个问题的思考方式。测试一下...

    CREATE PROCEDURE [dbo].[copySchoolHierarchy] (@SchoolId As Int) 
    As Begin
    
    BEGIN TRANSACTION
    
    BEGIN TRY
    
        DECLARE @tmpSchoolName NVARCHAR(100),
                @tmpNewSchoolID INT
    
        --First insert into schools
        SELECT @tmpSchoolName = School_Name FROM Schools WHERE ID = @SchoolId 
        INSERT INTO SCHOOLS (School_Name) VALUES (@tmpSchoolName)
        SELECT @tmpNewSchoolID = SCOPE_IDENTITY()
    
        --Then get the departments
        INSERT INTO Departments (ID_Schools, Department_Name)
        SELECT @tmpNewSchoolID AS someId, Department_Name FROM DEPARTMENTS Where ID_Schools = @SchoolId
    
        --and the classes
        INSERT INTO Classes (ID_Departments, Class_Name)
        SELECT C.ID_Departments, C.Class_Name FROM Classes C 
        INNER JOIN DEPARTMENTS D ON C.ID_Departments = D.ID
        WHERE D.ID_Schools = @tmpNewSchoolID 
    
        COMMIT TRANSACTION
    END TRY
    BEGIN CATCH
        --Raise some exception here...
    
        ROLLBACK TRANSACTION
    END CATCH
    END
    

    【讨论】:

      【解决方案3】:

      我建议使用 SQL INSERT AS SELECT 魔法,如下所述:Insert into ... values ( SELECT ... FROM ... )

      让您的旧 School ID 为 7,新 School ID 为 17,然后您可以为每个表创建一个查询为 INSERT INTO Departments(id, id_schools, name) VALUES (NULL, 17, (SELECT name FROM Departments WHERE id_schools = 17))

      当您需要按部门(包含多个部门)插入班级时会有点棘手,但您可以手动填写 WHERE id_departments IN (5,6,13, etc) 或自动填写为 WHERE id_departments IN (SELECT id FROM Departments WHERE School_ID = 17)

      P.S.:这更像是建议而不是答案,因此 SQL 方言或代码质量等一些细节可能不合适,但我确信方法本身。

      【讨论】:

        猜你喜欢
        • 2017-04-26
        • 1970-01-01
        • 2014-12-19
        • 1970-01-01
        • 2017-03-02
        • 2015-09-02
        • 1970-01-01
        • 2011-12-11
        • 1970-01-01
        相关资源
        最近更新 更多