Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> MySQL

กำหนดค่าผลลัพธ์ SQL ให้ตัวแปรจาก Prepared Statement ใน MySQL ด้วย Stored Procedure

การใช้ Prepared Statement ใน Stored Procedure เพื่อกำหนดค่าตัวแปร

ใช้ PREPARE, EXECUTE, DEALLOCATE PREPARE ภายใน Stored Procedure เพื่อสร้าง Dynamic SQL และเก็บผลลัพธ์ใน User Variable (@var)

ตัวอย่าง Stored Procedure แบบ Dynamic

mysql> DELIMITER //
mysql> CREATE PROCEDURE Prepared_Statement_Demo(
    IN nameOfTable VARCHAR(20),
    IN nameOfColumn VARCHAR(20),
    IN idColumnName INT
)
BEGIN
    SET @holdResult = CONCAT('SELECT ', nameOfColumn, ' INTO @value FROM ', nameOfTable, ' WHERE id = ', idColumnName);
    PREPARE st FROM @holdResult;
    EXECUTE st;
    DEALLOCATE PREPARE st;
END //
Query OK, 0 rows affected (0.20 sec)
mysql> DELIMITER ;

การเรียกใช้และตรวจสอบผลลัพธ์

สร้างตารางและข้อมูลทดสอบ:

mysql> CREATE TABLE DemoTable (Id INT, Name VARCHAR(100));
Query OK, 0 rows affected (1.51 sec)

mysql> INSERT INTO DemoTable VALUES (10, 'John'), (11, 'Chris');
Query OK, 2 rows affected

เรียก Procedure:

mysql> CALL Prepared_Statement_Demo('DemoTable', 'Name', 10);
Query OK, 0 rows affected, 2 warnings (0.00 sec)

ตรวจสอบตัวแปร @value:

mysql> SELECT @value;
+--------+
| @value |
+--------+
| John   |
+--------+
1 row in set (0.00 sec)

คำอธิบายขั้นตอน

  1. CONCAT - สร้าง SQL String แบบ Dynamic
  2. PREPARE st FROM @sql - Compile Statement
  3. EXECUTE st - รัน Statement (ผลลัพธ์จะไปอยู่ใน INTO @value)
  4. DEALLOCATE PREPARE st - ปล่อยหน่วยความจำ (สำคัญ! ป้องกัน Memory Leak)

ข้อควรระวังด้านความปลอดภัย (SQL Injection)

  • ตัวอย่างนี้ **อันตราย** หาก Input มาจาก User โดยไม่ Validate/Sanitize
  • ใช้ QUOTE() สำหรับ String: CONCAT('... WHERE name = ', QUOTE(user_input))
  • ใช้ Parameterized Query (Prepared Statement แบบ Parameter) แทน Dynamic SQL ถ้าเป็นไปได้
  • Validate Table/Column Name ให้อยู่ใน Whitelist

Prepared Statement แบบ Parameterized (ปลอดภัยกว่า)

PREPARE stmt FROM 'SELECT name FROM DemoTable WHERE id = ?';
SET @id = 10;
EXECUTE stmt USING @id;
DEALLOCATE PREPARE stmt;