SQLite中的这个不可见字符是什么?

时间:2018-10-09 16:46:03

标签: sqlite

这是测试用例:

sqlite> SELECT DISTINCT quote(meta_sheet_name), length(meta_sheet_name)
   ...>   FROM calendar.data calendar_tasks
   ...>   WHERE calendar_tasks.meta_sheet_name LIKE "%Tasks"
   ...> ;  
quote(meta_sheet_name)|length(meta_sheet_name)
'Tasks'|5

sqlite> SELECT DISTINCT quote(meta_sheet_name), length(meta_sheet_name)
   ...>   FROM calendar.data calendar_tasks
   ...>   WHERE calendar_tasks.meta_sheet_name LIKE "Tasks%"
   ...> ;  
quote(meta_sheet_name)|length(meta_sheet_name)
'Tasks'|5

sqlite> SELECT DISTINCT quote(meta_sheet_name), length(meta_sheet_name)
   ...>   FROM calendar.data calendar_tasks
   ...>   WHERE calendar_tasks.meta_sheet_name LIKE "Tasks"
   ...> ;  
sqlite> 

由于某种原因,最后一个查询不返回该行,而其他查询则返回。这是SELECT语句https://sqlite.org/lang_select.html上的SQLite文档,我找不到更具体的文档来记录LIKE的用法。


其他调试信息:

SQLite版本3.7.17 2013-05-20 00:56:22 118a3b35693b134d56ebd780123b7fd6f1497668

解释查询计划

sqlite> EXPLAIN QUERY PLAN SELECT DISTINCT quote(meta_sheet_name), length(meta_sheet_name)
   ...>   FROM calendar.data calendar_tasks
   ...>   WHERE calendar_tasks.meta_sheet_name LIKE "%Tasks"
   ...> ;  
selectid|order|from|detail
0|0|0|SCAN TABLE data AS calendar_tasks USING COVERING INDEX data_index (~500000 rows)
0|0|0|USE TEMP B-TREE FOR DISTINCT

sqlite> EXPLAIN QUERY PLAN SELECT DISTINCT quote(meta_sheet_name), length(meta_sheet_name)
   ...>   FROM calendar.data calendar_tasks
   ...>   WHERE calendar_tasks.meta_sheet_name LIKE "Tasks%"
   ...> ;  
selectid|order|from|detail
0|0|0|SCAN TABLE data AS calendar_tasks USING COVERING INDEX data_index (~500000 rows)
0|0|0|USE TEMP B-TREE FOR DISTINCT

sqlite> EXPLAIN QUERY PLAN SELECT DISTINCT quote(meta_sheet_name), length(meta_sheet_name)
   ...>   FROM calendar.data calendar_tasks
   ...>   WHERE calendar_tasks.meta_sheet_name LIKE "Tasks"
   ...> ;  
selectid|order|from|detail
0|0|0|SCAN TABLE data AS calendar_tasks (~500000 rows)
0|0|0|USE TEMP B-TREE FOR DISTINCT

说明

sqlite> EXPLAIN SELECT DISTINCT quote(meta_sheet_name), length(meta_sheet_name)
   ...>   FROM calendar.data calendar_tasks
   ...>   WHERE calendar_tasks.meta_sheet_name LIKE "%Tasks"
   ...> ;  
addr|opcode|p1|p2|p3|p4|p5|comment
0|Trace|0|0|0||00|
1|OpenEphemeral|1|0|0|keyinfo(2,BINARY,BINARY)|08|
2|Goto|0|20|0||00|
3|OpenRead|2|3|2|keyinfo(3,BINARY,BINARY)|00|
4|Rewind|2|18|1|0|00|
5|String8|0|2|0|%Tasks|00|
6|Column|2|1|3||00|
7|Function|1|2|1|like(2)|02|
8|IfNot|1|17|1||00|
9|Column|2|1|2||00|
10|Function|0|2|4|quote(1)|01|
11|Column|2|1|3||40|
12|Function|0|3|5|length(1)|01|
13|Found|1|17|4|2|00|
14|MakeRecord|4|2|1||00|
15|IdxInsert|1|1|0||00|
16|ResultRow|4|2|0||00|
17|Next|2|5|0||01|
18|Close|2|0|0||00|
19|Halt|0|0|0||00|
20|Transaction|2|0|0||00|
21|VerifyCookie|2|37|0||00|
22|TableLock|2|2|0|data|00|
23|Goto|0|3|0||00|

