خانه/ مدل‌سازی داده (CDM، LDM، PDM)/ گردش کار مدل‌سازی داده

گردش کار مدل‌سازی داده: از صورت مسئله تا CDM، LDM، PDM و اسکریپت SQL

مبتدی ۱۴ دقیقه مطالعه

طراحی پایگاه‌داده یک «کار یک‌مرحله‌ای» نیست؛ یک مسیر مشخص دارد که از صورت مسئله شروع می‌شود و به اسکریپت SQL می‌رسد. در این درس همان مسیر را با یک مثال کامل (نوبت‌دهی یک کلینیک) قدم‌به‌قدم می‌رویم. درس‌های بعدی همین کار را با ابزارهای واقعی (Power Designer و ابزارهای رایگان) انجام می‌دهند.

پنج مرحله‌ی مدل‌سازی

مرحلهخروجیسؤالی که جواب می‌دهد
۱. تحلیل نیازمندی‌هامتن صورت مسئله + قواعد کسب‌وکارسیستم چه اطلاعاتی را نگه می‌دارد و چه قواعدی دارد؟
۲. مدل مفهومی (CDM)موجودیت‌ها، صفت‌ها، ارتباط‌ها، کاردینالیتیچه چیزهایی داریم و چه ارتباطی دارند؟
۳. مدل منطقی (LDM)جدول‌ها، کلید اصلی و خارجی، جدول‌های واسطاین مفاهیم چطور در مدل رابطه‌ای نمایش داده می‌شوند؟
۴. مدل فیزیکی (PDM)نوع داده، قیدها، ایندکس‌ها برای یک DBMSدر SQL Server (یا هر DBMS هدف) دقیقاً چطور ساخته شود؟
۵. تولید و بازبینیاسکریپت SQL + داده‌ی نمونه + پرس‌وجوهای تستآیا مدل همه‌ی نیازها را جواب می‌دهد؟

مرحله ۱: تحلیل نیازمندی‌ها

«کلینیک بیماران را با نام، تاریخ تولد و تلفن ثبت می‌کند. هر پزشک نام و تخصص دارد. بیمار می‌تواند برای یک پزشک نوبت بگیرد؛ هر نوبت تاریخ و ساعت و وضعیت (ثبت‌شده، انجام‌شده، لغو) دارد. یک بیمار می‌تواند چند نوبت داشته باشد و یک پزشک در روز چند نوبت دارد، اما یک پزشک در یک ساعت فقط یک نوبت دارد.»

اسم‌ها را بردار: بیمار، پزشک، نوبت (موجودیت‌ها) و صفت‌هایی مثل نام، تخصص، تاریخ. فعل‌ها: «نوبت می‌گیرد»، «ویزیت می‌کند» (ارتباط‌ها). جمله‌ی آخر یک قاعده‌ی کسب‌وکار است که بعداً به قید تبدیل می‌شود.

مرحله ۲: مدل مفهومی (CDM)

فقط موجودیت‌ها، صفت‌ها، شناسه‌ها و ارتباط‌ها را می‌کشیم. هنوز هیچ کلید خارجی یا نوع داده‌ای نداریم. روی هر سر ارتباط، کاردینالیتی (min,max) نوشته می‌شود:

0,N1,1books 0,N1,1sees PatientID PatientIdFullNameBirthDatePhone AppointmentID AppointmentIdAppointmentDateStatus DoctorID DoctorIdFullNameSpecialty
CDM کلینیک: هر بیمار صفر یا چند نوبت دارد (0,N) و هر نوبت دقیقاً به یک بیمار و یک پزشک تعلق دارد (1,1).

مرحله ۳: مدل منطقی (LDM)

هر موجودیت جدول می‌شود و برای هر رابطه‌ی یک‌به‌چند، شناسه‌ی سمت «یک» به‌عنوان کلید خارجی به سمت «چند» می‌آید: PatientId و DoctorId به Appointment اضافه می‌شوند. چون هیچ رابطه‌ی چندبه‌چندی نداریم، جدول واسط لازم نیست.

PatientPK PatientIdFullNameBirthDatePhone AppointmentPK AppointmentIdFK PatientIdFK DoctorIdAppointmentDateStatus DoctorPK DoctorIdFullNameSpecialty

مرحله ۴: مدل فیزیکی (PDM)

حالا برای هر ستون یک نوع داده‌ی SQL Server انتخاب می‌کنیم و قیدها و ایندکس‌ها را اضافه می‌کنیم. قاعده‌ی «یک نوبت در هر ساعت برای هر پزشک» همین‌جا به یک ایندکس یکتا تبدیل می‌شود:

