Sqlite3将字符串存储为十六进制

时间:2018-02-20 10:25:09

标签: ruby sqlite sqlite3-ruby

在Ruby脚本中,我需要从现有的g SQLite3数据库中读取一些值。

DB = SQLite3::Database.open "#{App.root}/db/dm4sea_#{App.env}.db"

数据库有1个表(批次),结构如下

DB.execute "PRAGMA table_info(batches);"
=> [[0, "batch", "VARCHAR(30)", 0, nil, 1], 
   [1, "fdl", "INT", 0, nil, 0], 
   [2, "created_at", "DATETIME", 0, nil, 0], 
   [3, "updated_at", "DATETIME", 0, nil, 0]]

目前的内容是

DB.execute "SELECT * FROM batches"
=> [["TTX1", 0, "2018-02-20 10:26:17 +0100", "2018-02-20 10:26:17 +0100"], 
    ["TTX2", 0, "2018-02-20 10:36:33 +0100", "2018-02-20 10:36:33 +0100"], 
    ["TTX3", 0, "2018-02-20 10:39:52 +0100", "2018-02-20 10:39:52 +0100"]]

然而,令我惊讶的是,以下情况发生了

DB.execute "SELECT * FROM batches WHERE batch = 'TTX3'"
=> [] 

这里是数据库转储

sqlite> .dump
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE batches (
          batch VARCHAR(30) PRIMARY KEY,
          fdl INT,
          created_at DATETIME,
          updated_at DATETIME
        );
INSERT INTO batches VALUES(X'54545831',0,'2018-02-20 11:40:46 +0100','2018-02-20 11:40:46 +0100');
INSERT INTO batches VALUES(X'54545832',0,'2018-02-20 11:40:54 +0100','2018-02-20 11:40:54 +0100');
INSERT INTO batches VALUES(X'54545833',0,'2018-02-20 11:41:02 +0100','2018-02-20 11:41:02 +0100');
CREATE INDEX batches_batch
        ON batches (batch);
CREATE INDEX batches_fdl
        ON batches (fdl);
COMMIT;

为什么批次存储为十六进制值?

DB.execute "SELECT * FROM batches WHERE batch = X'54545833'"
=> [["TTX3", 0, "2018-02-20 11:41:02 +0100", "2018-02-20 11:41:02 +0100"]]

2 个答案:

答案 0 :(得分:0)

X前缀将HEX值转换为字符串。

sqlite> SELECT X'41';
A
sqlite> SELECT X'42';
B
sqlite> SELECT X'4242';
BB
sqlite> SELECT X'54545831';
TTX1 # Do not forget this one
sqlite> SELECT X'54';
T
sqlite> SELECT X'58';
X

不要让我们看到你的代码,

sqlite> select * from batches;
TTX1|0|2018-02-20 11:40:46 +0100|2018-02-20 11:40:46 +0100
TTX2|0|2018-02-20 11:40:54 +0100|2018-02-20 11:40:54 +0100
TTX3|0|2018-02-20 11:41:02 +0100|2018-02-20 11:41:02 +0100

以下查询返回空集。

sqlite> SELECT * FROM batches WHERE batch = 'TTX1';
sqlite> SELECT * FROM batches WHERE batch = 'TTX2';
sqlite> SELECT * FROM batches WHERE batch = 'TTX3';

不插入普通的字符串数据。

sqlite> INSERT INTO batches VALUES('TTX2',0,'2018-02-20 11:40:46 +0100','2018-02-20 11:40:46 +0100');
sqlite> select * from batches;
TTX1|0|2018-02-20 11:40:46 +0100|2018-02-20 11:40:46 +0100
TTX2|0|2018-02-20 11:40:54 +0100|2018-02-20 11:40:54 +0100
TTX3|0|2018-02-20 11:41:02 +0100|2018-02-20 11:41:02 +0100
TTX2|0|2018-02-20 11:40:46 +0100|2018-02-20 11:40:46 +0100
sqlite> select * from batches where batch = 'TTX2';
TTX2|0|2018-02-20 11:40:46 +0100|2018-02-20 11:40:46 +0100

让我们检查一些平等。

sqlite> Select 123 = 123;
1
sqlite> Select X'54545831' = 'TTX1';
0

响应batch = TTX{number}的数据是您作为字符串插入的数据。但其他人没有遇到这种情况。

答案 1 :(得分:0)

这些值存储为十六进制,它们存储为blob。在SQL语句中,编写blob的唯一方法是使用blob literal,其中blob的字节用十六进制数字表示。

无论编写什么程序,数据库都将这些值写为blob。

要搜索blob,请将搜索值转换为blob:

SELECT * FROM batches WHERE batch = CAST('TTX3' AS BLOB);

或者,修改数据库以使其包含文本值(可能会破坏其他程序):

UPDATE batches SET batch = CAST(batch AS TEXT);