从现有字段 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
主要思想是加入序列号从 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;
我正在尝试创建一个子 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
主要思想是加入序列号从 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;