آموزش تابع TRY_CONVERT در SQL Server برای تبدیل امن دادهها
آموزش تابع TRY_CONVERT در SQL Server برای تبدیل امن دادهها
مقدمه
در پروژههای واقعی همیشه دادهها تمیز و استاندارد نیستند. ممکن است تاریخ در یک ستون متنی ذخیره شده باشد، بعضی ردیفها عدد معتبر داشته باشند و بعضی شامل حروف یا قالب اشتباه باشند. استفاده مستقیم از CAST یا CONVERT روی چنین دادهای میتواند کل کوئری را با خطای تبدیل متوقف کند. TRY_CONVERT برای این شرایط طراحی شده است.
TRY_CONVERT تلاش میکند مقدار را به نوع مقصد تبدیل کند. اگر تبدیل به دلیل نامعتبر بودن مقدار انجام نشود، به جای متوقف کردن کوئری مقدار NULL برمیگرداند. این رفتار برای پاکسازی داده، وارد کردن فایل، مهاجرت پایگاه داده و اعتبارسنجی اولیه بسیار مفید است. با این حال NULL خروجی باید آگاهانه بررسی شود تا داده خراب پنهان نماند.
تعریف و نحو
TRY_CONVERT ( data_type [ ( length ) ], expression [ , style ] )
پارامترها
- data_type: نوع مقصد مانند int، decimal، date، datetime2 یا nvarchar.
- length: طول نوعهایی مانند varchar و nvarchar.
- expression: مقدار یا ستونی که باید تبدیل شود.
- style: پارامتر اختیاری برای کنترل قالب تبدیل، بهویژه تاریخ و متن.
نوع خروجی
در صورت موفقیت، خروجی از نوع مقصد است. در تبدیل ناموفق معمولی، خروجی NULL میشود. اگر نوع تبدیل ذاتاً مجاز نباشد، ممکن است همچنان خطا ایجاد شود؛ بنابراین TRY_CONVERT تضمین نمیکند هر تبدیل غیرممکنی بدون خطا باشد.
مثال ساده تبدیل متن به عدد
SELECT
TRY_CONVERT(int, '125') AS ValidNumber,
TRY_CONVERT(int, '12A') AS InvalidNumber;
| ValidNumber | InvalidNumber |
| 125 | NULL |
در صورت استفاده از CONVERT برای مقدار 12A، کوئری خطا میداد. TRY_CONVERT اجازه میدهد ردیف نامعتبر شناسایی و جداگانه مدیریت شود.
پیدا کردن دادههای عددی نامعتبر
DECLARE @ImportData TABLE
(
RowID int,
AmountText nvarchar(50)
);
INSERT INTO @ImportData VALUES
(1, N'150000'),
(2, N'125.50'),
(3, N'نامعتبر'),
(4, NULL);
SELECT
RowID,
AmountText
FROM @ImportData
WHERE AmountText IS NOT NULL
AND TRY_CONVERT(decimal(18,2), AmountText) IS NULL;
این کوئری ردیفهایی را نشان میدهد که مقدار دارند اما قابل تبدیل به decimal نیستند. این روش در مرحله Staging فرایند ETL بسیار کاربردی است.
تبدیل امن تاریخ با Style
SELECT
TRY_CONVERT(date, '2026-07-17', 23) AS IsoDate,
TRY_CONVERT(date, '17/07/2026', 103) AS BritishDate,
TRY_CONVERT(date, '31/02/2026', 103) AS InvalidDate;
| IsoDate | BritishDate | InvalidDate |
| 2026-07-17 | 2026-07-17 | NULL |
Style شماره 23 برای قالب yyyy-mm-dd و Style شماره 103 برای dd/mm/yyyy استفاده میشود. بهتر است قالب داده ورودی مشخص باشد و از تبدیلهای وابسته به زبان نشست جلوگیری شود.
پاکسازی و انتقال داده
INSERT INTO dbo.CleanOrders
(
OrderID,
OrderDate,
TotalAmount
)
SELECT
SourceOrderID,
TRY_CONVERT(date, OrderDateText, 23),
TRY_CONVERT(decimal(18,2), AmountText)
FROM dbo.StageOrders
WHERE TRY_CONVERT(date, OrderDateText, 23) IS NOT NULL
AND TRY_CONVERT(decimal(18,2), AmountText) IS NOT NULL;
برای حجم بالا بهتر است تبدیل را یک بار با CROSS APPLY محاسبه کنید تا عبارت تکراری خواناتر شود و موتور امکان استفاده مجدد از نتیجه را داشته باشد.
SELECT
S.SourceOrderID,
C.OrderDateValue,
C.AmountValue
FROM dbo.StageOrders AS S
CROSS APPLY
(
SELECT
TRY_CONVERT(date, S.OrderDateText, 23) AS OrderDateValue,
TRY_CONVERT(decimal(18,2), S.AmountText) AS AmountValue
) AS C
WHERE C.OrderDateValue IS NOT NULL
AND C.AmountValue IS NOT NULL;
مقایسه CAST، CONVERT و TRY_CONVERT
| تابع | Style | رفتار در مقدار نامعتبر | کاربرد |
| CAST | ندارد | خطا | تبدیل استاندارد و ساده |
| CONVERT | دارد | خطا | تبدیل ویژه SQL Server و قالب تاریخ |
| TRY_CONVERT | دارد | اغلب NULL | اعتبارسنجی و داده ناسالم |
مقایسه CAST و CONVERT
CAST از نظر استاندارد SQL قابل حملتر است. CONVERT قابلیت Style دارد و برای قالببندی تاریخ در SQL Server انعطاف بیشتری ایجاد میکند. برای نمایش نهایی تاریخ در رابط کاربری، معمولاً بهتر است قالببندی در لایه برنامه انجام شود.
اشتباهات رایج
- تبدیل تمام دادههای نامعتبر به NULL بدون ثبت خطا یا گزارش ردیفهای خراب.
- استفاده از TRY_CONVERT در WHERE روی ستون بزرگ و انتظار استفاده کامل از ایندکس.
- انتخاب نوع عددی با دقت یا Scale ناکافی.
- نادیده گرفتن جداکننده هزارگان، ممیز و تنظیمات زبان.
- استفاده از نوع varchar برای متن فارسی.
- فرض اینکه هر تبدیل غیرمجاز همیشه NULL میدهد.
نکات کارایی
اعمال TRY_CONVERT روی میلیونها ردیف هزینه CPU دارد. بهترین راه این است که داده از ابتدا با نوع صحیح ذخیره شود. در فرایند Import، جدول Staging متنی را از جدول نهایی جدا کنید و پس از اعتبارسنجی داده را به ستونهای Typed منتقل نمایید. اگر دائماً روی یک ستون متنی تبدیل انجام میدهید، این نشانه مشکل طراحی یا کیفیت داده است.
تابع روی ستون داخل شرط جستجو میتواند مانع Seek شود. در سناریوهای پرتکرار میتوان ستون محاسبهشده، فرایند پاکسازی دورهای یا ستون Typed جدا ایجاد کرد. قبل از ایجاد ایندکس روی ستون محاسبهشده، قطعی بودن عبارت و محدودیتهای SQL Server را بررسی کنید.
مثال واقعی: اعتبارسنجی تاریخ انتشار
DECLARE @PublishedDateText nvarchar(30) = N'2026-07-17';
SELECT
CASE
WHEN TRY_CONVERT(datetime2, @PublishedDateText, 23) IS NULL
THEN N'تاریخ نامعتبر است'
ELSE N'تاریخ معتبر است'
END AS ValidationResult;
این مثال برای فرمهای مدیریتی و مهاجرت محتوا مناسب است، اما اعتبارسنجی اصلی باید علاوه بر قالب، محدودیتهای کسبوکار مانند بازه مجاز تاریخ را نیز بررسی کند.
بهترین روشها
- داده نهایی را با نوع صحیح ذخیره کنید، نه به شکل متن.
- ردیفهای تبدیلنشده را در جدول خطا ثبت کنید.
- نوع مقصد، طول، Precision و Scale را صریح مشخص کنید.
- برای تاریخ از Style مشخص و قالب غیرمبهم استفاده کنید.
- در بارگذاری حجیم، تبدیل را در مرحله Staging انجام دهید.
- میزان NULL تولیدشده را پایش کنید تا خطای داده پنهان نشود.
سؤالات متداول و مصاحبه
تفاوت TRY_CAST و TRY_CONVERT چیست؟
هر دو در تبدیل ناموفق معمولی NULL برمیگردانند، اما TRY_CONVERT پارامتر Style دارد و ویژه SQL Server است.
آیا TRY_CONVERT جایگزین طراحی صحیح نوع داده است؟
خیر. این تابع ابزار پاکسازی و اعتبارسنجی است، نه مجوزی برای ذخیره دائمی عدد و تاریخ در ستون متنی.
چگونه ردیفهای خراب را پیدا کنیم؟
مقدار اصلی را غیر NULL و نتیجه TRY_CONVERT را NULL بررسی کنید.
چکلیست و جمعبندی
- نوع مقصد دقیق انتخاب شده است.
- قالب تاریخ با Style مشخص شده است.
- ردیف نامعتبر گزارش یا ثبت میشود.
- تبدیل روی حجم بزرگ از نظر CPU بررسی شده است.
- داده تمیز به ستون Typed منتقل میشود.
TRY_CONVERT راهی امن برای کار با دادههای نامطمئن در SQL Server است. این تابع از شکست کامل بسیاری از کوئریهای پاکسازی جلوگیری میکند، اما باید همراه با گزارش خطا، نوع داده صحیح و طراحی مناسب فرایند Import استفاده شود.