sqlite> EXPLAIN SELECT DISTINCT quote(meta_sheet_name), length(meta_sheet_name)
   ...>   FROM calendar.data calendar_tasks
   ...>   WHERE calendar_tasks.meta_sheet_name LIKE "Tasks%"
   ...> ;  
addr|opcode|p1|p2|p3|p4|p5|comment
0|Trace|0|0|0||00|
1|OpenEphemeral|1|0|0|keyinfo(2,BINARY,BINARY)|08|
2|Goto|0|20|0||00|
3|OpenRead|2|3|2|keyinfo(3,BINARY,BINARY)|00|
4|Rewind|2|18|1|0|00|
5|String8|0|2|0|Tasks%|00|
6|Column|2|1|3||00|
7|Function|1|2|1|like(2)|02|
8|IfNot|1|17|1||00|
9|Column|2|1|2||00|
10|Function|0|2|4|quote(1)|01|
11|Column|2|1|3||40|
12|Function|0|3|5|length(1)|01|
13|Found|1|17|4|2|00|
14|MakeRecord|4|2|1||00|
15|IdxInsert|1|1|0||00|
16|ResultRow|4|2|0||00|
17|Next|2|5|0||01|
18|Close|2|0|0||00|
19|Halt|0|0|0||00|
20|Transaction|2|0|0||00|
21|VerifyCookie|2|37|0||00|
22|TableLock|2|2|0|data|00|
23|Goto|0|3|0||00|

sqlite> EXPLAIN SELECT DISTINCT quote(meta_sheet_name), length(meta_sheet_name)
   ...>   FROM calendar.data calendar_tasks
   ...>   WHERE calendar_tasks.meta_sheet_name LIKE "Tasks"
   ...> ;  
addr|opcode|p1|p2|p3|p4|p5|comment
0|Trace|0|0|0||00|
1|OpenEphemeral|1|0|0|keyinfo(2,BINARY,BINARY)|08|
2|Goto|0|20|0||00|
3|OpenRead|0|2|2|38|00|
4|Rewind|0|18|0||00|
5|Column|0|37|2||00|
6|Column|0|1|3||00|
7|Function|0|2|1|like(2)|02|
8|IfNot|1|17|1||00|
9|Column|0|1|2||00|
10|Function|0|2|4|quote(1)|01|
11|Column|0|1|3||40|
12|Function|0|3|5|length(1)|01|
13|Found|1|17|4|2|00|
14|MakeRecord|4|2|1||00|
15|IdxInsert|1|1|0||00|
16|ResultRow|4|2|0||00|
17|Next|0|5|0||01|
18|Close|0|0|0||00|
19|Halt|0|0|0||00|
20|Transaction|2|0|0||00|
21|VerifyCookie|2|37|0||00|
22|TableLock|2|2|0|data|00|
23|Goto|0|3|0||00|

1 个答案:

答案 0 :(得分:0)

如果您真的想从SQLite角度了解实际情况,请使用以下命令

sqlite> .show

这将列出相应数据库的所有默认设置

       echo: off
        eqp: off
    explain: auto
    headers: off
       mode: list
  nullvalue: ""      /* This setting is set to empty string */
    output: stdout
colseparator: "|"
rowseparator: "\n"
    stats: off
    width: 

实际上,空值设置为空,因此您将所有空值视为空字符串

nullvalue: ""

如果要在空字符串的位置看到其他任何字符,则可以使用以下方式进行设置。但这是临时的,直到您退出数据库。

您可以如下设置:

.nullvalue NULL

现在它将开始将空字符串显示为NULL,类似于MySql