我对 sqlite 中的十六进制数字有疑问。
给定一个包含数字的 CSV 文件,其中一个数字写为十六进制 (0x1)
❯ cat my.csv
A,B
1,0x1
导入并检查架构
❯ sqlite3 my.db ".import --csv my.csv somet"
❯ sqlite3 my.db ".schema somet"
CREATE TABLE IF NOT EXISTS "somet"(
"A" TEXT, "B" TEXT);
现在我们可以选择 A 作为实数(没有单引号),但不能选择 B。
❯ sqlite3 my.db "select * from somet where a = 0x1;"
1|0x1
❯ sqlite3 my.db "select * from somet where b = 0x1;"
这对我来说是意料之外的。我们可以看到,SQLite 在 A 列上进行过滤时可以理解数字的十六进制表示,但在 B 列上却不能。
查看 A 的输出时,我们还看到 b 并未存储为数字,而似乎存储为一个十六进制字符串。
因此,鉴于 sqlite3 理解十六进制表示形式,并且它将使用数字作为“数字”,当导入 csv 时,为什么 B 不作为数字导入?
通过 shell 导入 CSV
sqlite3
会将值作为字符串插入。任何转换为其他存储类型的操作均由底层INSERT
根据列类型及其亲和性完成。B
表的列具有类型TEXT
,这意味着它具有文本亲和性;所有内容都存储为字符串(空值和 blob 除外)。如果您为列指定具有数字亲和性的类型,例如INTEGER
,包含整数文字的字符串将转换为 int,但以下情况除外您必须在导入之前更改 ETL 流程,用十进制整数替换这些十六进制值(并提前创建具有正确列类型的表),或者编写更智能的导入脚本。