【发布时间】:2019-12-21 20:25:56
【问题描述】:
假设我有一个使用字符串作为主键的表。例如,一个会话表(我会将其保留为 4 个字符,以便让我的示例更清晰)。
我还将添加一个 Auto Increment 列,以使我的示例更接近现实(以防它产生影响)。
CREATE TABLE sessions (
`id` INT AUTO INCREMENT,
`key` CHAR(4) NOT NULL,
PRIMARY KEY(`key`),
UNIQUE KEY `idx_key` ( `key` )
);
我可以在表格中插入数据。
INSERT INTO sessions (`key`) VALUES ('abcd');
因为这是来自浏览器的会话 ID,所以我不信任它并在处理请求的代码中使用正确的绑定值。恶意用户可以在这里发送各种字符串,但它们总是以字符串的形式结束,而不是注入攻击。没关系。 MySQL 会很高兴地截断这些数据并发出警告。
INSERT INTO sessions(`key`) VALUES ('abcdefg');
Warning (Code 1265): Data truncated for column 'key' at row 1
但是,这只是用于创建行的“好”(不是很好,但无论如何)。相同的操作首先查找一行,然后再尝试插入。你知道的 - upsert。 MySQL 不会费心截断 this 数据,并确定它不在表中。
SELECT * FROM sessions WHERE `key` = 'abcdefg';
Empty set (0.00 sec)
这意味着我之前的插入更加糟糕,因为当我插入数据时,MySQL 会将其截断为一个确实存在的值。
INSERT INTO sessions (`key`) VALUES ('abcdefg');
Warning (Code 1265): Data truncated for column 'key' at row 1
Error (Code 1062): Duplicate entry 'abcd' for key 'idx_key'
网站代码不知道此列的约束,我无意提供此信息。
如何让 MySQL 只比较字符串的前 N 个字符,其中 N 是文本字段的(最大)长度?
【问题讨论】:
-
根据您的实际问题,我将您的关键示例更新为字母而不是数字。
-
AUTO_INCREMENT列必须是主键。 -
@Barmar -
AUTO_INCREMENT的唯一索引要求是它是 some 索引中的第一列。它不一定是 PK。