2008-08-27 33 views
11

Tôi có một cơ sở dữ liệu có tên trong đó chẳng hạn như John Doe, vv Thật không may, một số tên trong số này có chứa các dấu ngoặc kép như Keiran O'Keefe. Bây giờ, khi tôi thử và tìm kiếm những tên như sau:Làm cách nào để xử lý các dấu ngoặc kép 'trong SQL

SELECT * FROM PEOPLE WHERE SURNAME='O'Keefe' 

Tôi (có thể hiểu) gặp lỗi.

Làm cách nào để ngăn lỗi này xảy ra. Tôi đang sử dụng Oracle và PLSQL.

+0

Xem [** Kỹ thuật ký hiệu chuỗi trích dẫn cho dấu nháy đơn **] (http://lalitkumarb.com/2014/12/31/quoting-string-literal-technique-to-avoid-erros -due-to-single-quotes-marks-in-the-string /) –

Trả lời

30

Ký tự thoát là ', vì vậy bạn cần phải thay thế báo giá bằng hai dấu ngoặc kép.

Ví dụ,

SELECT * FROM PEOPLE WHERE SURNAME='O'Keefe'

trở thành

SELECT * FROM PEOPLE WHERE SURNAME='O''Keefe'

Điều đó nói rằng, nó có thể không chính xác để làm điều này cho mình. Ngôn ngữ của bạn có thể có một chức năng để thoát khỏi chuỗi để sử dụng trong SQL, nhưng một lựa chọn tốt hơn là sử dụng các tham số. Thông thường điều này hoạt động như sau.

lệnh SQL của bạn sẽ là:

SELECT * FROM PEOPLE WHERE SURNAME=?

Sau đó, khi bạn thực hiện nó, bạn vượt qua trong "O'Keefe" như một tham số.

Vì SQL được phân tích cú pháp trước khi giá trị tham số được đặt, không có cách nào cho giá trị tham số thay đổi cấu trúc của SQL (và thậm chí nhanh hơn một chút nếu bạn muốn chạy cùng một câu lệnh nhiều lần với các tham số khác nhau).

Tôi cũng nên chỉ ra rằng, trong khi ví dụ của bạn chỉ gây ra lỗi, bạn tự mở cho mình nhiều vấn đề khác bằng cách không thoát chuỗi một cách thích hợp. Xem http://en.wikipedia.org/wiki/SQL_injection để có điểm xuất phát tốt hoặc cổ điển sau đây xkcd comic.

alt text

+0

+1 để giới thiệu các biến liên kết. Nếu bạn sử dụng các biến liên kết, những thứ gây phiền nhiễu như thế này không bao giờ xảy ra và các truy vấn của bạn tốt hơn, và bạn không mở các cuộc tấn công SQL injection. –

+0

Cảm ơn rất nhiều, bạn chỉ cần lưu ngày của tôi :). Chúc tôi có thể +2 bài đăng này. Phim hoạt hình đẹp quá :) –

0

lọc đầu vào thường được thực hiện vào mức độ ngôn ngữ chứ không phải là lớp cơ sở dữ liệu.
php và .NET đều có thư viện tương ứng để thoát khỏi các câu lệnh sql. Kiểm tra ngôn ngữ của bạn, xem waht có sẵn.
Nếu dữ liệu của bạn là đáng tin cậy, thì bạn chỉ có thể làm một chuỗi thay thế để thêm một 'infront khác của' để thoát khỏi nó. Thông thường đó là đủ nếu không có bất kỳ rủi ro mà đầu vào là độc hại.

1

Tôi cho rằng câu hỏi hay là ngôn ngữ bạn đang sử dụng?
Trong PHP bạn sẽ làm: SELECT * FROM PEOPLE WHERE SURNAME = 'mysql_escape_string (O'Keefe)'
Nhưng vì bạn không chỉ định ngôn ngữ, tôi sẽ đề nghị bạn xem xét một hàm chuỗi thoát mysql hoặc cách khác trong ngôn ngữ.

+0

'mysqli_real_escape_string()' để có thêm phương pháp cập nhật. – Jordan

1

Truy vấn tham số là bạn của bạn, theo đề xuất của Matt.

Command = SELECT * FROM PEOPLE WHERE SURNAME=? 

Họ sẽ bảo vệ bạn khỏi đau đầu liên quan với

  • Strings với dấu ngoặc kép
  • Truy vấn sử dụng ngày
  • SQL Injection
1

Sử dụng SQL tham số có những lợi ích khác, nó giảm chi phí CPU (cũng như các tài nguyên khác) trong Oracle bằng cách giảm số lượng công việc Oracle req uires để phân tích cú pháp tuyên bố. Nếu bạn không sử dụng tham số (chúng tôi gọi chúng là các biến liên kết trong Oracle) thì "select * from foo where bar = 'cat'" và "select * from foo where bar = 'dog'" được coi là các câu lệnh riêng biệt, ở đâu là " chọn * từ foo nơi bar =: b1 "là cùng một câu lệnh, có nghĩa là những thứ như cú pháp, giá trị của các đối tượng được tham chiếu vv ... không cần phải được kiểm tra lại. Có những vấn đề thường xảy ra khi sử dụng các biến liên kết thường không thể nhận được kế hoạch thực hiện SQL hiệu quả nhất nhưng có cách giải quyết cho vấn đề này và các vấn đề này thực sự phụ thuộc vào các biến vị ngữ bạn đang sử dụng, lập chỉ mục và dữ liệu nghiêng.

3

Oracle 10 giải pháp là

SELECT * FROM PEOPLE WHERE SURNAME=q'{O'Keefe}' 
+0

downvote. Ngay cả với Oracle, bạn nên sử dụng các truy vấn parametrized. –

0

Để đối phó dấu ngoặc kép nếu bạn đang sử dụng Zend Framework đây là mã

$db = Zend_Db_Table_Abstract::getDefaultAdapter();

$db->quoteInto('your_query_here = ?','your_value_here');

ví dụ;

//SELECT * FROM PEOPLE WHERE SURNAME='O'Keefe' will become 
SELECT * FROM PEOPLE WHERE SURNAME='\'O\'Keefe\'' 
Các vấn đề liên quan