我正在将旧数据库数据迁移到新数据库,他们过去常常按以下格式存储电话号码:
示例1:
41.9044-9082;41.9044-9661;41.9851-9862;41.9984-0393;41.3399-9169;41.3997-7999;
示例2:
41.3369-0102;41.8928-5992;
没有电话(空):
;
如何将这些单个VARCHAR字段拆分为多个值,并单独插入?
表格示例:
|#id_tel#|### number ####|#|client_id|#|
|# 1 #|111163;3554353;|#| 2 |#|
|# 2 #|222222; |#| 3 |#|
|# 3 #|; |#| 4 |#|
表示我希望如何:
|#id_tel#|### number ####|#|client_id|#|
|# 1 #|111163 |#| 2 |#|
|# 2 #|3554353 |#| 2 |#|
|# 3 #|222222 |#| 3 |#|
答案 0 :(得分:1)
您可以使用SUBSTRING_INDEX()和数字表的嵌套调用来实现。在我的例子中,我动态创建了数字表,最多可以有100个数字。
假设表old_tel具有以下CREATE TABLE语句:
CREATE TABLE old_tel (
id_tel INT,
`number` VARCHAR(200),
client_id INT
);
使用此查询获取带有client_id的拆分数字:
SELECT
SUBSTRING_INDEX(SUBSTRING_INDEX(`number`, ';', n.n), ';', -1) value,
client_id
FROM
old_tel
CROSS JOIN (
SELECT
1 + a.N + b.N * 10 AS n
FROM
(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
ORDER BY n
) n
WHERE
n.n <= LENGTH(`number`) - LENGTH(REPLACE(`number`, ';', ''))
AND
SUBSTRING_INDEX(SUBSTRING_INDEX(`number`, ';', n.n), ';', -1) <> ''
ORDER BY
client_id, SUBSTRING_INDEX(SUBSTRING_INDEX(`number`, ';', n.n), ';', -1);
假设您的新电话号码表看起来几乎相同:
CREATE TABLE new_tel (
id_tel INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`number` VARCHAR(200),
client_id INT
);
您可以使用第一个查询使用这个简单的INSERT
语句填充此表:
INSERT INTO new_tel (`number`, client_id)
SELECT
SUBSTRING_INDEX(SUBSTRING_INDEX(`number`, ';', n.n), ';', -1) value,
client_id
FROM
old_tel
CROSS JOIN (
SELECT
1 + a.N + b.N * 10 AS n
FROM
(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a
,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b
ORDER BY n
) n
WHERE
n.n <= LENGTH(`number`) - LENGTH(REPLACE(`number`, ';', ''))
AND
SUBSTRING_INDEX(SUBSTRING_INDEX(`number`, ';', n.n), ';', -1) <> ''
ORDER BY
client_id, SUBSTRING_INDEX(SUBSTRING_INDEX(`number`, ';', n.n), ';', -1);
带有UNION ALL的内部子选择动态创建数字表。我们将此限制在number
列中的子字符串数量,并过滤掉空值。
SUBSTRING_INDEX(SUBSTRING_INDEX(`number`, ';', n.n), ';', -1) value
删除以分号分隔的第n个数字。
看到它在 Demo
中工作**注意:**通过避免逐行插入令人痛苦,这是非常快的。