我有以下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
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 方言或代码质量等一些细节可能不合适,但我对方法本身很确定。
我尝试为此目的编写一个简单的存储过程。我没有时间测试它的逻辑,但我认为它可以给出我对这个问题的思考方式。测试一下...
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
复制学校和部门很容易。要复制班级,我们需要一个函数,根据新旧 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字段中并稍后更新(在创建课程之后)。