งบเตรียมจะมีประโยชน์มากกับการฉีด SQL
งบเตรียมและพารามิเตอร์ที่ถูกผูกไว้
งบเตรียมเป็นคุณสมบัติที่ใช้ในการดำเนินการเดียวกัน (or similar) คำสั่ง SQL ซ้ำ ๆ ที่มีประสิทธิภาพสูง
งบเตรียมพื้นทำงานเช่นนี้:
- เตรียม: แม่แบบคำสั่ง SQL จะถูกสร้างขึ้นและถูกส่งตัวไปยังฐานข้อมูล ค่าบางอย่างที่เหลือที่ไม่ได้ระบุเรียกว่าพารามิเตอร์ (labeled "?") ตัวอย่าง: INSERT INTO MyGuests VALUES(?, ?, ?)
- ฐานข้อมูลแยก, รวบรวมและดำเนินการเพิ่มประสิทธิภาพการค้นหาแม่แบบคำสั่ง SQL และเก็บผลที่ได้โดยไม่ต้องรันมัน
- ดำเนินการ: ในเวลาต่อมาแอพลิเคชันผูกค่าพารามิเตอร์และฐานข้อมูลรันคำสั่ง โปรแกรมประยุกต์อาจรันคำสั่งหลายครั้งตามที่มันต้องการที่มีค่าที่แตกต่าง
เมื่อเทียบกับการดำเนินการคำสั่ง SQL โดยตรงงบเตรียมมีสองข้อได้เปรียบหลัก:
- เตรียมงบช่วยลดเวลาในการแยกการจัดทำแบบสอบถามที่มีการทำเพียงครั้งเดียว (although the statement is executed multiple times)
- พารามิเตอร์ผูกพันลดแบนด์วิดธ์ไปยังเซิร์ฟเวอร์ที่คุณต้องการส่งพารามิเตอร์เท่านั้นในแต่ละครั้งและไม่แบบสอบถามทั้งหมด
- งบเตรียมจะมีประโยชน์มากกับการฉีด SQL เพราะค่าพารามิเตอร์ซึ่งจะถูกส่งในภายหลังโดยใช้โปรโตคอลที่แตกต่างกันไม่จำเป็นต้องหนีออกมาได้อย่างถูกต้อง ถ้าแม่แบบคำสั่งเดิมจะไม่ได้มาจากการป้อนข้อมูลภายนอกฉีด SQL ไม่สามารถเกิดขึ้นได้
เตรียมงบใน MySQLi
ตัวอย่างต่อไปนี้ใช้งบเตรียมและพารามิเตอร์ที่ถูกผูกไว้ใน MySQLi:
ตัวอย่าง (MySQLi with Prepared Statements)
<?php
$servername = "localhost";
$username = "username";
$password =
"password";
$dbname =
"myDB";
// Create connection
$conn = new mysqli($servername,
$username, $password, $dbname);
// Check connection
if ($conn->connect_error)
{
die("Connection failed: " . $conn->connect_error);
}
// prepare and bind
$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email)
VALUES (?, ?, ?)");
$stmt->bind_param("sss", $firstname, $lastname,
$email);
// set parameters and execute
$firstname = "John";
$lastname
= "Doe";
$email = "[email protected]";
$stmt->execute();
$firstname
= "Mary";
$lastname = "Moe";
$email = "[email protected]";
$stmt->execute();
$firstname = "Julie";
$lastname = "Dooley";
$email = "[email protected]";
$stmt->execute();
echo "New records created successfully";
$stmt->close();
$conn->close();
?>
สายรหัสที่จะอธิบายจากตัวอย่างข้างต้น:
"INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)"
ใน SQL ของเราเราใส่เครื่องหมายคำถาม (?) ที่เราต้องการเพื่อทดแทนในจำนวนเต็มสตริงมูลค่าคู่หรือหยด
จากนั้นมีลักษณะที่เป็น bind_param() ฟังก์ชั่น:
$stmt->bind_param("sss", $firstname, $lastname, $email);
ฟังก์ชั่นนี้ผูกพารามิเตอร์แบบสอบถาม SQL ฐานข้อมูลและบอกสิ่งที่พารามิเตอร์ที่มี "sss" โต้แย้งแสดงรายการชนิดของข้อมูลที่พารามิเตอร์ ดัชนี S ตัวละครบอก MySQL พารามิเตอร์เป็นสตริง
อาร์กิวเมนต์อาจจะเป็นหนึ่งในสี่ประเภท:
- ฉัน - จำนวนเต็ม
- d - คู่
- s - สตริง
- ข - หยด
เราต้องมีหนึ่งในเหล่านี้สำหรับแต่ละพารามิเตอร์
โดยบอก MySQL สิ่งที่ประเภทของข้อมูลที่จะคาดหวังว่าเราลดความเสี่ยงของการฉีดของ SQL
หมายเหตุ: หากเราต้องการที่จะใส่ข้อมูลใด ๆ จากแหล่งภายนอก (like user input) มันเป็นสิ่งสำคัญมากที่ข้อมูลจะถูกสุขอนามัยและการตรวจสอบ
เตรียมงบใน PDO
ตัวอย่างต่อไปนี้ใช้งบเตรียมและพารามิเตอร์ที่ถูกผูกไว้ใน PDO:
ตัวอย่าง (PDO with Prepared Statements)
<?php
$servername = "localhost";
$username = "username";
$password =
"password";
$dbname =
"myDBPDO";
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname",
$username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE,
PDO::ERRMODE_EXCEPTION);
// prepare sql and bind
parameters
$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);
// insert a row
$firstname =
"John";
$lastname = "Doe";
$email = "[email protected]";
$stmt->execute();
// insert another row
$firstname = "Mary";
$lastname = "Moe";
$email = "[email protected]";
$stmt->execute();
// insert another row
$firstname = "Julie";
$lastname = "Dooley";
$email = "[email protected]";
$stmt->execute();
echo "New records created successfully";
}
catch(PDOException $e)
{
echo "Error: " . $e->getMessage();
}
$conn = null;
?>