2015-04-24 77 views
0

我在Ruby中有一個方法來查詢數據庫並打印出一些數據,而我試圖使用一個準備語句來代替。如何將變量傳遞給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

當你這樣說:

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

+0

這很有道理。非常感謝! – Teresa

相關問題