PatientPK PatientIdINT IDENTITYFullNameNVARCHAR(100)BirthDateDATEPhoneVARCHAR(20) AppointmentPK AppointmentIdINT IDENTITYFK PatientIdINTFK DoctorIdINTAppointmentDateDATETIME2StatusNVARCHAR(20) DoctorPK DoctorIdINT IDENTITYFullNameNVARCHAR(100)SpecialtyNVARCHAR(50)
sql
CREATE TABLE Patient (
  PatientId INT IDENTITY(1,1) PRIMARY KEY,
  FullName  NVARCHAR(100) NOT NULL,
  BirthDate DATE NULL,
  Phone     VARCHAR(20) NULL
);

CREATE TABLE Doctor (
  DoctorId  INT IDENTITY(1,1) PRIMARY KEY,
  FullName  NVARCHAR(100) NOT NULL,
  Specialty NVARCHAR(50)  NOT NULL
);

CREATE TABLE Appointment (
  AppointmentId   INT IDENTITY(1,1) PRIMARY KEY,
  PatientId       INT NOT NULL REFERENCES Patient(PatientId),
  DoctorId        INT NOT NULL REFERENCES Doctor(DoctorId),
  AppointmentDate DATETIME2 NOT NULL,
  Status          NVARCHAR(20) NOT NULL
    CONSTRAINT CK_Appointment_Status CHECK (Status IN (N'registered', N'done', N'cancelled'))
);

-- قاعده‌ی کسب‌وکار: هر پزشک در هر زمان فقط یک نوبت دارد
CREATE UNIQUE INDEX UX_Appointment_Doctor_Time
  ON Appointment (DoctorId, AppointmentDate);

-- ایندکس برای فهرست نوبت‌های یک بیمار
CREATE INDEX IX_Appointment_Patient ON Appointment (PatientId);

مرحله ۵: بازبینی با داده و پرس‌وجو

مدل وقتی ارزش دارد که پرسش‌های واقعی را جواب بدهد. چند داده‌ی نمونه وارد کن و سؤال‌های کلینیک را بپرس:

sql
-- نوبت‌های امروز یک پزشک
SELECT a.AppointmentDate, p.FullName AS Patient
FROM Appointment a
JOIN Patient p ON p.PatientId = a.PatientId
WHERE a.DoctorId = 1
  AND CAST(a.AppointmentDate AS DATE) = CAST(GETDATE() AS DATE)
ORDER BY a.AppointmentDate;

-- بیمارانی که هیچ نوبتی نداشته‌اند
SELECT p.FullName
FROM Patient p
LEFT JOIN Appointment a ON a.PatientId = p.PatientId
WHERE a.AppointmentId IS NULL;

اگر پرسشی بود که مدل جوابش را نمی‌داد (مثلاً «هر نوبت چه خدماتی داشته؟»)، به مرحله‌ی ۲ برگرد و مدل را اصلاح کن. این رفت‌وبرگشت طبیعی است.

ردیابی نیازمندی تا جدول

نیازمندیCDMLDM / PDM
بیمار نوبت می‌گیردارتباط Patient — Appointment (0,N / 1,1)ستون PatientId (FK) در Appointment
پزشک ویزیت می‌کندارتباط Doctor — Appointmentستون DoctorId (FK) در Appointment
وضعیت نوبت محدود استصفت Statusقید CHECK
یک پزشک در یک زمان یک نوبت داردقاعده‌ی کسب‌وکار (یادداشت)ایندکس یکتای (DoctorId, AppointmentDate)
همین مدل را در طراح تعاملی ER باز کن و بین سه سطح جابه‌جا شو؛ می‌بینی چطور یک مدل در سه شکل نمایش داده می‌شود و اسکریپت SQL خودکار ساخته می‌شود.

در درس بعد، همین مسیر را با Power Designer انجام می‌دهیم.

تمرین‌های خودآزمایی

اول خودت جواب بده، بعد پاسخ را باز کن و مقایسه کن.

۱چرا قاعده‌ی «هر بیمار نمی‌تواند در یک ساعت دو نوبت با یک پزشک داشته باشد» را در CDM نشان نمی‌دهیم و کجا اعمال می‌کنیم؟نمایش پاسخ
پاسخ

این یک قید پیاده‌سازی است و به ساختار جدول‌ها و ایندکس‌ها مربوط می‌شود، نه تحلیل مفهومی. در PDM با یک ایندکس یکتا اعمال می‌شود:

CREATE UNIQUE INDEX UX_Appointment_Doctor_Time
  ON Appointment (DoctorId, AppointmentDate);
۲اگر کلینیک بخواهد برای هر نوبت چند خدمت (ویزیت، آزمایش، ...) ثبت کند، مدل چطور تغییر می‌کند؟نمایش پاسخ
پاسخ

بین «نوبت» و «خدمت» رابطه‌ی چندبه‌چند است. در CDM یک موجودیت Service و رابطه‌ی M:N اضافه می‌شود و در LDM یک جدول واسط AppointmentService با دو کلید خارجی (و ستونی مثل قیمت در زمان ارائه) ساخته می‌شود.