Преобразование первичного ключа CHAR в INT в MySQL / MariaDB - PullRequest
0 голосов
/ 11 февраля 2019

У меня есть таблица, которая использует 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 строк.Как преобразовать не-int строки в согласованный результат INT?

Идеальный результат будет выглядеть так: для идентификаторов клиентов, которые являются исключительно целыми числами, оставьте их в покое.Для идентификаторов клиентов, содержащих любую букву, замените все в идентификаторе уникальным числовым идентификатором.

Ожидаемый результат:

SELECT * FROM Customers;

`customer_id`
-------
99944
99946
99976
13871911
13871912
13871913
13872128
13872229
13872293
13872505
13872512
13872561

Ответы [ 3 ]

0 голосов
/ 12 февраля 2019

С 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() превращает каждый из них в его порядковый (числовой) формат.

Демонстрация на DB Fiddle :

old_id |   new_id
:----- | -------:
99944  |    99944
9Z946  |   936946
A9CZ6  | 36936366
A0C14  |  3603614
0ABC0  |  3636360
0 голосов
/ 12 февраля 2019

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    |

ps Возможно, вы генерируете большой или большой int, вам нужно использовать тип данных BIGINT.см. demo

Обновлено

Другой метод для генерирования меньших целых чисел (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        |

см. демо

0 голосов
/ 11 февраля 2019

Использование MySQL 8.0 REGEXP_REPLACE:

select cast(REGEXP_REPLACE(customer_id,'[^0-9]','') AS UNSIGNED) FROM customers;

db <> fiddle demo

...