这应该是最简单的事情,但由于某种原因它完全逃避了我。
我有一个名为DB
的数据库的续集连接。如果这很重要的话,它会使用Mysql2引擎。
我试图更新数据库中表中的单个记录。我使用的短循环如下所示:
dataset = DB["SELECT post_id, message FROM xf_post WHERE message LIKE '%#{match}%'"]
dataset.each do |row|
new_message = process_message(row[:message])
# HERE IS WHERE I WANT TO UPDATE THE ROW IN THE DATABASE!
end
我试过了:
dataset.where('post_id = ?', row[:post_id]).update(message: new_message)
这是the Sequel cheat sheet recommends。
和
DB["UPDATE xf_post SET message = ? WHERE post_id = ?", new_message, row[:post_id]]
哪个应该是Sequel连接器执行的原始SQL。既不会抛出错误也不会输出任何错误消息(我使用带有续集连接的记录器)。但是这两个调用都无法更新数据库中的记录。在运行代码后查询数据库时数据未更改。
如何在此处正确更新呼叫功能?
答案 0 :(得分:1)
您的问题是您正在使用原始SQL数据集,因此where
调用不会更改SQL,而update
只是执行原始SQL。这是你想做的事情:
dataset = DB[:xf_post].select(:post_id, :message).
where(Sequel.like(:message, "%#{match}%"))
这会使where
/ update
组合起作用。
请注意,如果match
依赖于用户输入,则原始代码会有一个简单的SQL注入漏洞,而这个新代码会避免这种情况。如果要在Dataset#escape_like
内转义元字符,可能需要考虑使用match
,否则如果match
依赖于用户输入,则用户可以使用非常复杂的匹配语法数据库可能执行缓慢或无法正确处理。
注意原因
DB["UPDATE xf_post SET message = ? WHERE post_id = ?", new_message, row[:post_id]]
不起作用是因为它只创建一个数据集,它不会执行它。您实际上可以在该数据集上调用update
来运行查询并返回受影响的行数。