sql:重复行和所有相关行

时间:2014-07-24 11:38:52

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

我有以下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表中插入一个新的raw,最终会生成一个新的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

我怎样才能以简单明智的方式实现这一目标?

4 个答案:

答案 0 :(得分:0)

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

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

当您需要插入Classes - by - Departments(具有多个部门)时,它会变得有点棘手,但您可以手动填写WHERE id_departments IN (5,6,13, etc)或将其自动化为WHERE id_departments IN (SELECT id FROM Departments WHERE School_ID = 17)

P.S。:这更像是建议然后答案,所以像SQL方言或代码质量这样的细节可能不合适,但我确信这种方法本身。

答案 1 :(得分: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

答案 2 :(得分: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字段临时中并稍后更新(在创建类之后)。

答案 3 :(得分:0)

我终于找到一篇文章,详细解释了一些不同的技术,用于复制具有依赖关系here的数据。