我在Ruby中有一个查询数据库并打印出一些数据的方法,而我正在尝试使用预备语句。
这是没有准备好的声明的正常运作方法:
def print_state_speakers(*states)
puts "STATE SPEAKERS"
state_string = "'#{states.*"', '"}'"
state_speakers = $db.execute("
SELECT name, location
FROM congress_members
WHERE location IN (#{state_string})
ORDER BY location")
state_speakers.each { |rep, location| puts "#{rep} - #{location}" }
end
这是我尝试使用预准备语句的相同方法:
def print_state_speakers(*states)
puts "STATE SPEAKERS"
state_string = "'#{states.*"', '"}'"
begin
pst = $db.prepare "SELECT name, location
FROM congress_members
WHERE location IN (?)
ORDER BY location"
state_speakers = pst.execute state_string
end
state_speakers.each { |rep, location| puts "#{rep} - #{location}" }
end
这是我调用方法的地方:
print_state_speakers('NJ', 'NY' , 'ME', 'FL', 'AK')
当我用第一种方法运行文件时它会显示数据,当我使用第二种方法时,它什么也没显示。它不会引发错误。我觉得语法需要与传入的字符串不同,但我一直在网上搜索并乱用它一段时间而无法让它工作。任何有关如何修复准备好的声明的见解将不胜感激。
答案 0 :(得分:0)
当你这样说时:
pst = $db.prepare "SELECT name, location
FROM congress_members
WHERE location IN (?)
ORDER BY location"
state_speakers = pst.execute state_string
pst.execute
调用将转义并引用state_string
,就像任何其他字符串一样。但是你的state_string
实际上不是一个单独的字符串,它是一个表示为(Ruby)字符串的SQL列表,因此你最终会双重引用所有内容。
一个简单的解决方案是使用字符串插值来添加适当数量的占位符,然后让SQLite3::Statement
处理所有引用本身:
placeholders = ([ '?' ] * states.length).join(',')
pst = $db.prepare "SELECT name, location
FROM congress_members
WHERE location IN (#{placeholders})
ORDER BY location"
state_speakers = pst.execute states
这种字符串插值的使用非常安全,因为您确切知道placeholders
中的内容。