إعداد البيانات في MySQL

Ali Majrashiمنذ 7 سنوات

جمل الإعداد Prepared statements هي ميزه تسمح لك بتنفيذ جمل SQL سواء كانت متشابهة او مختلفة بشكل متكرر ولكن بأداء و كفاءة عالية.

جمل الإعداد Prepared statements هي حماية ممتازة ضد هجمات SQL injections.

طريقة عملها:

  • نقوم باعداد جملة SQL باستخدام prepare ليكون لدينا قالب SQL statement template يتم إرسال هذا القالب لقاعدة البيانات ولكن بدون مدخلات Parameters حيث اننا نستبدل هذه المدخلات برموز تدل عليها مثال :
    
    INSERT INTO MyGuests VALUES(?, ?, ?)
  • قاعدة البيانات سوف تستقبل هذا القالب الذي قمت بإعداده ومعالجته ، و تنفيذ بعض العمليات عليه لتحسين جملة SQL ، و يتم تخزين القالب ، و لكن بدون تنفيذ محتواه.
  • التنفيذ: في وقت لاحق في البرنامج نستطيع ربط القيم Values بالمدخلات Parameters ، و سوف تقوم قاعدة البيانات بتنفيذ جملة SQL بالقيم المدخلة ، و في برنامجك تستطيع تكرار تنفيذ جملة SQL ، و لكن بقيم مختلفة عند كل تنفيذ.

عند مقارنة فوائد عمل جمل الإعداد prepared statement ، و تنفيذ جمل SQL  مباشره ممكن تلخيصه بالتالي:

  • جمل الإعداد Prepared statements تقوم بتقليل parsing time ؛ لاننا نقوم بعملية الإعداد مره واحدة فقط ، و عند تنفيذ عدة جمل SQL فان قاعدة البيانات سوف تنفذ الجملة مباشرة باستخدام القالب الذي سبق اعداداه بدون اعدادها وتجهيزها كل مرة.
  • ربط القيم بالمتغيرات يخفف كمية البيانات bandwidth المرسلة للسيرفر حيث انك سوف تقوم بارسال القيم فقط ، و ليس كامل الإستعلام query عند كل تنفيذ.
  • جمل الإعداد Prepared statements هي حماية ممتازة ضد هجمات SQL injections ، حيث انه عند إرسال القيم ، و ربطها بالمدخلات Parameters لاحقا عن طريق بروتوكول مختلف ، ليس من الضروري تجاهل تنفيذ القيم ، حيث انه لن يتم تنفيذ اي أكواد ضمن هذه المدخلات ؛ لتحميك من هجمات الحقن SQL injections ضمن قالب قمت انت بتجهيزه وإعداده بشكل يدوي ليستخدم لتنفيذ الإستعلام لاحقا.

تجهيز البيانات:

سوف نعرض جميع الأمثله لطرق كتابة جمل الإعداد Prepared statements كالتالي:

مثال على MySQLi Object-Oriented:


<?php

$servername = "localhost";
$username = "root";
$password = "root";
$dbname = "new-DB";

// إجراء الإتصال
$conn = new mysqli($servername, $username, $password, $dbname);

// التحقق من الإتصال
if ($conn->connect_error) {
    die("فشل الإتصال: " . $conn->connect_error);
}

// SQL إعداد القالب لجملة
$stmt = $conn->prepare("INSERT INTO users (name, email) VALUES (?, ?)");
// ربط المتغيرات بالقيم في القالب الذي اعددناه
$stmt->bind_param("ss", $name, $email);

// تعريف المتغيرات ثم تنفيذ الإستعلام
$name = "Mohammed";
$email = "[email protected]";
$stmt->execute();

// تعريف المتغيرات ثم تنفيذ الإستعلام
$name = "Abdullah";
$email = "[email protected]";
$stmt->execute();

// تعريف المتغيرات ثم تنفيذ الإستعلام
$name = "Mansour";
$email = "[email protected]";
$stmt->execute();

echo "تم إضافة السجلات بنجاح";

// إغلاق الإتصال
$stmt->close();
$conn->close();

تفصيل عمل الأكواد :

بعد عملية الإتصال بقاعدة البيانات بنجاح استخدمنا prepare لإعداد جملة SQL لنستخدمها كقالب لتخزين قيم جديدة في قاعدة البيانات جملة SQL كانت كالتالي:


INSERT INTO users (name, email) VALUES (?, ?)

