在 mysql 中用 AES_ENCRYPT 和 AES_DECRYPT 搜索 LIKE
Search LIKE with AES_ENCRYPT and AES_DECRYPT in mysql
我使用这种技术来加密我数据库的某些字段:
How to use AES_ENCRYPT and AES_DECRYPT in mysql
效果很好,但我遇到了问题。
既然字段的内容是加密的,我就不能用经典的方式做 LIKE 了!
我尝试在解密字段上执行类似操作,但 sql 无法识别该字段!
这是结构(非常简单):
CREATE TABLE `messages` (
`id` int(11) NOT NULL,
`message` varchar(250) NOT NULL,
`crypt_key` varchar(50) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE `messages`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1;
插入:
INSERT into messages (message) VALUES (AES_ENCRYPT('Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. ', '123456'));
简单 select:
SELECT
CAST(AES_DECRYPT(message, '123456') AS CHAR(50)) decrypt
FROM messages
完美,一切顺利!
现在,假设我想在 'message' 字段中使用 LIKE 进行搜索:
SELECT
CAST(AES_DECRYPT(message, '123456') AS CHAR(50)) decrypt
FROM messages WHERE decrypt LIKE '%Lorem%'
我收到这个错误:
Unknown 'decrypt' field in where clause
这个查询同样的错误:
SELECT
CAST(AES_DECRYPT(message, '123456') AS CHAR(50)) AS decrypt
FROM messages WHERE decrypt.message LIKE '%Lorem%'
原则上,我有消息加密,解密密钥和解密算法!应该可以在解密字段中按 sql 搜索,但我找不到解决方案。
有请求栈?但这不是很优化...
我接受任何解决方案和任何意见!
WHERE 子句中不允许使用列别名。但是您可以在 HAVING 子句中使用它们:
SELECT CAST(AES_DECRYPT(message, '123456') AS CHAR(50)) decrypt
FROM messages
HAVING decrypt LIKE '%Lorem%'
您也可以只复制完整的表达式并在 WHERE 子句中使用它(就像 Bernd Buffen 在评论中建议的那样):
SELECT CAST(AES_DECRYPT(message, '123456') AS CHAR(50)) decrypt
FROM messages
HAVING CAST(AES_DECRYPT(message, '123456') AS CHAR(50)) LIKE '%Lorem%'
但我看不出这里代码重复的原因。性能应该是相同的,因为 table 扫描将以任何一种方式执行。
这不是答案。它仅适用于@Paul Spiegel。
最大的不同是首先创建一个 result-set
所有 ROW,然后使用 HAVING 子句过滤结果。
因此查询将占用更多内存来存储第一个结果。
如果您使用 WHERE 子句,它也是一个完整的 table 扫描,但 mysql 只放置
结果集中的结果行。
查看示例。我创建了一个只有 1000 行的 table,并且只有每 10 行在字符串中有一个 "LOREM"。请参阅 EXPLAIN 中的第 "filtered" 列。
mysql> select id,CAST(message AS CHAR(20)) from messages limit 10;
+----+---------------------------+
| id | CAST(message AS CHAR(20)) |
+----+---------------------------+
| 1 | Lorem ipsum dolor si |
| 2 | XXXXX ipsum dolor si |
| 3 | XXXXX ipsum dolor si |
| 4 | XXXXX ipsum dolor si |
| 5 | XXXXX ipsum dolor si |
| 6 | XXXXX ipsum dolor si |
| 7 | XXXXX ipsum dolor si |
| 8 | XXXXX ipsum dolor si |
| 9 | XXXXX ipsum dolor si |
| 10 | XXXXX ipsum dolor si |
+----+---------------------------+
10 rows in set, 10 warnings (0,00 sec)
mysql> EXPLAIN SELECT
-> message decrypt
-> FROM messages
-> HAVING decrypt LIKE '%LOREM%';
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------+
| 1 | SIMPLE | messages | NULL | ALL | NULL | NULL | NULL | NULL | 1000 | 100.00 | NULL |
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------+
1 row in set, 1 warning (0,00 sec)
mysql>
mysql> EXPLAIN SELECT
-> message decrypt
-> FROM messages
-> WHERE message LIKE '%LOREM%';
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | messages | NULL | ALL | NULL | NULL | NULL | NULL | 1000 | 11.11 | Using where |
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0,00 sec)
mysql>
我使用这种技术来加密我数据库的某些字段:
How to use AES_ENCRYPT and AES_DECRYPT in mysql
效果很好,但我遇到了问题。
既然字段的内容是加密的,我就不能用经典的方式做 LIKE 了!
我尝试在解密字段上执行类似操作,但 sql 无法识别该字段!
这是结构(非常简单):
CREATE TABLE `messages` (
`id` int(11) NOT NULL,
`message` varchar(250) NOT NULL,
`crypt_key` varchar(50) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ALTER TABLE `messages`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1;
插入:
INSERT into messages (message) VALUES (AES_ENCRYPT('Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. ', '123456'));
简单 select:
SELECT
CAST(AES_DECRYPT(message, '123456') AS CHAR(50)) decrypt
FROM messages
完美,一切顺利!
现在,假设我想在 'message' 字段中使用 LIKE 进行搜索:
SELECT
CAST(AES_DECRYPT(message, '123456') AS CHAR(50)) decrypt
FROM messages WHERE decrypt LIKE '%Lorem%'
我收到这个错误:
Unknown 'decrypt' field in where clause
这个查询同样的错误:
SELECT
CAST(AES_DECRYPT(message, '123456') AS CHAR(50)) AS decrypt
FROM messages WHERE decrypt.message LIKE '%Lorem%'
原则上,我有消息加密,解密密钥和解密算法!应该可以在解密字段中按 sql 搜索,但我找不到解决方案。
有请求栈?但这不是很优化...
我接受任何解决方案和任何意见!
WHERE 子句中不允许使用列别名。但是您可以在 HAVING 子句中使用它们:
SELECT CAST(AES_DECRYPT(message, '123456') AS CHAR(50)) decrypt
FROM messages
HAVING decrypt LIKE '%Lorem%'
您也可以只复制完整的表达式并在 WHERE 子句中使用它(就像 Bernd Buffen 在评论中建议的那样):
SELECT CAST(AES_DECRYPT(message, '123456') AS CHAR(50)) decrypt
FROM messages
HAVING CAST(AES_DECRYPT(message, '123456') AS CHAR(50)) LIKE '%Lorem%'
但我看不出这里代码重复的原因。性能应该是相同的,因为 table 扫描将以任何一种方式执行。
这不是答案。它仅适用于@Paul Spiegel。
最大的不同是首先创建一个 result-set 所有 ROW,然后使用 HAVING 子句过滤结果。 因此查询将占用更多内存来存储第一个结果。
如果您使用 WHERE 子句,它也是一个完整的 table 扫描,但 mysql 只放置 结果集中的结果行。
查看示例。我创建了一个只有 1000 行的 table,并且只有每 10 行在字符串中有一个 "LOREM"。请参阅 EXPLAIN 中的第 "filtered" 列。
mysql> select id,CAST(message AS CHAR(20)) from messages limit 10;
+----+---------------------------+
| id | CAST(message AS CHAR(20)) |
+----+---------------------------+
| 1 | Lorem ipsum dolor si |
| 2 | XXXXX ipsum dolor si |
| 3 | XXXXX ipsum dolor si |
| 4 | XXXXX ipsum dolor si |
| 5 | XXXXX ipsum dolor si |
| 6 | XXXXX ipsum dolor si |
| 7 | XXXXX ipsum dolor si |
| 8 | XXXXX ipsum dolor si |
| 9 | XXXXX ipsum dolor si |
| 10 | XXXXX ipsum dolor si |
+----+---------------------------+
10 rows in set, 10 warnings (0,00 sec)
mysql> EXPLAIN SELECT
-> message decrypt
-> FROM messages
-> HAVING decrypt LIKE '%LOREM%';
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------+
| 1 | SIMPLE | messages | NULL | ALL | NULL | NULL | NULL | NULL | 1000 | 100.00 | NULL |
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------+
1 row in set, 1 warning (0,00 sec)
mysql>
mysql> EXPLAIN SELECT
-> message decrypt
-> FROM messages
-> WHERE message LIKE '%LOREM%';
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | messages | NULL | ALL | NULL | NULL | NULL | NULL | 1000 | 11.11 | Using where |
+----+-------------+----------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0,00 sec)
mysql>