خانه/ مبانی پایگاه داده/ انواع داده

انواع داده: راهنمای کامل انتخاب نوع درست

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

در درس قبل، بدون توضیح زیاد از INT و NVARCHAR استفاده کردیم. وقت آن رسیده که کامل بفهمیم چرا نوع داده‌ی هر ستون این‌قدر مهم است. انتخاب درست نوع داده فقط یک جزئیات فنی نیست — مستقیم روی سه چیز اثر می‌گذارد: فضای ذخیره‌سازی (چقدر حجم دیسک مصرف می‌شود)، درستی داده (جلوگیری از ورود مقادیر نامعتبر) و سرعت (پرس‌وجوها و ایندکس‌ها روی انواع کوچک‌تر سریع‌تر کار می‌کنند). این درس طولانی‌ترین درس این فصل است، چون مرجعی است که در تمام درس‌های بعدی به آن برمی‌گردیم.

۱. انواع عددی (Numeric Types)

SQL Server دو خانواده‌ی عدد دارد: دقیق (Exact) که همیشه مقدار را بدون هیچ گرد کردنی نگه می‌دارند، و تقریبی (Approximate) که برای محاسبات علمی مناسب‌اند اما ممکن است کمی گرد شوند.

اعداد صحیح

نوعبازه‌ی مقدارحجم ذخیره‌سازی
TINYINT0 تا 2551 بایت
SMALLINT۳۲٬۷۶۸- تا ۳۲٬۷۶۷2 بایت
INTحدود ۲.۱ میلیارد- تا ۲.۱ میلیارد+4 بایت
BIGINTاعداد بسیار بزرگ (تریلیون‌ها)8 بایت
قاعده‌ی طلایی: کوچک‌ترین نوعی را انتخاب کن که مطمئنی همیشه کافی است. برای ستون «سن» که هیچ‌وقت از ۱۵۰ بیشتر نمی‌شود، TINYINT بهتر از INT است — هم فضای کمتری می‌گیرد، هم پرس‌وجو و ایندکس روی آن سریع‌تر است.

اعداد اعشاری دقیق

برای مبالغ مالی یا هر عددی که گرد شدنش قابل قبول نیست، از DECIMAL(p, s) استفاده می‌شود؛ p (Precision) تعداد کل رقم‌ها و s (Scale) تعداد رقم‌های بعد از اعشار را مشخص می‌کند:

sql
Price DECIMAL(10, 2)  -- تا 8 رقم صحیح و دقیقاً 2 رقم اعشار، مثل 1234567.89

اعداد اعشاری تقریبی

FLOAT و REAL برای محاسبات علمی سریع طراحی شده‌اند، اما ممکن است مقدار را با خطای بسیار کوچک ذخیره کنند.

هشدار مهم: هرگز از FLOAT یا REAL برای مبالغ پول استفاده نکن. همین خطای گرد‌شدگی کوچک، در محاسبات مالی می‌تواند به تفاوت‌های واقعی و گزارش‌های نادرست منجر شود. برای پول همیشه DECIMAL یا نوع مخصوص MONEY را انتخاب کن.

۲. انواع متنی (Text Types)

نوعتوضیح
CHAR(n)طول ثابت؛ همیشه دقیقاً n نویسه فضا می‌گیرد، حتی اگر متن کوتاه‌تر باشد
VARCHAR(n)طول متغیر تا سقف n نویسه؛ فقط به‌اندازه‌ی متن واقعی فضا مصرف می‌کند
NCHAR(n) / NVARCHAR(n)نسخه‌ی Unicode همان دو نوع بالا؛ برای متن فارسی و هر زبان غیرلاتین ضروری‌اند
NVARCHAR(MAX)برای متن‌های بسیار طولانی (مثل توضیحات یک مقاله)، بدون محدودیت عملی طول

تفاوت CHAR و VARCHAR را با یک مثال ببینیم: اگر ستونی از نوع CHAR(10) باشد و مقدار 'علی' را در آن بریزی، SQL Server آن را تا ۱۰ نویسه با فاصله پر می‌کند. اما همان مقدار در VARCHAR(10) فقط به‌اندازه‌ی همان چند حرف واقعی فضا می‌گیرد. به همین دلیل CHAR معمولاً فقط برای مقادیر با طول همیشه‌ثابت (مثل کد ملی ۱۰ رقمی) مناسب است، و VARCHAR/NVARCHAR انتخاب پیش‌فرض و رایج‌تر برای بقیه‌ی موارد است.

همان‌طور که در درس قبل هم دیدیم: هر جا احتمال دارد متن فارسی ذخیره شود، حتماً از NVARCHAR استفاده کن، نه VARCHAR ساده.

۳. تاریخ و زمان (Date & Time)

