Trong truy vấn SQL, chỉ có các giá trị (literal) mới có thể được tham số hóa, còn các định danh (identifier) ví dụ: tên trường, tên bảng, tên view, ..., các từ khóa (keyword) thì không thể tham số hóa được. Do đó, không thể xây dựng các truy vấn tham số hóa như các dạng sau:
Trong đó các dấu ? là các biến giữ chỗ (placeholder), tùy vào từng database, biến giữ chỗ sẽ khác nhau, chúng ta sẽ đề cập cụ thể về chúng ở các mục sau.
Như vậy, trong nhiều vấn được sử dụng, ta có thể sử dụng truy vấn SQL động trong đó xâu ký tự mô tả truy vấn đó sẽ được sử dụng để tham số hóa, ví dụ một xâu mô tả truy vấn như sau:
String sql = "SELECT * FROM " + tbl_Name + "WHERE column_Name = ?"
Nói chung, trong những trường hợp mà ứng dụng của chúng ta cần sử dụng các định danh đóng vai trò tham số thì chúng ta cần cân nhắc kỹ. Nếu có thể, hãy tối đa sử dụng các định danh đó dưới dạng truy vấn tĩnh (fixed), điều đó khiến database tối ưu truy vấn dễ dàng hơn, và cũng phần nào giảm thiểu nguy cơ SQL Injection.
Mô hình tham số hóa hiện tại chỉ thực hiện được trên các câu lệnh DML (select, insert, replace, update), create table, chứ các dạng câu lệnh khác vẫn chưa được hỗ trợ.
a. Tham số hóa truy vấn trong PHP
Một prepared query thường có dạng như sau:
SELECT * FROM tbl_name WHERE col_name = ?
Dấu ? được gọi là biến giữ chỗ (placeholder). Khi thực thi, ta cần cung cấp giá trị thay thế cho dấu ?.
Bản thân MySQL cũng hỗ trợ hàm PREPARE để sinh các truy vấn tham số hóa. Ví dụ với truy vấn đơn giản sau:
PREPARE class FROM "SELECT * FROM class WHERE class_name=?";
Khi thực thi:
SELECT * FROM ? WHERE username = 'nam' SELECT ? FROM students WHERE studentid = 21 SELECT * FROM students WHERE grade LIKE
SET @test_class = "11B";
EXECUTE class USING @test_class;
Xét trường hợp PHP sử dụng sqli để kết nối tới MySQL, ta có thể sử dụng cả hai hình thức tham số hóa (kiểu hướng đối tượng và kiểu thủ tục) như sau:
/*---========---========---
Source from: http://www.php.net/manual/en/mysqli.prepare.php OOP – style /*---========---========---
<?php $mysqli = new mysqli("localhost", "my_user", "my_password", "my_demo");
$city = "Amersfoort";
/* create a prepared statement */
if ($stmt = $mysqli->prepare(" SELECT grade FROM subject WHERE Name=?"))
{
/* bind parameters for markers */
$stmt->bind_param("s", $subject; /* execute query */
$stmt->execute();
/* bind result variables */
$stmt->bind_result($grade); /* fetch value */
$stmt->fetch();
/*---========---========--- Procedural style */
/*---========---========--- <?php
$link = mysqli_connect("localhost",
"my_user", "my_password", "my_demo"); …
$city = "Amersfoort";
/* create a prepared statement */ if ($stmt = mysqli_prepare($link,
"SELECT grade FROM subject WHERE Name=?")) {
/* bind parameters for markers */
mysqli_stmt_bind_param($stmt, "s", $subject); /* execute query */
mysqli_stmt_execute($stmt); /* bind result variables */
mysqli_stmt_bind_result($stmt, $grade); /* fetch value */
mysqli_stmt_fetch($stmt);
printf("%s is in district %s\n", $subject, $grade); /* close statement */ mysqli_stmt_close($stmt); } /* close connection */ mysqli_close($link); ?>