脱离STI-SQL,将单个表分解为新的多表结构

脱离STI-SQL,将单个表分解为新的多表结构,sql,mysql,database,database-design,foreign-keys,Sql,Mysql,Database,Database Design,Foreign Keys,我正在将使用单表继承的旧项目移动到一个更结构化的新数据库中。如何编写SQL脚本来移植此端口 旧结构 为了便于阅读,我简化了SQL CREATE TABLE customers ( id int(11), ... firstName varchar(50), surname varchar(50), address1 varchar(50), address2 varchar(50), town varchar(50), county varchar(50),

我正在将使用单表继承的旧项目移动到一个更结构化的新数据库中。如何编写SQL脚本来移植此端口

旧结构

为了便于阅读,我简化了SQL

CREATE TABLE customers (
  id int(11),
  ...
  firstName varchar(50),
  surname varchar(50),

  address1 varchar(50),
  address2 varchar(50),
  town varchar(50),
  county varchar(50),
  postcode varchar(50),
  country varchar(50),

  delAddress1 varchar(50),
  delAddress2 varchar(50),
  delTown varchar(50),
  delCounty varchar(50),
  delPostcode varchar(50),
  delCountry varchar(50),

  tel varchar(50),
  mobile varchar(50),
  workTel varchar(50),
);
新结构


表引用使用适当的跨数据库符号(如果适用):

INSERT INTO Users(id, firstname, surname, ...)
    SELECT id, firstname, surname, ...
        FROM Customers;
INSERT INTO Addresses(id, street1, street2, ...)
    SELECT id, street1, street2, ...
        FROM Customers;
INSERT INTO Phone_Numbers(id, number, type, ...)
    SELECT id, phone, type, ...
        FROM Customers;

如果同时需要新的和旧的地址del*版本,则在两组带有适当标记的源列上重复地址操作。同样,对于三个电话号码,重复电话号码操作。或者在每种情况下都使用UNION。

首先确保备份现有数据

如果要使用原始id字段或生成新的id字段,则过程不同

假设您要使用原始数据库,请确保在启动SQL Server之前能够将id字段插入表中。如果您正在自动生成该数字,并且该数字已设置为identity insert,则不确定mysql将使用什么。将插入从旧表插入到父表:

insert newparenttable (idfield, field1, field2) 
select idfield, field1, field2 from old parent table
然后根据需要的字段为所有子表编写类似的插入。例如,如果在不同的字段中有多个电话号码,则可以使用union all语句作为插入选择

Insert newphone (phonenumber, userid, phonetype)
select home_phone, id, 100 from oldparenttable
union all
select work_phone, id, 101 from oldparenttable
Union all
select cell_phone, id, 102 from oldparenttable
如果你要生成一个新的id,那么用一个字段为旧id创建一个表。你可以在最后删除它,尽管我会保留它大约六个月。然后,可以从新父表连接到旧id上的旧父表,并在插入子表时从新父表获取新id。比如:

Insert newphone (phonenumber, userid, phonetype)
select home_phone, n.id, 100 from oldparenttable o
    join newparenttable n on n.oldid = o.id
union all
select work_phone, n.id, 101 fromoldparenttable o
    join newparenttable n on n.oldid = o.id
Union all
select cell_phone, n.id, 102 from oldparenttable o
    join newparenttable n on n.oldid = o.id

比这更复杂一点-你根本没有考虑这三个表之间的关键关系。@乔-是的,我是:我在这三个表中使用相同的ID值。请注意,新表直接state ID是一个外键,它引用了新用户表。地址表中的ID列不是独立的新标识列;它被记录为用户表中值的副本。@乔:我唯一的假设是地址和电话号码表上有一个主键——可能是每种情况下ID和类型列的组合。查看OP的架构不清楚ID是地址/电话号码中返回到主键的FK还是乔:如果你这么说的话。使用的符号是id int11,ForeignKeyuser,我将其解释为id int11引用用户的松散版本,这或多或少是标准符号,另一种选择是:id int11,外键id引用用户。我还没有正式验证我的语法;这与所需内容非常接近。插入时,您可能希望添加代码以检查各个列中的实际有效值。例如,其中COALESCEtel用于电话插入等,这是一个很好的观点,尤其是当您将数据类型从旧的更改为新的时。旧表中有效的可能在新表中无效。这不是单表继承,这只是一个非规范化的表。您的工作是构造一个与该表完全相同的视图。我们是否可以编辑OP以反映事实确实如此?单表继承处理实际的继承,而OP中没有提到这些。
Insert newphone (phonenumber, userid, phonetype)
select home_phone, n.id, 100 from oldparenttable o
    join newparenttable n on n.oldid = o.id
union all
select work_phone, n.id, 101 fromoldparenttable o
    join newparenttable n on n.oldid = o.id
Union all
select cell_phone, n.id, 102 from oldparenttable o
    join newparenttable n on n.oldid = o.id