MySQL: CONCAT/SUBSTRING: 这不起作用是因为我使用的是 int 变量吗?

MySQL: CONCAT/SUBSTRING: Does this not work because I am using an int variable?

我正在尝试编写一个信用卡号,每组四个,最多十六位。我正在使用 CONCAT 和 SUBSTRING 来执行此操作。

注意:我没有收到错误,它 运行 但输出不是我想要的。

我想要的是:xxxx-xxxx-xxxx-xxxx 我得到的是:2147-4836-47-(不仅在一个地方,而且在所有四个条目中)

发生这种情况是因为我试图在下标语句中分解一个 int 变量吗?你能在 substring() 中使用 int 字符吗? BIGINT 呢?

不管我为什么将其更改为 varchar,并 运行 使用 CONCAT 和 SUBSCRIPT。一切似乎都很好,但欢迎进一步的输入。 :)

已创建 Table:

CREATE TABLE credit_cards
(
credit_card_ID          int(10)             UNIQUE,
credit_card_num         int(20)         NOT NULL,
exp_date                DATE                NOT NULL,
card_fname              varchar(35)         NOT NULL,
card_lname              varchar(35)         NOT NULL,
security_code           int(5)              NOT NULL,
bill_street             varchar(50)         NOT NULL,
bill_city               varchar(25)         NOT NULL,
bill_state              varchar(2),
bill_zip                int(10)             NOT NULL,
PRIMARY KEY (credit_card_ID)
);

插入数据:

INSERT INTO credit_cards VALUES 
(1, 0025184796520000, '2016-08-13', 'Sarah', 'Jones', 3351, '2490 Paseo Verde parkway, suite 150', 'San Diego','CA',92124),
(2, 7896541232548526, '2017-09-21', 'Desmond', 'Lowell', 1204, '3201 Kelsey Street, suite 109', 'San Diego','CA',92174),
(3, 1234567890123456, '2018-02-11', 'Mark', 'Jefferson', 1591, '876 Silverado Street, suite 304', 'Henderson','NV',89162),
(4, 4001330852539605, '2017-01-10', 'Jaime', 'Evans', 8879, '924 Shady Pines Circle, suite 120', 'Summerlin','NV',89074);

Select数据

SELECT credit_card_ID as 'Card ID', 
        CONCAT(
        SUBSTRING(credit_card_num, 1,4), '-',
        SUBSTRING(credit_card_num, 5,4), '-',
        SUBSTRING(credit_card_num, 9,4), '-',
        SUBSTRING(credit_card_num, 13,4)) as 'Card Number',
        security_code as 'Security Code',
        DATE_FORMAT(exp_date, '%m-%d-%Y') as 'Expiration Date', 
        CONCAT(card_fname, ' ', card_lname) as 'Customer Name',
        CONCAT(bill_street, ', ', bill_city, ', ', bill_state, ' ', bill_zip) as 'Billing Address'
FROM credit_cards
ORDER BY exp_date ASC;

有两个问题:

1) INT不能取16位,得用BIGINT.

Integer types documentation for MySQL 5.7

CREATE TABLE `credit_cards` (
    `credit_card_ID` INT(10) NOT NULL,
    `credit_card_num` BIGINT(16) NOT NULL,       -- use BIGINT here
    `exp_date` DATE NOT NULL,
    `card_fname` VARCHAR(35) NOT NULL,
    `card_lname` VARCHAR(35) NOT NULL,
    `security_code` INT(5) NOT NULL,
    `bill_street` VARCHAR(50) NOT NULL,
    `bill_city` VARCHAR(25) NOT NULL,
    `bill_state` VARCHAR(2) NULL DEFAULT NULL,
    `bill_zip` INT(10) NOT NULL,
    PRIMARY KEY (`credit_card_ID`),
    UNIQUE INDEX `credit_card_ID` (`credit_card_ID`)
);

2) 前导零通常被截断。你必须使用 LPAD。

LPAD documentation for MySQL 5.7

LPAD(credit_card_num, 16, 0)

读取:左填充 credit_card_num,长度为 0 至 16 位。查询可能如下所示:

SELECT credit_card_ID as 'Card ID', 
        CONCAT(
        SUBSTRING(LPAD(credit_card_num, 16, 0), 1,4), '-',
        SUBSTRING(LPAD(credit_card_num, 16, 0), 5,4), '-',
        SUBSTRING(LPAD(credit_card_num, 16, 0), 9,4), '-',
        SUBSTRING(LPAD(credit_card_num, 16, 0), 13,4)) as 'Card Number',
        security_code as 'Security Code',
        DATE_FORMAT(exp_date, '%m-%d-%Y') as 'Expiration Date', 
        CONCAT(card_fname, ' ', card_lname) as 'Customer Name',
        CONCAT(bill_street, ', ', bill_city, ', ', bill_state, ' ', bill_zip) as 'Billing Address'
FROM credit_cards
ORDER BY exp_date ASC;

See it live.

无论它值多少钱,我都不会使用整数来存储信用卡号。我会使用 CHAR(16)--而不是 VARCHAR,因为字符串的大小永远不会改变。我会解释为什么。

没有理由使用任何类型的整数变量,除非您要在某种形式的计算中使用这些数字。将它们存储为字符串(即 CHAR、VARCHAR、NCHAR 或 NVARCHAR)会更容易,因为您会从一些环节中发现您必须跳过才能获得所需内容。即使您要进行某种形式的校验位验证,与从整数中获取数字值的子集相比,从字符串中剥离数字并将结果转换为整数会更容易。

事实上,当您将 SUBSTRING 应用于整数时,解析器会在应用之前隐式地将整数转换为字符串,因此在这种情况下使用某种形式的整数类型会产生额外的开销。您最好问问自己是否需要额外的开销,如果需要,为什么。如果不需要,您应该考虑将简化作为一般原则。

请务必记住,数字通常最好可视化为字母数字字符集的一个子集,您可能会问自己为什么需要将信用卡号视为具有数学功能的数字(即整数)而不是而不是纯字符数据。这里很容易出错,因为它有点违反直觉:一个标准的初学者错误是将邮政编码存储为整数,然后想知道如何计算东海岸数字中的前导零。任何尝试过将邮政编码放入 Excel 电子表格的人都遇到过这个。