在MySQL / MariaDB中将CHAR主键转换为INT

时间:2019-02-11 20:09:05

标签: mysql sql char type-conversion mariadb

我有一个使用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');

Fiddle

我曾尝试对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

3 个答案:

答案 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()将每个数字字符转换为其有序(数字)表示。

Demo on DB Fiddle

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;

db<>fiddle demo