如何在 SQLite3 和 Rails 3.1 中打开 REGEXP?

Posted

技术标签:

【中文标题】如何在 SQLite3 和 Rails 3.1 中打开 REGEXP?【英文标题】:How to turn on REGEXP in SQLite3 and Rails 3.1? 【发布时间】:2011-10-13 22:19:08 【问题描述】:

我在使用 SQLite3 数据库的 Rails 3 中有以下语句:

word = 'Hello'
word_entry = Word.where("name REGEXP :word", :word => "[[:<:]]#word[[:>:]]")

但是,在 SQLite3 下运行它时,我不断得到:

SQLite3::SQLException: 没有这样的函数:REGEXP

我在 SQLite3 文档中读到它确实支持 REGEXP 函数。 在我的 gemfile 中,我有一行

gem 'sqlite3'

我的数据库配置文件如下所示:

development:
  adapter: sqlite3
  database: db/development.sqlite3
  pool: 5
  timeout: 5000

有什么想法吗?

解决方案: 我最终找到了this solution。不幸的是,它不适用于 Rails 3。 所以为了使用正则表达式,我最终改用 mysql 而不是 SQLite3。

【问题讨论】:

【参考方案1】:

我遇到了同样的问题。我采用了解决方案中使用的代码,将其移植到 Rails 3+ 中,并制作了一个 gem,以便于使用。我希望这会有所帮助。

https://github.com/sei-mi/sqlite3_ar_regexp

【讨论】:

为此,您将获得布朗尼积分(并且您的答案被标记为正确的)。谢谢谢谢谢谢!【参考方案2】:

来自fine manual:

REGEXP 运算符是 regexp() 用户函数的特殊语法。默认情况下没有定义 regexp() 用户函数,因此使用 REGEXP 运算符通常会导致错误消息。如果在运行时添加了名为“regexp”的应用程序定义的 SQL 函数,则会调用该函数以实现 REGEXP 运算符。

所以语法支持 REGEXP 但默认的 SQLite 库没有提供它的实现。如果你想要或需要这样的东西,你必须通过一些 C 争论来连接你自己的实现。

大概的理由是 SQLite 的人们希望 SQLite 尽可能小而紧凑,但包含一个完整的正则表达式库会增加大多数人不想要的重量。此外,他们必须选择一个正则表达式库并将其包含在 SQLite 源代码中,否则他们将不得不忍受每个人在 libc 中的正则表达式支持的变幻莫测。我不是 SQLite 开发人员之一,所以这纯粹是猜测。

我猜你可能不得不使用LIKE and GLOB。使用 LIKE 将提供更便携的解决方案。

【讨论】:

不够具体,无法解决我的问题,但这是我问题的正确答案。请参阅我题为 RESOLUTION 的问题中的编辑。 @yuval:这是一个很好的发现,可惜它不再起作用了。【参考方案3】:

您可能会在 sqlite3-pcre 包中进行测试,该包为 SQLite 实现了 REGEXP

有关类似问题,请参阅 this comment。

【讨论】:

【参考方案4】:

我有一个类似的问题,并找到了一个名为 wherex 的 Gem,它有据可查并且开箱即用。

你在上面的表情

Word.where("name REGEXP :word", :word => "[[:<:]]#word[[:>:]]")

会有

Word.where(:name => Regexp.new("[[:<:]]#word[[:>:]]"))

对我来说就像一个魅力:-)

【讨论】:

【参考方案5】:

从 sqlite3_ar_regexp 项目的源代码中,我提取了这个:

db = SQLite3::Database.open( database_name )
db.create_function('regexp', 2) do |func, pattern, expression|
  func.result = expression.to_s.match(
      Regexp.new(pattern.to_s, Regexp::IGNORECASE)) ? 1 : 0
end

【讨论】:

【参考方案6】:

从 sqlite3_ar_regexp 项目的源代码中,我提取了这个:

    db = ActiveRecord::Base.connection.raw_connection
    db.create_function('regexp', 2) do |func, pattern, expression|
      func.result = expression.to_s.match(
          Regexp.new(pattern.to_s, Regexp::IGNORECASE)) ? 1 : 0
    end

改进了ActiveRecord::Base.connection.raw_connection 的先前答案,因此不需要数据库名称

【讨论】:

以上是关于如何在 SQLite3 和 Rails 3.1 中打开 REGEXP?的主要内容,如果未能解决你的问题,请参考以下文章

这个 Rails 文件存储在哪里? db/development.sqlite3

Rails 3 SQLite3 布尔值 false

如何在 Rails 3.1 应用程序中完全禁用 CoffeeScript?

如何开始使用 Backbone.js 和 Rails 3.1

导轨 3.1。如何防止 Rails 使用 CoffeeScript?

将带有 SQLite3 的 Rails 推送到 Heroku 失败 [重复]