2011-11-18 19 views
14

Mam tabelę companies, która ma dwie kolumny o nazwach name i address. Uruchamiając poniższy kod, nowe dane są wstawiane do tabeli:Uciekając pojedynczy cytat z zapytania SQL

my_name = "my company name" 
my_address = "ABC" 

query = "INSERT INTO companies (name,address) VALUES ('#{my_name}','#{my_address}');" 

ActiveRecord::Base.connection.execute(query); 

Jeśli zmienię my_name wartość z "my company name" do "John's company", będę się błąd składni. To dlatego, że zapytanie się:

"INSERT INTO companies (name,address) VALUES ('John's company','ABC');" 

i 'John's company' ma pojedynczy cudzysłów wewnątrz niej.

Biorąc pod uwagę, że już użyłem podwójnego cudzysłowu do definicji ciągu zapytania, jak mogę pozbyć się tego błędu dotyczącego pojedynczego cudzysłowu w mojej wartości?

+0

uciec z \? – rgin

+0

if my_name.include? ('\' ') My_name.sub (/' /, '\' ')? –

+3

To jest naprawdę zły pomysł ... ryzykujesz ataki SQL injection, nawet jeśli unikniesz pojedynczych cudzysłowów z odwróconymi ukośnikami. Musisz zrozumieć kodowanie znaków, ale na to naiwne podejście jest poważny (znany) exploit. Użyj parametrów wiązania w zapytaniu i pozwól DBMS bezpiecznie przetransportować wartości. – d11wtq

Odpowiedz

61

Jeśli musisz zrobić to w ten sposób, a następnie użyć quote method na obiekcie gra:

ofertowe (wartość, kolumna = nil)
Cytaty wartość kolumny, aby zapobiec atakom SQL injection.

Więc coś takiego:

my_name = ActiveRecord::Base.connection.quote("John O'Neil") 
my_address = ActiveRecord::Base.connection.quote("R'lyeh") 

query = "INSERT INTO companies (name,address) VALUES (#{my_name}, #{my_address})" 

ActiveRecord::Base.connection.execute(query); 

Nigdy nie próbować obsługiwać własne cytowania. I nie próbuj używać podwójnych cudzysłowów do cytowania literału SQL, do czego służą pojedyncze cytaty; podwójne cudzysłowy służą do cytowania identyfikatorów (takich jak nazwy tabel i kolumn) w większości baz danych, ale MySQL używa do tego odsyłaczy.

+0

Ponieważ używam zmiennej dla my_name, myślę, że mogę użyć my_name = ActiveRecord :: Base.connection.quote (NAME_VARIABLE) –

+0

@ Leem.fin: Right. Lub możesz umieścić go wewnątrz interpolacji ciągów, ale to sprawi, że twój kod będzie trudniejszy do odczytania. –

+0

Myślę, że w twoim kodzie jest błąd, powinieneś usunąć pojedynczy cudzysłów w części VALUES zapytania, ponieważ metoda quote() już dodała znak cudzysłowu dla ciągu znaków. Teraz jeśli uruchomię kod tak jak powiedziałeś, otrzymałem błąd składni SQL, ponieważ mam "firmę Johna" jako wartość –

Powiązane problemy