【问题标题】:Sqlite where clause is not working (is this a bug?)Sqlite where 子句不起作用(这是一个错误吗?)
【发布时间】:2012-03-15 12:24:58
【问题描述】:

我正在调试一个在 Sqlite 上运行时出现问题的 Ruby on Rails 引擎,它在查找应用程序本身创建的记录时出现问题。在 MySQL 上运行时,一切正常,但 SQLite 上的相同查询失败。

我已经找到了这个问题,我发现问题出在一个简单的 WHERE 查询中,它找不到创建的记录。本质上,表结构有一个名为 key 的列,它存储一些 md5 哈希。失败的规范插入具有给定哈希的记录,然后在以下指令中对相同的哈希执行 SELECT 查询,但 SQLite 不返回相同键的记录。我已经从应用程序中提取了生成的数据库和失败的查询,这是应用程序数据库的副本:

http://dl.dropbox.com/u/2289657/combustion_test.sqlite

以下是软件执行的查询记录(使用命令行实用程序制作):

# Here I'm selecting all the records from the table
# there is a single record  in it, the key is the third field
$ sqlite3 combustion_test.sqlite 'SELECT * FROM tr8n_translation_keys'
1||b56c67d10759f8012aff28fc03f26cbf|Hello World|We must start with this sentence!||||en-US|0|2012-03-14 11:49:50.335322|2012-03-14 11:49:50.335322|

# Here I'm selecting the record with that key and it doesn't return anything
$ sqlite3 combustion_test.sqlite "SELECT * FROM tr8n_translation_keys WHERE key = 'b56c67d10759f8012aff28fc03f26cbf'"

# Here I'selecting the record with a LIKE clause and it finds the record
$ sqlite3 combustion_test.sqlite "SELECT * FROM tr8n_translation_keys WHERE key LIKE 'b56c67d10759f8012aff28fc03f26cbf'"
1||b56c67d10759f8012aff28fc03f26cbf|Hello World|We must start with this sentence!||||en-US|0|2012-03-14 11:49:50.335322|2012-03-14 11:49:50.335322|

我应该将此作为错误报告给 SQLite 网站吗?

附:我也尝试过使用不同 SQLite 版本的不同系统,但结果是一样的。

更新

这是表架构

sqlite> .schema tr8n_translation_keys
CREATE TABLE "tr8n_translation_keys" (
   "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 
   "type" varchar(255), "key" varchar(255) NOT NULL,
   "label" text NOT NULL, 
   "description" text, 
   "verified_at" datetime, 
   "translation_count" integer, 
   "admin" boolean, 
   "locale" varchar(255), 
   "level" integer DEFAULT 0, 
   "created_at" datetime, 
   "updated_at" datetime, 
   "synced_at" datetime
);
CREATE UNIQUE INDEX "index_tr8n_translation_keys_on_key" ON "tr8n_translation_keys" ("key");
CREATE INDEX "index_tr8n_translation_keys_on_synced_at" ON "tr8n_translation_keys" ("synced_at");

更新 2

这是计算插入表中的键值的 rails 代码(我删除了一些代码,完整方法 is here

def self.find_or_create(label, desc = "", options = {})
  key = generate_key(label, desc).to_s
  # IF I UNCOMMENT THIS LINE EVERYTHING WORKS
  #key = 'b56c67d10759f8012aff28fc03f26cbf'
  
  tkey = Tr8n::Cache.fetch("translation_key_#{key}") do
    existing_key = where(:key => key).first ### THIS IS THE FAILING WHERE
    
    existing_key ||= begin
      new_tkey = create(:key => key.to_s, 
                        :label => label, 
                        :description => desc, 
                        :locale => locale,
                        :level => level,
                        :admin => Tr8n::Config.block_options[:admin])
# rest of method...

这里是generate_key方法,关于sqlite的评论来自作者,不是我的)

def self.generate_key(label, desc = "")
  # TODO: there is something iffy going on with the strings from the hash
  # without the extra ~ = the strings are not seen in the sqlite database - wtf?
  "#{Digest::MD5.hexdigest("#{label};;;#{desc}")}"
end

【问题讨论】:

  • 请同时发布您的表定义。
  • @DarkFalcon 我已经发布了表格架构

标签: ruby-on-rails sqlite


【解决方案1】:

这行得通:

SELECT * FROM tr8n_translation_keys WHERE LOWER(key)='b56c67d10759f8012aff28fc03f26cbf';

但这不是:

SELECT * FROM tr8n_translation_keys WHERE key='b56c67d10759f8012aff28fc03f26cbf' COLLATE NOCASE;

当我在 SQLiteManager 中检查数据库时,它显示 key 如下:

X'6235366336376431303735396638303132616666323866633033663236636266'

这意味着它将key 视为BLOB(原始二进制数据)而不是TEXT。这就是比较失败的原因。但是LOWER(key) 会导致字段转换为文本,因此比较成功。

因此,我们需要找出为什么该条目被存储为BLOB 而不是TEXT。这些值是如何插入数据库的?


在您的更新 2 之后:我不是 Ruby 专家,但从 generate_key 返回的值没有按照您期望的方式转换为字符串。在调用generate_key 时尝试to_str 而不是to_s

【讨论】:

  • 那么问题应该出在与区分大小写有关的东西上吗?这可以解释为什么 LIKE 选择有效。有没有办法查看存储在现场的原始数据?只是为了查看该记录中实际存储的内容。
  • 这很奇怪,表是由rails迁移创建的,这是我第一次看到这样的问题。我用 RoR 迁移管理了很多表,他们从来没有做过什么奇怪的事情。我想我会向 SQLite 站点发布错误报告。感谢您的帮助。
【解决方案2】:

基于以下 Stack Overflow 答案...

https://stackoverflow.com/a/6591427/18064

...您可能希望按如下方式更新密钥的生成:

def self.generate_key(label, desc = "")
   # TODO: there is something iffy going on with the strings from the hash
   # without the extra ~ = the strings are not seen in the sqlite database - wtf?
   "#{Digest::MD5.hexdigest("#{label};;;#{desc}").encode('UTF-8')}"
end

注意添加.encode('UTF-8')

当我遇到和你一样的问题时,这对我有用。

【讨论】:

    猜你喜欢
    • 2018-08-04
    • 1970-01-01
    • 1970-01-01
    • 2013-01-31
    • 1970-01-01
    • 2016-07-24
    • 1970-01-01
    • 1970-01-01
    • 2015-01-27
    相关资源
    最近更新 更多