انواع داده: راهنمای کامل انتخاب نوع درست
در درس قبل، بدون توضیح زیاد از INT و NVARCHAR استفاده کردیم. وقت آن رسیده که کامل بفهمیم چرا نوع دادهی هر ستون اینقدر مهم است. انتخاب درست نوع داده فقط یک جزئیات فنی نیست — مستقیم روی سه چیز اثر میگذارد: فضای ذخیرهسازی (چقدر حجم دیسک مصرف میشود)، درستی داده (جلوگیری از ورود مقادیر نامعتبر) و سرعت (پرسوجوها و ایندکسها روی انواع کوچکتر سریعتر کار میکنند). این درس طولانیترین درس این فصل است، چون مرجعی است که در تمام درسهای بعدی به آن برمیگردیم.
۱. انواع عددی (Numeric Types)
SQL Server دو خانوادهی عدد دارد: دقیق (Exact) که همیشه مقدار را بدون هیچ گرد کردنی نگه میدارند، و تقریبی (Approximate) که برای محاسبات علمی مناسباند اما ممکن است کمی گرد شوند.
اعداد صحیح
| نوع | بازهی مقدار | حجم ذخیرهسازی |
|---|---|---|
| TINYINT | 0 تا 255 | 1 بایت |
| SMALLINT | ۳۲٬۷۶۸- تا ۳۲٬۷۶۷ | 2 بایت |
| INT | حدود ۲.۱ میلیارد- تا ۲.۱ میلیارد+ | 4 بایت |
| BIGINT | اعداد بسیار بزرگ (تریلیونها) | 8 بایت |
TINYINT بهتر از INT است — هم فضای کمتری میگیرد، هم پرسوجو و ایندکس روی آن سریعتر است.اعداد اعشاری دقیق
برای مبالغ مالی یا هر عددی که گرد شدنش قابل قبول نیست، از DECIMAL(p, s) استفاده میشود؛ p (Precision) تعداد کل رقمها و s (Scale) تعداد رقمهای بعد از اعشار را مشخص میکند:
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 | نسخهی قدیمیتر و کمدقتتر؛ فقط برای سازگاری با سیستمهای قدیمی نگه داشته شده |
۴. مقدار درست/نادرست (BIT)
برای مقادیری که فقط دو حالت دارند (مثل «فعال/غیرفعال» یا «تحویل شده/نشده»)، از BIT استفاده میشود که فقط سه مقدار میپذیرد: 0 (نادرست)، 1 (درست) یا NULL (نامشخص).
IsActive BIT DEFAULT 1 -- پیشفرض: فعال
۵. سایر انواع مهم
| نوع | کاربرد |
|---|---|
| VARBINARY(MAX) | ذخیرهی فایلهای باینری مثل تصویر یا PDF مستقیم در پایگاهداده |
| UNIQUEIDENTIFIER | یک شناسهی یکتای جهانی (GUID)، مفید وقتی چند سیستم مختلف همزمان داده تولید میکنند |
| XML | ذخیره و پرسوجو گرفتن مستقیم روی دادههای ساختاریافتهی XML |
تبدیل نوع داده (CAST و CONVERT)
گاهی لازم است مقداری از یک نوع را به نوع دیگری تبدیل کنیم — مثلاً یک عدد را برای نمایش، به متن تبدیل کنیم:
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، نوع واقعی هرکدام از مقادیر ذخیرهشده را بررسی میکنیم:
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 در همین سایت آشنا شدی.