نوعتوضیح
DATEفقط تاریخ، بدون زمان — مثل 2024-05-20
TIMEفقط زمان، بدون تاریخ — مثل 14:30:00
DATETIME2تاریخ و زمان با دقت بالا؛ گزینه‌ی توصیه‌شده برای پروژه‌های جدید
DATETIMEنسخه‌ی قدیمی‌تر و کم‌دقت‌تر؛ فقط برای سازگاری با سیستم‌های قدیمی نگه داشته شده
نکته‌ی مهم برای پروژه‌های فارسی: SQL Server تاریخ‌ها را همیشه به تقویم میلادی ذخیره می‌کند؛ هیچ نوع داده‌ای برای تقویم شمسی وجود ندارد. تبدیل بین شمسی و میلادی معمولاً باید در لایه‌ی برنامه (مثلاً در کد C# یا جاوااسکریپت) انجام شود، نه داخل خود پایگاه‌داده.

۴. مقدار درست/نادرست (BIT)

برای مقادیری که فقط دو حالت دارند (مثل «فعال/غیرفعال» یا «تحویل شده/نشده»)، از BIT استفاده می‌شود که فقط سه مقدار می‌پذیرد: 0 (نادرست)، 1 (درست) یا NULL (نامشخص).

sql
IsActive BIT DEFAULT 1  -- پیش‌فرض: فعال

۵. سایر انواع مهم

نوعکاربرد
VARBINARY(MAX)ذخیره‌ی فایل‌های باینری مثل تصویر یا PDF مستقیم در پایگاه‌داده
UNIQUEIDENTIFIERیک شناسه‌ی یکتای جهانی (GUID)، مفید وقتی چند سیستم مختلف هم‌زمان داده تولید می‌کنند
XMLذخیره و پرس‌وجو گرفتن مستقیم روی داده‌های ساختاریافته‌ی XML

تبدیل نوع داده (CAST و CONVERT)

گاهی لازم است مقداری از یک نوع را به نوع دیگری تبدیل کنیم — مثلاً یک عدد را برای نمایش، به متن تبدیل کنیم:

sql
SELECT CAST(Grade AS NVARCHAR(10)) AS GradeText
FROM Students;

CAST استاندارد و قابل‌استفاده در تقریباً همه‌ی DBMSهاست؛ CONVERT مشابه همین کار را انجام می‌دهد اما مخصوص SQL Server است و امکانات بیشتری برای قالب‌بندی تاریخ دارد.

انواع داده در Playground این سایت

این‌جا مهم‌ترین تفاوت مفهومی بین SQL Server و SQLite (موتور Playground) قرار دارد، پس حتماً به آن دقت کن:

  • در SQL Server، نوع داده‌ی هر ستون از لحظه‌ی ساخت جدول برای همیشه قفل می‌شود: اگر ستونی INT تعریف شده باشد، هرگز نمی‌توانی در آن متن دلخواه ذخیره کنی.
  • در SQLite، سیستم نوع بسیار انعطاف‌پذیرتر است و به آن Type Affinity می‌گویند: یک ستون فقط «ترجیح» می‌دهد نوع خاصی ذخیره شود، اما در عمل می‌تواند مقادیر با نوع دیگر را هم بپذیرد.

بیا این تفاوت را عملاً ببینیم. جدول زیر را می‌سازیم و با تابع typeof() مخصوص SQLite، نوع واقعی هرکدام از مقادیر ذخیره‌شده را بررسی می‌کنیم:

ببین SQLite واقعاً چه نوعی ذخیره کرده
دیدی؟ با این‌که هر دو مقدار در یک ستون یکسان (price با نوع NUMERIC) ذخیره شدند، عدد ۱۵۰۰۰۰ (که اعشار ندارد) در عمل با نوع integer ذخیره شد، ولی ۲۵۰۰۰.۵ با نوع real. این دقیقاً همان انعطاف Type Affinity در SQLite است: ستون فقط «ترجیح» می‌دهد عدد باشد، اما نوع دقیق را بر اساس هر مقدار جدا تعیین می‌کند. در SQL Server واقعی، اگر ستونی DECIMAL تعریف شود، هر دو مقدار همیشه دقیقاً با همان یک نوع ذخیره می‌شدند، بدون این تفاوت.

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

  • برای اعداد صحیح، کوچک‌ترین نوعی را انتخاب کن که مطمئناً کافی است (TINYINT تا BIGINT).
  • برای پول همیشه DECIMAL، هرگز FLOAT یا REAL.
  • برای متن فارسی همیشه NVARCHAR، نه VARCHAR.
  • برای تاریخ و زمان در پروژه‌های جدید، DATE/DATETIME2 را به DATETIME ترجیح بده.
  • SQL Server نوع را برای همیشه قفل می‌کند؛ SQLite (پلی‌گراند این سایت) با Type Affinity انعطاف‌پذیرتر عمل می‌کند.

با این درس، فصل ۱ (مبانی پایگاه داده) را کامل تمام کردی! از درس بعدی وارد فصل ۲ (مبانی SQL) می‌شویم و شروع می‌کنیم به نوشتن پرس‌وجوهای واقعی — همان‌جایی که با دستور SELECT در همین سایت آشنا شدی.