NTM Solutions

Facebook Youtube Google+

Thứ Tư, 24 tháng 10, 2018

MYSQL – Bài 07 – Câu truy vấn soạn sẵn


XEM MỤC LỤC CÁC BÀI VIẾT PHP


Các câu truy vấn soạn sẵn rất hữu dụng dùng chống lại nguy cơ SQL injections.

Câu truy vấn soạn sẵn và tham số ràng buộc


Câu truy vấn soạn sẵn là tính năng dùng để thực thi các câu truy vấn SQL giống nhau (hoặc tương tự) lặp đi lặp lại với hiệu suất cao.

Câu truy vấn soạn sẵn về cơ bản hoạt động như sau:

  1. Chuẩn bị: 01 khuôn mẫu truy vấn SQL được tạo và gửi đến cơ sở dữ liệu. Các giá trị bất kỳ không xác định rõ được gọi là tham số (với ký tự đại diện là dấu "?"). Ví dụ: INSERT INTO MyGuests VALUES(?, ?, ?)
  2. Cơ sở dữ liệu phân tích , biên dịch, và thực hiện tối ưu hoá truy vấn  dựa trên câu truy vấn SQL mẫu, và lưu kết quả nhưng chưa thực thi nó.
  3. Thực thi: 01 khoảng thời gian sau đó, ứng dụng gắn các giá trị vào các tham số, và cơ sở dữ liệu thực thi các câu lệnh. Lúc này ứng dụng có thể thực thi câu lệnh bao nhiêu lần mà nó muốn với các giá trị khác nhau.

So với việc thực thi các câu lệnh truy vấn SQL trực tiếp, các câu lệnh soạn sẵn có 03 ưu điểm chính sau:

  • Câu lệnh soạn sẵn rút ngắn thời gian phân tích khi chuẩn bị để câu truy vấn được thực hiện chỉ 01 lần (mặc dù câu lệnh được thực thi nhiều lần)
  • Việc truyền tham số giúp tối thiểu hóa băng thông đến máy chủ khi bạn chỉ cần gửi tham số mỗi lần kết nối thay vì nguyên cả câu truy vấn.
  • Câu truy vấn soạn sẵn rất hữu dụng để chống SQL injections, do các giá trị tham số được truyền đi sau sẽ sử dụng 01 giao thức khác , không cần truyền đầy đủ gói. Nếu câu lệnh truy vấn khuôn mẫu gốc không bị lộ ra khi truyền đi, SQL injection không thể có. 

Câu truy vấn soạn sẵn trong MySQLi


Ví dụ sau sử dụng các câu truy vấn soạn sẵn và các tham số truyền vào với MySQLi:

Ví dụ (MySQLi truy vấn soạn sẵn)


<?php
$servername = "localhost";
$username = 
"root";
$password = 
"";
$dbname = 
"myDB";

// Tạo kết nối
$conn = new mysqli($servername, $username, $password, $dbname);

// Kiểm tra kết nối
if ($conn->connect_error) {
    
die("Kết nối thất bại: " . $conn->connect_error);
}

// prepare and bind
$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)");
$stmt->bind_param(
"sss", $firstname, $lastname, $email);

// thiết lập tham số và thực thi
$firstname = "Nguyễn";
$lastname = 
"Du";
$email = 
"nguyendu@example.com";
$stmt->execute();

$firstname = 
"Nguyễn";
$lastname = 
"Khuyến";
$email = 
"nguyenkhuyen@example.com";
$stmt->execute();

$firstname = 
"Trần Hưng";
$lastname = 
"Đạo";
$email = 
"tranhungdao@example.com";
$stmt->execute();

echo "Thêm mới các bản ghi thành công!";

$stmt->close();
$conn->close();
?>



Giải thích các dòng mã ví dụ trên như sau:

"INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)"

Trong các câu truy vấn SQL, ta chèn dấu hỏi (?) nơi chúng ta muốn để giá trị là 01 số nguyên, chuỗi, số thực double hoặc blob.

Sau đó, ta nhìn vào hàm bind_param()

$stmt->bind_param("sss", $firstname, $lastname, $email);

Hàm này truyền tham số vào câu truy vấn SQL và nói với cơ sở dữ liệu đây là các tham số. Cú pháp "sss" liệt kê các loại dữ liệu của tham số . Chữ s báo cho mysql rằng tham số này là 01 chuỗi.

Tham số có thể là 01 trong 04 dạng sau:

  • i - integer
  • d - double
  • s - string
  • b – BLOB ()

BLOB: dùng cho dữ liệu lớn ở dạng nhị phân (binary large object) không có cấu trúc như tập tin ảnh, text, phim.

Dữ liệu của chúng ta bắt buộc phải là 01 trong các dạng trên.

Việc báo cho mysql kiểu dữ liệu mà bạn mong muốn giúp giảm thiểu nguy cơ SQL injections.

Ghi chú: nếu chúng ta muốn chèn bất kỳ dữ liệu nào từ bên ngoài (Ví dụ: từ người dùng nhập vào) , nhất thiết phải “làm sạch” và kiểm tra nó trước.

Câu truy vấn soạn sẵn trong PDO


Ví dụ sau sử dụng câu truy vấn soạn sẵn và các tham số truyền vào với PDO:

Ví dụ (PDO truy vấn soạn sẵn)


<?php
$servername = "localhost";
$username = 
"root";
$password = 
"";
$dbname = 
"myDBPDO";

try {
    $conn = 
new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
    
// thiết lập PDO chế độ xử lý lỗi bằng ngoại lệ
    $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    
// thiết lập câu truy vấn sql và truyền tham số
    $stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email)
    VALUES (:firstname, :lastname, :email)"
);
    $stmt->bindParam(
':firstname', $firstname);
    $stmt->bindParam(
':lastname', $lastname);
    $stmt->bindParam(
':email', $email);

    
// chèn 01 dòng
    $firstname = "Nguyễn";
    $lastname = 
"Du";
    $email = 
"nguyendu@example.com";
    $stmt->execute();

    
// chèn thêm dòng khác
    $firstname = "Nguyễn";
    $lastname = 
"Khuyến";
    $email = 
"nguyenkhuyen@example.com";
    $stmt->execute();

    
// chèn thêm dòng khác
    $firstname = "Trần Hưng";
    $lastname = 
"Đạo";
    $email = 
"tranhungdao@example.com";
    $stmt->execute();

    
echo "Thêm mới các bản ghi thành công!";
    }
catch(PDOException $e)
    {
     
echo "Lỗi: " . $e->getMessage();
    }
 $conn = null;
?>


Ghi chú: các bạn nên chèn thêm đoạn mã xử lý unicode như trong các bài trước để hiển thị Tiếng Việt chính xác.

Nếu vẫn chưa rõ các bạn xem them video clip sau:



XEM MỤC LỤC CÁC BÀI VIẾT PHP


By #tiensim
Nguồn: sưu tầm