sql:重复行和所有相关行

问题描述 投票:0回答:3

我有以下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

如何以简单而智能的方式实现这一目标?

sql sql-server sql-server-2012
3个回答
0
投票

我建议使用 SQL

INSERT AS SELECT
魔法,如下所述:插入...值(SELECT ... FROM ...)

假设您的旧学校 ID 为 7,新学校 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 方言或代码质量等一些细节可能不合适,但我对方法本身很确定。


0
投票

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

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

0
投票

复制学校和部门很容易。要复制班级,我们需要一个函数,根据新旧 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字段中并稍后更新(在创建课程之后)。

© www.soinside.com 2019 - 2024. All rights reserved.