خانه/ طراحی پایگاه‌داده/ انواع داده در طراحی

انواع داده: این‌بار به‌عنوان یک تصمیم طراحی

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

در فصل ۱ فهرست کامل انواع داده‌ی SQL Server را دیدیم — INT، NVARCHAR، DATETIME2 و بقیه. این درس، آن فهرست را تکرار نمی‌کند؛ به‌جایش، حالا که با نرمال‌سازی و روابط آشنا شدی، انتخاب نوع داده را به‌عنوان بخشی از تصمیم طراحی نگاه می‌کنیم — نه فقط یک انتخاب فنی جدا از بقیه.

قانون طلایی: کلید خارجی باید دقیقاً هم‌نوع کلید اصلی باشد

وقتی جدولی مثل enrollments را طراحی می‌کنی، ستون student_id باید دقیقاً همان نوع داده‌ای باشد که students.id دارد — نه فقط «یک نوع نزدیک». بیا ببینیم چرا این‌قدر مهم است:

امتحانش کن — وقتی نوع کلید خارجی با کلید اصلی یکی نیست
نتیجه‌ی نگران‌کننده: هر دو ردیف — یکی با student_id = '1' و دیگری با مقدار عجیب‌تر '01' — با «علی محمدی» تطبیق پیدا کردند! چون SQLite برای مقایسه‌ی متن و عدد، به‌طور خودکار تبدیل نوع انجام می‌دهد (یادت هست از درس انواع داده در فصل ۱؟). این یعنی اگر '01' در واقعیت قرار بود شناسه‌ای متفاوت باشد (مثلاً یک کد پیگیری با صفر ابتدایی معنادار)، این تبدیل خودکار، بی‌سروصدا این تفاوت را نادیده می‌گیرد.

در SQL Server، مقایسه‌ی نوع‌های ناهم‌خوان معمولاً به یک تبدیل ضمنی (Implicit Conversion) منجر می‌شود که هم می‌تواند از استفاده‌ی درست ایندکس روی آن ستون جلوگیری کند (بحث فصل ۱۰)، و هم بسته به ترکیب دقیق نوع‌ها، گاهی اصلاً خطا می‌دهد. راه‌حل ساده است: همیشه نوع کلید خارجی را دقیقاً برابر نوع کلید اصلی تعریف کن.

انتخاب دقت مناسب برای مبالغ، از زمان طراحی

یادت هست در فصل ۱ گفتیم هرگز از FLOAT برای پول استفاده نکن؟ در زمان طراحی، این یعنی باید از همان اول دقت (Scale) درست را هم انتخاب کنی — نه فقط نوع درست:

sql
-- برای تومان/ریال بدون اعشار، معمولاً کافی است:
Price DECIMAL(12, 0)

-- برای ارزهای خارجی که اعشار معنا دارد:
Price DECIMAL(12, 2)

این تصمیم را باید همان لحظه‌ی طراحی جدول بگیری — تغییردادن دقت یک ستون پولی بعد از این‌که میلیون‌ها ردیف داده در آن ثبت شده، بسیار پرهزینه‌تر از تصمیم درست از همان اول است.

نه خیلی تنگ، نه خیلی گشاد

در فصل ۱ دیدیم کوچک‌ترین نوع کافی را انتخاب کنیم (مثلاً TINYINT برای سن). اما این قانون یک طرف قضیه است؛ طرف دیگرش این است که بیش‌ازحد محتاط هم نباش:

  • خیلی تنگ: اگر شناسه‌ی مشتریان را TINYINT (حداکثر ۲۵۵) بگیری، به‌محض رسیدن به مشتری ۲۵۶ام، کل سیستم متوقف می‌شود.
  • خیلی گشاد: اگر همه‌چیز را NVARCHAR(MAX) یا BIGINT بگیری «چون شاید لازم شود»، هم فضای دیسک را بی‌دلیل هدر می‌دهی، هم به خواننده‌ی کد هیچ اطلاعاتی درباره‌ی محدوده‌ی واقعی داده نمی‌دهی.

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

NULL هم یک تصمیم طراحی است

وقتی هر ستون جدید را تعریف می‌کنی، این سوال را از خودت بپرس: «آیا این مقدار می‌تواند مشروع و واقعی نامشخص باشد؟» اگر جواب نه است (مثل نام دانش‌آموز)، آن ستون را NOT NULL تعریف کن — این خودش یک قانون طراحی است که از ورود داده‌ی ناقص، از همان لحظه‌ی ساخت جدول جلوگیری می‌کند، دقیقاً همان چیزی که در درس جدول‌ها (فصل ۱) و درس NULL (فصل ۲) دیدیم.

جمع‌بندی این درس (و کل فصل ۷)

  • نوع کلید خارجی باید دقیقاً با نوع کلید اصلی مرتبطش یکی باشد — عدم تطابق می‌تواند بی‌سروصدا (در SQLite) یا با خطا/کندی (در SQL Server) مشکل‌ساز شود.
  • دقت مناسب برای مبالغ پولی را از همان لحظه‌ی طراحی انتخاب کن، نه بعداً.
  • نه بیش‌ازحد تنگ (ریسک سرریز)، نه بیش‌ازحد گشاد (اتلاف فضا و ابهام) — نوع را متناسب با نیاز واقعی انتخاب کن.
  • NOT NULL گذاشتن روی ستون‌هایی که واقعاً نباید خالی باشند، خودش یک تصمیم طراحی مهم است.

با این درس، فصل ۷ (طراحی پایگاه‌داده) کامل شد! حالا هم می‌دانی چطور SQL بنویسی، هم چطور از اول، یک پایگاه‌داده‌ی درست طراحی کنی. در فصل بعدی، وارد برنامه‌نویسی داخل خودِ SQL Server می‌شویم: Viewها، رویه‌های ذخیره‌شده، توابع و متغیرها.