3.4 · SQL مع نود : بوستغريسكيول وماي.سيك.يو.إل وبريزما

المستوى 3 · إكسبريس وقواعد البيانات (Express & databases)

3.4SQL مع نود : بوستغريسكيول وماي.سيك.يو.إل وبريزما

الهدف: معرفة التخزين الدائم بقاعدة علائقية (PostgreSQL/MySQL) عبر ORM عصري (بريزما)، مع كتابة استعلامات آمنة — استكمالا لإتقانكم عائلتي القواعد.
الوقت المقدّر: 11 دقيقة · قراءة ذاتية · إذا كان لديك 5 دقائق فقط: اقرأ «الأساسي في 30 ثانية» + المخطط.

الأساسي في 30 ثانية

  • العلائقي يهيكل : جداول وأسطر ومفاتيح أجنبية (PostgreSQL/MySQL)، ومخطط صارم ومعاملات ACID للسلامة.
  • يُكتَب SQL أو يُولَّد : ‏SELECT/INSERT/UPDATE/DELETE + JOIN‏ خاما مُعامَلا، أو طرق ORM (بريزما/Sequelize) تولد SQL آمنا.
  • الأمن غير قابل للتفاوض : لا دمج أبدا لبيانات المستعمل (حقن SQL) — استعلامات مُعامَلة أو ORM + فهم SQL الكامن.

حالة مصغرة متسلسلة — ساليم يُفوتر بـ SQL دون ثغرة

ساليم، مطور مبتدئ في الجزائر، عليه الفوترة : زبناء وطلبات وأسطر مرتبطة، ومجاميع يجب ضمانها. لم تعد NoSQL المرنة تكفي. ينمذج ثلاثة جداول مرتبطة بمفاتيح أجنبية (PostgreSQL)، ويكتب أول استعلامات SELECT/JOIN مُعامَلة، ثم يمر إلى بريزما : مخطط تصريحي schema.prisma، وترحيل يُصدِر النسخ، وعميل مُنمَّط ‏prisma.commande.create()‏ و findMany(). وعندما يحتوي حقل بحث على علامة تنصيص مفخخة، يحيدها التعامل : لا حقن.

آخر حلقة من خيط ساليم — من إكسبريس إلى عائلتي القواعد : التخزين الدائم الكامل.

1. النموذج العلائقي و SQL

تنظم عائلة SQL / العلائقية (خصوصا PostgreSQL، القوي والمفتوح، و MySQL/MariaDB) البيانات في جداول (أعمدة مُنمَّطة) و أسطر (تسجيلات) و علاقات رسمية بـ مفاتيح أجنبية (طلب يحيل على زبون). ولغة SQL تستعلم : SELECT (قراءة) و INSERT (إنشاء) و UPDATE و DELETE و JOIN (جمع جداول مرتبطة). وضمانات قوية : مخطط صارم و معاملات ACID للاتساق — مثالية للبيانات المهيكلة والحرجة.

ومن نود، مستويان : المشغل الخام (مثلا pg لبوستغريسكيول) حيث نكتب SQL في سلاسل — مع وجوب استعلامات مُعامَلة ($1 و $2…) لأن دمج مدخلات المستعمل يفتح حقن SQL (injection)، ثغرة حرجة. أو ORM يولد SQL مكانكم.

2. بريزما : المخطط والترحيلات والعميل المُنمَّط

يربط ORM (مرابط كائني-علائقي) الجداول ↔ كائنات JS : نعالج ‏prisma.client.create({ data })‏ و ‏findMany({ where })‏ بدل سلاسل SQL — أوضح وأنتج ومحمي من الحقن بالتعامل التلقائي. الشائعة : بريزما (Prisma) (عصري ومحبوب جدا) و Sequelize (قديم ومُجرَّب).

تتميز بريزما (Prisma) بـمخططها التصريحي (ملف schema.prisma يصف النماذج والعلاقات)، وترحيلاتها (إصدار تطور المخطط) وعميلها المولَّد والمُنمَّط (إكمال تلقائي وأمن الأنواع — ممتاز مع TypeScript، القسم 5-1). موصى بها لمعظم التطبيقات ؛ ونبقي SQL الخام للاستعلامات الدقيقة جدا. ومنعكس ساليم : فهم SQL المولَّد (تحميل العلاقات بكفاءة وتفادي N+1) بدل معاملة ORM صندوقا أسود.

خطأ شائع في الفهم: « مع ORM، لا فائدة من تعلم SQL، ودمج مدخل في الاستعلام يُسعف ». لا. دون أسس SQL (الربط وتحميل العلاقات)، ينتج ORM استعلامات غير فعالة (N+1) غير مفهومة. ودمج بيانات مستعمل، حتى « للاختبار فقط »، يفتح حقن SQL قابلا للاستغلال : التعامل دائما، دون استثناء.
‏SQL‏ مع نود : مستويان من SQL المباشر إلى العميل المُنمَّط علائقيجداول وأسطر ومفاتيح أجنبية+مشغل خام‏SQL‏ مُعامَل، ولا دمج أبدا+‏ORM‏ بريزمامخطط وترحيلات وعميل مُنمَّط يحمي ORM من الحقن ؛ ويبقى SQL واجب الفهم.
من SQL المباشر إلى العميل المُنمَّط
نص المخطط (SEO / قارئات الشاشة / الترجمة): 1) العلائقي : يربط ساليم الزبناء والطلبات والأسطر بمفاتيح أجنبية. 2) المشغل الخام : تمر SELECT/JOIN خاصته في استعلامات مُعامَلة. 3) ‏ORM‏ : تولد بريزما عميلا مُنمَّطا من schema.prisma مع ترحيلات. الدرس : إنتاجية ORM دون هجر SQL.

