我有一个使用CHAR
作为客户主键的表。我正在尝试将此表加载到架构中,以便主键应为INT
。
DROP TABLE IF EXISTS `customers`;
CREATE TABLE `customers` (
`customer_id` char(5) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `customers` VALUES ('99944'),('99946'),('99976'),('A0014'),('A0049'),('A0124'),('C01AH'),('C01AQ'),('C01AW'),('C01AX'),('C01AY'),('C01AZ');
我曾尝试对select cast(customer_id AS UNSIGNED) FROM customers;
进行变体,但对于非整数行,只能返回0。如何将非整数行转换为一致的INT
结果?
理想的结果如下所示: 对于仅是整数的客户ID,请不要理会它们。 对于包含任何字母的客户ID,请用唯一的数字标识符替换ID中的所有内容。
预期结果:
SELECT * FROM Customers;
`customer_id`
-------
99944
99946
99976
13871911
13871912
13871913
13872128
13872229
13872293
13872505
13872512
13872561
答案 0 :(得分:2)
对于Maria DB> = 10.0.5,这是一种以可预测的方式将字符串主键转换为整数主键的解决方案:
SELECT
customer_id old_id,
CAST(
REGEXP_REPLACE(customer_id, '([^0-9])', ORD('$1'))
AS UNSIGNED
) new_id
FROM customers;
REGEXP_REPLACE()
捕获非数字字符(在字符串中的任意位置),ORD()
将每个数字字符转换为其有序(数字)表示。
old_id | new_id :----- | -------: 99944 | 99944 9Z946 | 936946 A9CZ6 | 36936366 A0C14 | 3603614 0ABC0 | 3636360
答案 1 :(得分:2)
GMB确实给了我另一个想法。
使用HEX()
和CONV(.., 16, 10)
将十六进制转换为十进制
查询
SELECT
customers.customer_id
, CASE
WHEN (customers.customer_id >> 0) > 0
THEN customers.customer_id >> 0
ELSE
CONV(HEX(customers.customer_id), 16, 10)
END
AS customer_id_int
FROM
customers;
结果
| customer_id | customer_id_int |
| ----------- | --------------- |
| 99944 | 99944 |
| 99946 | 99946 |
| 99976 | 99976 |
| A0014 | 279981338932 |
| A0049 | 279981339705 |
| A0124 | 279981404724 |
| C01AH | 288571343176 |
| C01AQ | 288571343185 |
| C01AW | 288571343191 |
| C01AX | 288571343192 |
| C01AY | 288571343193 |
| C01AZ | 288571343194 |
p.s
您可能需要使用BIGINT
数据类型来生成一个很大的整数。
参见demo
已更新
另一种生成较小的int(UNSIGNED INT
)的方法,该方法使用“ SQL数字生成器”,SUBSTRING()
,ORD()
和GROUP_CONCAT()
。
查询
SELECT
customers.customer_id
CASE
WHEN customers.customer_id >> 1 > 0
THEN customers.customer_id
ELSE
GROUP_CONCAT(
CASE
WHEN SUBSTRING(customers.customer_id, number_generator.number, 1) NOT BETWEEN 'A' AND 'Z'
THEN SUBSTRING(customers.customer_id, number_generator.number, 1) >> 1
ELSE ORD(SUBSTRING(customers.customer_id, number_generator.number, 1))
END
ORDER BY
number_generator.number ASC
SEPARATOR ''
)
END
) AS customer_id_int
FROM (
SELECT
record_1.number
FROM (
SELECT 1 AS number UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5
) AS record_1
) AS number_generator
CROSS JOIN
customers
GROUP BY
customers.customer_id
ORDER BY
customers.customer_id ASC
结果
| customer_id | customer_id_int |
| ----------- | --------------- |
| 99944 | 99944 |
| 99946 | 99946 |
| 99976 | 99976 |
| A0014 | 650002 |
| A0049 | 650024 |
| A0124 | 650012 |
| C01AH | 67006572 |
| C01AQ | 67006581 |
| C01AW | 67006587 |
| C01AX | 67006588 |
| C01AY | 67006589 |
| C01AZ | 67006590 |
请参阅demo
答案 2 :(得分:1)
使用MySQL 8.0 REGEXP_REPLACE
:
select cast(REGEXP_REPLACE(customer_id,'[^0-9]','') AS UNSIGNED) FROM customers;