sqlite的模式匹配不起作用的原因可能是什么?

时间:2019-12-12 16:36:08

标签: sqlite sql-like

我有一个包含日志数据的数据库文件。数据库包含表LOG,表包含列MSG。该表中有30行,其中MSG列在行尾包含字符串“ down”:

$ sqlite3 log.db "select msg from log" | grep down$ | wc -l
30

但是当我尝试用LIKE查找它们时,我找不到匹配项:

$ sqlite3 log.db "select msg from log where msg like '%down'" | grep down$ | wc -l
0

这可能是什么原因?

更新:MCVE

CREATE TABLE LOG (MSG VARCHAR(6291456) NOT NULL);

INSERT INTO LOG VALUES (X'666163696c6974793d6461656d6f6e3b636f6d706f6e656e743d6e616d65643b746578743d7368757474696e6720646f776e');

SELECT MSG FROM LOG;                                         -- returns the row
SELECT MSG FROM LOG WHERE MSG LIKE '%down';                  -- returns nothing
SELECT MSG FROM LOG WHERE MSG LIKE '%down%';                 -- returns nothing
SELECT MSG FROM LOG WHERE CAST(MSG AS VARCHAR) LIKE '%down'; -- returns the row

我不知道为什么将VARCHAR转换为VARCHAR会有所作为。

更新:另一个MCVE

CREATE TABLE LOG (MSG VARCHAR(6291456) NOT NULL);

INSERT INTO LOG VALUES (X'666163696c6974793d6461656d6f6e3b636f6d706f6e656e743d6e616d65643b746578743d7368757474696e6720646f776e');
INSERT INTO LOG VALUES ('facility=daemon;component=named;text=shutting down');

SELECT ROWID,MSG FROM LOG;                                         -- returns both rows

SELECT ROWID,MSG FROM LOG WHERE MSG LIKE '%down';                  -- returns just the second

SELECT ROWID,MSG FROM LOG WHERE MSG LIKE '%down%';                 -- returns just the second

SELECT ROWID,MSG FROM LOG WHERE CAST(MSG AS VARCHAR) LIKE '%down'; -- returns both rows

SELECT HEX(MSG) FROM LOG;

2 个答案:

答案 0 :(得分:1)

鉴于您的示例数据和在不同版本的sqlite上看到的结果,这是肯定的事情。

首先,您要在表中而不是字符串中插入Blob。这些Blob会按原样存储,而不是像您正在使用的那样,将数字值转换为具有TEXT相似性的列的数值。有关列亲和力和隐式数据类型转换的详细信息,请参见the documentation

第二,与{b3}不匹配的sqlite3实例是在SQLITE_LIKE_DOESNT_MATCH_BLOBS配置选项打开的情况下构建的,而与它们匹配的sqlite3实例是在关闭此选项的情况下构建的(默认设置)。

  

如果两个操作数中的任何一个是BLOB,此编译时选项都会使LIKE运算符始终返回False。 LIKE的默认行为是在完成比较之前将BLOB操作数强制转换为TEXT。

如果您检查PRAGMA compile_options的输出,则应该能够验证它是否正在使用。

答案 1 :(得分:0)

我会将其粘贴到注释中,但是格式看起来很难看。它对我有用:

$ sqlite3 log.db
SQLite version 3.24.0 2018-06-04 14:10:15
Enter ".help" for usage hints.
sqlite> create table log (id int, msg text);
sqlite> insert into log values (1,'database is down');
sqlite> insert into log values (2,'database is down');
sqlite> insert into log values (3,'database is down');
sqlite> ^D
$ sqlite3 log.db "select msg from log" | grep down$ | wc -l
       3
$ sqlite3 log.db "select msg from log where msg like '%down'" | grep down$ | wc -l
       3

您可以共享log表的内容,以便我尝试重现您的问题吗?