🔎 مثال ملموس — بريزما : CRUD مُنمَّط وآمن

ينشئ ساليم الزبناء ويسردهم دون كتابة SQL.

// يعلن schema.prisma عن Client و Commande المرتبطين (1-N)
const nouveau = await prisma.client.create({
  data: { nom: 'Salim', email: 'salim@exemple-fictif.test' }
});
const actifs = await prisma.client.findMany({
  where: { actif: true }
});
// المعادل بالمحرك الخام الآمن (مُعامَل، pg) :
// await pool.query('SELECT * FROM clients WHERE email = $1', [emailSaisi]);

القراءة : كائنات وطرق جهة بريزما، و $1 مُعامَل جهة الخام.

الدرس : الطريقان يحيدان الحقن ؛ والدمج أبدا.

مفردات القسم

‏SQL‏ / علائقي
قواعد في جداول وأسطر ومفاتيح أجنبية (PostgreSQL و MySQL) ؛ مخطط صارم ومعاملات ACID.

مثال بسيط: زبناء ساليم وطلباته وأسطره المرتبطة.

ما ليس كذلك: مستندات مرنة دون مخطط.

رد فعل: اختياره للبيانات المرتبطة والحرجة.

‏SQL‏ (لغة)
‏SELECT‏ (قراءة) و INSERT (إنشاء) و UPDATE و DELETE و JOIN (جمع جداول مرتبطة).

مثال بسيط: ‏SELECT‏ مع JOIN طلبات-زبناء عند ساليم.

ما ليس كذلك: نداءات طرق ORM.

رد فعل: معرفة قراءة SELECT/JOIN حتى مع ORM.

حقن SQL
ثغرة حرجة : مدخل مدمج يصبح كودا منفذا ؛ وتُصَد بالتعامل.

مثال بسيط: علامة تنصيص مفخخة حيدها $1.

ما ليس كذلك: مجرد خطأ عرض دون خطورة.

رد فعل: لا دمج أبدا، والتعامل دائما.

‏ORM‏ (بريزما و Sequelize)
يربط الجداول ↔ كائنات JS ويولد SQL : طرق مقروءة وآمنة ومنتجة.

مثال بسيط: ‏prisma.client.findMany({ where })‏ عند ساليم.

ما ليس كذلك: ‏SQL‏ خام مدمج باليد.

رد فعل: تفضيل ORM لـ CRUD الجاري.

بريزما (عصرية)
‏ORM‏ بمخطط تصريحي (schema.prisma) وترحيلات مُصدَرة وعميل مولَّد مُنمَّط.

مثال بسيط: الترحيل الذي يضيف جدول الأسطر.

ما ليس كذلك: مشغل خام دون نموذج ولا نمط.

رد فعل: إصدار كل تطور بترحيل.

في التطبيق — التخزين الدائم بقاعدة SQL و ORM

  1. افهموا النموذج العلائقي : جداول وأعمدة مُنمَّطة وأسطر وعلاقات بمفاتيح أجنبية ؛ وعمليات SQL الأساسية (SELECT و INSERT و UPDATE و DELETE و JOIN).
  2. احفظوا وجوب الأمن : لا تدمجوا أبدا بيانات مستعمل في SQL (الحقن) — استعلامات مُعامَلة أو ORM.
  3. اكتشفوا ORM عصريا : عرفوا مخططا (بريزما : schema.prisma) وأنجزوا CRUD بطرق (‏prisma.user.create/findMany/update/delete‏).
  4. استكشفوا ترحيلات بريزما (إصدار تطور المخطط) وفائدة العميل المُنمَّط (إكمال تلقائي وأمن الأنواع مع TypeScript).
تعرفون التخزين الدائم بقاعدة علائقية (PostgreSQL/MySQL) عبر ORM عصري (بريزما)، مع كتابة استعلامات آمنة — استكمالا لإتقانكم عائلتي القواعد.

نص جاهز للقول — عرض SQL الآمن (30 ثانية)

« الفوترة في PostgreSQL : جداول زبناء وطلبات وأسطر مرتبطة بمفاتيح أجنبية. يمر CRUD ببريزما، مخطط تصريحي إضافة إلى ترحيلات، وعميل مُنمَّط. وبقية SQL الخام مُعامَلة بـ $1، ولا دمج أبدا : مُختبَر بمدخل مفخخ، والحقن مُحايَد. »

يُقال في مراجعة الأمن ؛ ويُعرَض المخطط واستعلام مُعامَل.

نموذج نسخ-لصق — بريزما + استعلام مُعامَل

