2009-03-23 33 views
38

Tôi mổ xẻ một số mã và tình cờ này,Ý nghĩa của dấu hỏi trong MySQL tại "WHERE column =?" Là gì?

$sql = 'SELECT page.*, author.name AS author, updator.name AS updator ' 
    . 'FROM '.TABLE_PREFIX.'page AS page ' 
    . 'LEFT JOIN '.TABLE_PREFIX.'user AS author ON author.id = page.created_by_id ' 
    . 'LEFT JOIN '.TABLE_PREFIX.'user AS updator ON updator.id = page.updated_by_id ' 
    . 'WHERE slug = ? AND parent_id = ? AND (status_id='.Page::STATUS_REVIEWED.' OR status_id='.Page::STATUS_PUBLISHED.' OR status_id='.Page::STATUS_HIDDEN.')'; 

Tôi tự hỏi những biểu tượng "?" trong câu lệnh WHERE. Có một số loại trình giữ tham số không?

Trả lời

35

Thống kê được chuẩn bị sử dụng '?' trong MySQL để cho phép các tham số ràng buộc đối với câu lệnh. Được coi là an toàn hơn so với tiêm SQL nếu được sử dụng đúng cách. Điều này cũng cho phép truy vấn SQL nhanh hơn vì yêu cầu chỉ được biên dịch một lần và có thể được sử dụng lại.

+0

Làm cách nào để sử dụng chúng? Bằng cách đó tôi có nghĩa là làm thế nào để bạn thiết lập các dấu hỏi để đưa vào một tham số? – Levi

+1

Có nhiều cách để làm các câu lệnh chuẩn bị, PDO và MySQLi hỗ trợ chúng. http://us3.php.net/mysqli http://us3.php.net/manual/en/mysqli.prepare.php và tìm kiếm nhanh trên google đã đưa tôi đến http://www.petefreitag.com/item/ 356.cfm – Jayrox

24

Dấu hỏi đại diện cho thông số mà sau này sẽ được thay thế. Sử dụng truy vấn được tham số hóa an toàn hơn việc nhúng các thông số ngay vào truy vấn.

SQL Server gọi các truy vấn này tham số hóa và Oracle gọi nó liên kết các biến.

Cách sử dụng thay đổi theo ngôn ngữ mà bạn đang thực hiện truy vấn.

Dưới đây là ví dụ về cách sử dụng từ PHP.

giả định rằng $mysqli là kết nối cơ sở dữ liệu và people là bảng có 4 cột.

$stmt = $mysqli->prepare("INSERT INTO People VALUES (?, ?, ?, ?)"); 

$stmt->bind_param('sssd', $firstName, $lastName, $email, $age); 

Các 'sssd' là một lá cờ xác định phần còn lại của các thông số, nơi s đại diện cho chuỗi và d đại diện cho chữ số.

1

Đây là những chuẩn bị phát biểu, báo cáo chuẩn bị cung cấp hai lợi ích chính:

Truy vấn chỉ cần được phân tích cú pháp (hoặc chuẩn bị) một lần, nhưng có thể thực hiện nhiều lần với các thông số tương tự hoặc khác nhau. Khi truy vấn được chuẩn bị, cơ sở dữ liệu sẽ phân tích, biên dịch và tối ưu hóa kế hoạch của nó để thực hiện truy vấn. Đối với các truy vấn phức tạp, quá trình này có thể mất đủ thời gian để làm chậm ứng dụng nếu cần phải lặp lại cùng một truy vấn nhiều lần với các tham số khác nhau. Bằng cách sử dụng tuyên bố đã chuẩn bị, ứng dụng sẽ tránh lặp lại chu trình phân tích/biên dịch/tối ưu hóa. Điều này có nghĩa là các câu lệnh được chuẩn bị sử dụng ít tài nguyên hơn và do đó chạy nhanh hơn.

Các tham số cho các câu lệnh đã chuẩn bị không cần phải được trích dẫn; trình điều khiển sẽ tự động xử lý điều này. Nếu một ứng dụng chỉ sử dụng các câu lệnh chuẩn bị , nhà phát triển có thể chắc chắn rằng không có SQL injection sẽ xảy ra (tuy nhiên, nếu các phần khác của truy vấn đang được xây dựng với đầu vào chưa thoát, thì vẫn có thể tiêm SQL).

http://php.net/manual/en/pdo.prepared-statements.php

5

Không

? nghĩa gì để MySQL WHERE = khoản, chỉ để vài giao diện bên ngoài như PHP stdlib và web khuôn khổ như Rails.

? chỉ là một lỗi cú pháp tại địa chỉ:

CREATE TABLE t (s CHAR(1)); 
SELECT * FROM t WHERE s = ?; 

vì nó là không thể viện chứng, và nằm ở:

INSERT INTO t VALUES ('a'); 
INSERT INTO t VALUES ("?"); 
SELECT * FROM t WHERE s = '?'; 

nó sẽ trả về:

s 
? 

do đó dường như không có ý nghĩa đặc biệt.

Rails dụ

Trong Rails ví dụ, dấu hỏi được thay thế bằng một cuộc tranh cãi do một biến của ngôn ngữ lập trình của thư viện (Ruby), ví dụ:

Table.where("column = ?", "value") 

và nó tự động báo giá các đối số để tránh lỗi và chèn SQL, tạo một tuyên bố như:

SELECT * FROM Table WHERE column = 'value'; 

Trích dẫn ULD cứu chúng ta trong trường hợp của một cái gì đó như:

Table.where("column = ?", "; INJECTION") 

MySQL 5.0 chuẩn bị báo cáo

MySQL 5.0 thêm prepared statement feature trong đó có ngữ nghĩa tương tự như dấu hỏi trong khuôn khổ web.

Ví dụ từ các tài liệu:

PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse'; 
SET @a = 3; 
SET @b = 4; 
EXECUTE stmt1 USING @a, @b; 

Output:

hypotenuse 
5 

Đây cũng thoát khỏi nhân vật đặc biệt như mong đợi:

PREPARE stmt1 FROM 'SELECT ? AS s'; 
SET @a = "'"; 
EXECUTE stmt1 USING @a; 

Output:

s 
' 
Các vấn đề liên quan