لاحظ انه عند بناء جملة SQL استخدمنا علامة الإستفهام ? بدلا من كتابة القيم مباشرة ثم بعدها استخدمنا bind_param لربط هذه الإستفهامات بمتغيرات كالتالي:


$stmt->bind_param("ss", $name, $email);

وظيفة bind_param هي ربط المدخلات بجملة SQL ثم إخبار قاعدة البيانات بنوع كل مدخل ، لاحظ أول مدخل بالدالة عبارة عن "ss" عبارة عن نوع لكل مدخل في هذه الدالة ، وظيفة هذه الأحرف إخبار MySQL بنوع كل مدخل عند عملية ربط كل مدخل بقيمة في جملة SQL ، حيث انه لكل مدخل نعرفه بالدالة يجب ان تقوم بتعريف نوعه بواسطة حرف يدل على النوع بحيث يكون احد هذه الأحرف ولكل حرف معنى محدد

  • integer - i
  • double - d
  • string - s
  • BLOB - b

لنفرض ان لديك جدول آخر يقبل تخزين ٣ قيم لجدول ، و هم عباره عن عمودين من نوع نص ، و عمود من نوع عدد ، سيكون اول مدخل في الدالة عبارة عن "ssi" ، اي اول قيمتين نص وثالث قيمة عبارة عن عدد.

ثم بعد تعريف نوع المدخلات بواسطة اول مدخل في الدالة نعرف المدخلات المراد ربطها بعلامات الإستفهام حيث يجب ان تكون بنفس عدد الإستفهامات المعرفة بجملة SQL.

عند إخبار MySQL بنوع البيانات المتوقع تخزينها هنا نقوم بخفض نسبة خطر حدوث ثغرات SQL injections.

ملاحظة: عندما ترغب بتخزين قيم يقوم بإدخالها المستخدم لقاعدة البيانات دائما تاكد من صحة البيانات Validation وقم بتنقيحها Sanitization من أي أكواد خبيثة.

بعد عملية إعداد البيانات وربط المدخلات بجملة SQL ، نقوم بتعريف المتغيرات ، و تخزين القيم فيها ، ثم استخدام execute لتنفيذ العملية ، و تخزين هذه القيم في قاعدة البيانات ، لو اردت تخزين قيم جديدة كل ماعليك الآن هو تعريف المتغيرات بقيم جديدة ، ثم استخدام execute لعملية التنفيذ فقط.

واخيرا نستخدم close لإنهاء عملية الإعداد وقطع الإتصال بقاعدة البيانات.

عند عمل الكود بالمتصفح بنجاح سيكون الناتج كالتالي:

multi-insert.png

مثال على PDO:


<?php

$servername = "localhost";
$username = "root";
$password = "root";
$dbname = "new-DB";

try {
	    // إجراء الإتصال
	$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
	// تعديل نوع معالج الأخطاء
	$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

	// SQL إعداد القالب لجملة
	$stmt = $conn->prepare("INSERT INTO users (name, email)
	VALUES (:name, :email)");

	// ربط المتغيرات بالقيم في القالب الذي اعددناه
	$stmt->bindParam(':name', $name);
	$stmt->bindParam(':email', $email);

	// تعريف المتغيرات ثم تنفيذ الإستعلام
	$name = "Mohammed";
	$email = "[email protected]";
	$stmt->execute();

	// تعريف المتغيرات ثم تنفيذ الإستعلام
	$name = "Abdullah";
	$email = "[email protected]";
	$stmt->execute();

	// تعريف المتغيرات ثم تنفيذ الإستعلام
	$name = "Mansour";
	$email = "[email protected]";
	$stmt->execute();

	echo "تم إضافة السجلات بنجاح";
}
catch(PDOException $e) {
	echo $sql . "<br>" . $e->getMessage();
}

// إغلاق الإتصال
$conn = null;

لاحظ: في هذا المثال استخدمنا مسميات بدل علامة الإستفهام عند بناء جملة SQL ثم استخدمنا stmt->bindParam$ لربط كل متغير باسم وهي اسهل للقراءة ومعرفة ترتيب البيانات عند الحفظ. 

عند عمل الكود بالمتصفح بنجاح سيكون الناتج كالتالي:

multi-insert.png

التعليقات (0)

لايوجد لديك حساب في عالم البرمجة؟

تحب تنضم لعالم البرمجة؟ وتنشئ عالمك الخاص، تنشر المقالات، الدورات، تشارك المبرمجين وتساعد الآخرين، اشترك الآن بخطوات يسيرة !