// (مقتطف وهمي) schema.prisma :
// model Client { id Int @id @default(autoincrement())
//   nom String
//   email String @unique
//   commandes Commande[] }
async function main() {
  const nouveau = await prisma.client.create({
    data: { nom: 'Salim', email: 'salim@exemple-fictif.test' }
  });
  const liste = await prisma.client.findMany({ where: { actif: true } });
  await prisma.client.update({
    where: { email: 'salim@exemple-fictif.test' },
    data: { actif: false }
  });
  // تذكير بالخام الآمن (pg) — لا دمج أبدا :
  // await pool.query('SELECT * FROM clients WHERE email = $1', [emailSaisi]);
}
main().catch(console.error);

مستقل

الفوترة في PostgreSQL + بريزما : ثلاثة جداول مرتبطة و CRUD مُنمَّط تكفي.

مقاولة صغيرة في الجزائر

يُصدِر ساليم كل إضافة عمود بترحيل يُراجَع قبل النشر.

فريق منتج

فرض العميل المُنمَّط المشترك لاستعلامات متسقة بين الفرق.

مبتدئ

هذا الأسبوع : نموذج بريزما واحد و create واحد و findMany واحد مع where.

حذر: البيانات ووصول SQL : اعملوا على قاعدة محلية أو اختبار ببيانات وهمية (رسائل بـ @exemple-fictif.test)، ولا تلصقوا أبدا كلمة سر ولا سلسلة اتصال حقيقية في الكود أو اللقطات، وامنحوا كل دور أدنى الحقوق. وكل مدخل مستعمل يذهب في معامل ($1 و ORM)، ولا يُدمَج أبدا. وعند الشك — سر مكشوف أو استعلام مدمج — توقفوا وطهروا السر وجددوه قبل المواصلة.

✓ ممارسات جيدة

  • استعمال ORM عصري (بريزما) للإنتاجية والأمن.
  • استعلامات مُعامَلة دائما (ولا دمج أبدا) ضد حقن SQL.
  • فهم SQL الكامن وتحميل العلاقات بكفاءة (تفادي N+1).

✗ أخطاء شائعة

  • دمج بيانات مستعمل في استعلام SQL (حقن حرج).
  • معاملة ORM صندوقا أسود (استعلامات غير فعالة و N+1).
  • تجاهل أسس SQL بالاتكال كليا على ORM.

النقاط الأساسية

  • ‏SQL‏ / العلائقي (PostgreSQL و MySQL) : بيانات في جداول/أسطر بعلاقات عبر مفاتيح أجنبية ؛ وضمانات قوية (ACID).
  • لغة SQL : ‏SELECT/INSERT/UPDATE/DELETE + JOIN‏. أمن حرج : لا دمج أبدا لبيانات المستعمل (حقن SQL).
  • ‏ORM‏ (بريزما و Sequelize) يربط الجداول ↔ الكائنات ويولد SQL : مقروء وآمن ضد الحقن ومنتج.
  • بريزما : مخطط تصريحي + ترحيلات + عميل مُنمَّط. إتقان SQL ‏+ NoSQL‏ = عدة تخزين دائم كاملة.

تحدي 48 ساعة — طبّق غدا

أعلنوا نموذج بريزما واحدا وأنجزوا create ‏+ findMany‏، ثم أعيدوا كتابة SELECT‏ مُعامَلة $1.

قائمة الخروج من القسم
  • أذكر الجداول والمفاتيح الأجنبية و ACID.
  • الـ SQL الخام عندي مُعامَل، ولا دمج أبدا.
  • الـ CRUD بريزما عندي يمر بمخطط + ترحيل.
تقييم ذاتي 1-5 : هل كل استعلاماتي الخام مُعامَلة ؟هل أعرف شرح SQL المولَّد من ORM خاصتي ؟

أسئلة شائعة

مشغل SQL خام أو ORM (بريزما/Sequelize) : ماذا نختار ؟

لمعظم التطبيقات، ORM : إنتاجية (‏prisma.user.create()‏ موجز) وأمن (تعامل تلقائي ضد الحقن) ومقروئية وعلاقات بسيطة. ويحتفظ المشغل الخام (pg) بمكانه لأجل الضبط الدقيق والاستعلامات الدقيقة. يجمع ساليم : ‏ORM‏ يوميا، و SQL مُعامَل لتقارير JOIN المعقدة.

ما هو حقن SQL وكيف نحمي منه ؟

فمدخل مستعمل مدمج في SQL قد يصبح كودا منفذا (تجاوز مصادقة أو قراءة بيانات أو تدميرها). مثال الخطر : ' OR '1'='1 مدسوس في بريد. الحماية : استعلامات مُعامَلة (مواضع $1 تفصل الكود عن البيانات) و ORM يعامل افتراضيا. ولا دمج أبدا، حتى في الاختبار — فهذه معرفة أمنية أساسية.

تحقّق من فهمك

أي ممارسة تحمي من حقن SQL في نود ؟

موارد إضافية (اختياري، للتعمّق أكثر)

اختبار المستوى 3أسئلة جديدة وأصعب للتحقق من مكتسباتك