从现有字段 MySQL 创建子项 table

Create a child table from an existing field MySQL

我正在尝试创建一个子 table,它派生自现有 table 的字段中的一组字符串。现有字段包含一组我需要解析的字符串。请参阅下面的数据示例:

+------------------------------------------------------------+
|                           Column                           |
+------------------------------------------------------------+
| ['ffffffff-11111-1111-baaa-xxxx']'                         |
| ['zxyvvv-1234567-abcdefghijk', '1234567-abcdefg-hijklmn']' |
+------------------------------------------------------------+

目标是从现有字段中获取字符串集并创建新的 table 这些字符串可以使用某种类型的外键连接回父 table。

Parent table
+--------+
| Col_id |
+--------+
|      1 |
|      2 |
+--------+

Child Table

+-----------+-------------------------------+
| Col_id    |            Column             |
+-----------+-------------------------------+
|         1 | ffffffff-11111-1111-baaa-xxxx |
|         2 | zxyvvv-1234567-abcdefghijk    |
|         2 | 1234567-abcdefg-hijklmn       |
+-----------+-------------------------------+

我不确定处理这种情况时的正确方法或 "best practices"。我还假设我需要在引用父 table 的子 table 中创建一个外键来执行连接。如果 Stack Overflow 中还有另一个 post 与此主题相关,请提供并将其标记为重复。

MySQL 8 解决方案 JSON 和 CTE

假设这是你现在的table:

create table old_table(
  data text
);
insert into old_table(data)values
  ("['ffffffff-11111-1111-baaa-xxxx']"),
  ("['zxyvvv-1234567-abcdefghijk', '1234567-abcdefg-hijklmn']");

而你想"transfer"将数据放入两个新的tables:

create table parent_table(
  parent_id int primary key
);

create table child_table(
  child_id int auto_increment primary key,
  parent_id int not null,
  data varchar(100),
  foreign key (parent_id) references parent_table(parent_id)
);

首先使用 AUTO_INCREMENT id 列创建旧 table 的(临时)副本:

create table tmp_table(
  id int auto_increment primary key,
  data json
);

从旧 table 复制数据时将数据转换为 JSON:

insert into tmp_table(data)
  select replace(data, "'", '"') from old_table;

tmp_table 中的 ID 填充 parent_table:

insert into parent_table(parent_id)
  select id from tmp_table;

现在(主要部分)用以下查询填充 child_table

insert into child_table(parent_id, data)
  with recursive seq(i) as ( -- sequence numbers 0 to 999
    select 0
    union all
    select i + 1
    from seq
    where i < 999
  )
  select t.id as parent_id
       , json_unquote(json_extract(t.data, concat('$[', s.i, ']'))) as data
  from tmp_table t
  join seq s on s.i <= json_length(t.data)-1;

child_table 现在包含以下数据:

child_id    parent_id   data
1           1           ffffffff-11111-1111-baaa-xxxx
2           2           zxyvvv-1234567-abcdefghijk
3           2           1234567-abcdefg-hijklmn

db-fiddle demo

主要思想是加入序列号从 0 到 999(使用递归 CTE 生成)的 tmp_table,并使用这些数字从 JSON 数组中提取相应的元素。

您可以通过执行以下操作来提取列:

select substring_index(column, ',', 1) as data
from t
union all
select substring_index(substring_index(column, ',', 2), -1) as data
from t
where column like '%,%'
union all
select substring_index(substring_index(column, ',', 3), -1) as data
from t
where column like '%,%,%'
union all
select substring_index(substring_index(column, ',', 4), -1) as data
from t
where column like '%,%,%,%';

获取 child id 比较麻烦。您可以使用原始列和一些变量来执行此操作:

select c.col_id, t.data
from (select column, substring_index(column, ',', 1) as data
      from t
      union all
      select column, substring_index(substring_index(column, ',', 2), -1) as data
      from t
      where column like '%,%'
      union all
      select column, substring_index(substring_index(column, ',', 3), -1) as data
      from t
      where column like '%,%,%'
      union all
      select column, substring_index(substring_index(column, ',', 4), -1) as data
      from t
      where column like '%,%,%,%'
     ) t join
     (select column, (@rn := @rn + 1) as col_id
      from t cross join
           (select @rn := 0) params
     ) c
     on t.column = c.column;