sco*_*ies 3 ruby sql postgresql activerecord ruby-on-rails
如果我有一个数字(例如88)并且我想在主ID列的Rails中执行LIKE查询以返回在ID结尾处包含该数字的所有记录(IE:88,288等),我该怎么办?这是生成结果的代码,在SQLLite中可以正常工作:
@item = Item.where("id like ?", "88").all
Run Code Online (Sandbox Code Playgroud)
在PostgreSQL中,我遇到了这个错误:
PG::Error: ERROR: operator does not exist: integer ~~ unknown
Run Code Online (Sandbox Code Playgroud)
我该怎么做呢?我已经尝试将数字转换为字符串,但这似乎也不起作用.
LIKE用于字符串/文本类型.由于您的主键是整数,因此您应该使用数学运算.
id当除以100时,使用modulo获取值的其余部分.
Item.where("id % 100 = 88")
Run Code Online (Sandbox Code Playgroud)
这将返回列Item以其id结尾的记录88
1288
1488
1238872388
862388
Run Code Online (Sandbox Code Playgroud)
等等...
如果您要动态执行此操作(例如,匹配任意两位数字,但您知道它总是两位数),您可以执行以下操作:
Item.where(["id % 100 = ?", last_two_digits)
Run Code Online (Sandbox Code Playgroud)
如果您想匹配任意数量的数字,只要它们始终是最终数字(而不是id字段中其他位置出现的数字),您可以在模型上添加自定义方法.就像是:
class Item < ActiveRecord
...
def find_by_final_digits(num_digits, digit_pattern)
# Where 'num_digits' is the number of final digits to match
# and `digit_pattern` is the set of final digits you're looking fo
Item.where(["id % ? = ?", 10**num_digits, digit_pattern])
end
...
end
Run Code Online (Sandbox Code Playgroud)
使用此方法,您可以找到id以...结尾的值88:
Item.find_by_final_digits(2, 88)
Run Code Online (Sandbox Code Playgroud)
比方说,你希望找到所有id与数字最终值之间的 09和12,无论出于何种原因.也许它们代表了你正在寻找的一些特殊代码范围.为此,您可以使用另一种自定义方法来使用Postgres BETWEEN来查找范围.
def find_by_final_digit_range(num_digits, start_of_range, end_of_range)
Item.where(["id % ? BETWEEN ? AND ?", 10**num_digits, start_of_range, end_of_range)
end
Run Code Online (Sandbox Code Playgroud)
......可以使用以下方式调用:
Item.find_by_final_digit_range(2, 9, 12)
Run Code Online (Sandbox Code Playgroud)
......当然,这只是有点疯狂,而且可能有点过分.
该LIKE运算符仅适用于字符串类型。
将模运算符%用于您要执行的操作:
@item = Item.where("(id % 100) = ?", "88").all
Run Code Online (Sandbox Code Playgroud)
我怀疑它在 SQLite 中“有效”,即使它将数字类型强制转换为字符串。不引导%模式是行不通的。
-> sqlfiddle 演示
投射到任意长度并按您的意图text使用:LIKE
@item = Item.where("(id::text LIKE ('%'::text || ?)", "'12345'").all
Run Code Online (Sandbox Code Playgroud)
或者,数学上:
@item = Item.where("(id % 10^(length(?)) = ?", "'12345'", "12345").all
Run Code Online (Sandbox Code Playgroud)
基于Erwin的答案:
这是一个非常老的问题,但是如果有人需要它,可以使用::textcast 使用一个非常简单的答案:
Item.where("(id::text LIKE ?)", "%#{numeric_variable}").all
Run Code Online (Sandbox Code Playgroud)
这样,您可以在字符串中的任意位置找到数字。仅当您希望数字位于字符串末尾时,才应在左侧
使用%通配符。如果您希望数字在字符串中的任何位置,也
请%在右侧使用通配符。
| 归档时间: |
|
| 查看次数: |
3020 次 |
| 最近记录: |