آموزش تابع TRY_CONVERT در SQL Server با Style تاریخ
مقدمه
تابع TRY_CONVERT یکی از ابزارهای مهم تبدیل داده در Microsoft SQL Server است. تبدیل نوع فقط تغییر ظاهر مقدار نیست؛ نوع مقصد بر مقایسه، دقت محاسبه، مرتبسازی، مصرف حافظه و امکان استفاده از ایندکس اثر میگذارد. در این راهنما از مثال ساده آغاز میکنیم و سپس سناریوهای پاکسازی داده، گزارشگیری، مدیریت NULL و بهینهسازی را بررسی میکنیم.
اگر نوع ستون با معنای واقعی داده هماهنگ باشد، نیاز به تبدیل در Queryها کمتر و طراحی پایدارتر میشود. با این حال در مرزهای سامانه مانند فایل ورودی، API، گزارش متنی و اتصال به نرمافزار قدیمی، استفاده آگاهانه از TRY_CONVERT ضروری است. هر مثال این مقاله کامل، مستقل و دارای خروجی مورد انتظار است تا بتوانید رفتار را در محیط آزمایشی بررسی کنید.
برای دیدن جایگاه این تابع در کنار پنج گزینه دیگر، راهنمای جامع توابع تبدیل داده در SQL Server را نیز مطالعه کنید. آن مقاله یک جدول تصمیم دارد و نشان میدهد چه زمانی تبدیل استاندارد، نسخه امن، Style یا Culture انتخاب مناسبتری است.
تعریف تابع TRY_CONVERT
TRY_CONVERT نسخه مقاوم CONVERT است و همزمان دو قابلیت مهم ارائه میکند: بازگرداندن NULL در شکستهای رایج تبدیل و پذیرش آرگومان style. این ترکیب برای تشخیص تاریخهایی با قالب معلوم، پاکسازی دادههای متنی و جلوگیری از شکست دستهای رکوردها مناسب است.
وجود واژه TRY به این معنی است که بسیاری از شکستهای قالبی به NULL تبدیل میشوند، اما مسئولیت ثبت و تحلیل شکست از بین نمیرود. آرگومان Style باید بخشی از قرارداد ورودی یا خروجی باشد و استفاده از کدهای مبهم بدون توضیح توصیه نمیشود.
نحو یا Syntax
-- Syntax
TRY_CONVERT ( data_type [ ( length ) ], expression [ , style ] )
پارامترها
- data_type: نوع مقصد.
- expression: مقدار یا ستون منبع.
- style: کد اختیاری قالب، بهویژه برای تاریخ و زمان؛ اگر Style با رشته هماهنگ نباشد معمولاً NULL برمیگردد.
نوع خروجی و رفتار خطا
نتیجه از نوع مقصد است و در شکست متداول NULL خواهد بود. تبدیل صریحاً ممنوع، مانند بعضی تبدیلهای عدد به xml، همچنان خطا ایجاد میکند و TRY به معنی نادیده گرفتن همه خطاهای ممکن نیست.
| معیار | راهنمای استفاده |
|---|
| نوع مبدأ | نوع واقعی عبارت و اولویت انواع SQL Server را بررسی کنید. |
| نوع مقصد | طول، precision، scale و دقت زمانی را صریح انتخاب کنید. |
| داده نامعتبر | خروجی NULL را ثبت و از NULL اصلی تفکیک کنید. |
| حجم بالا | از اجرای تابع روی ستون ایندکسشده در Predicate پرهیز کنید. |
چه زمانی از TRY_CONVERT استفاده کنیم؟
این تابع برای تبدیلهایی مناسب است که علاوه بر نوع مقصد، Style مشخص تاریخ، زمان یا باینری اهمیت دارد. اگر داده در اختیار شماست، اصلاح نوع ستون در طراحی پایگاه داده معمولاً بهتر از تکرار تبدیل در همه Queryها خواهد بود.
تبدیل را نزدیک مرزی انجام دهید که داده از متن یا سامانه خارجی وارد مدل استاندارد میشود. مقدار خام را برای حسابرسی حفظ کنید، مقدار تبدیلشده را در نوع درست بنویسید و وضعیت اعتبارسنجی را جدا نگه دارید. این الگو سبب میشود گزارشها سادهتر، ایندکسها مؤثرتر و مسئولیت کیفیت داده شفافتر باشد.
در عملیات مالی، precision و scale را از قبل محاسبه کنید. در متن فارسی nvarchar و پیشوند N را بهکار ببرید. برای تاریخوزمان نیز میان date، datetime2 و datetimeoffset تفاوت بگذارید؛ تبدیل یک زمان محلی به متن، آن را خودکار به UTC تبدیل نمیکند و Offset باید در قرارداد سامانه مشخص باشد.
مثالهای عملی
مثال 1: تبدیل موفق عدد متنی
TRY_CONVERT در تبدیل ساده نوع مقصد را در آرگومان نخست میگیرد. ورودی سالم به int تبدیل میشود و در محاسبات بعدی میتوان از آن مانند یک عدد واقعی استفاده کرد.
SELECT TRY_CONVERT(int, '4096') AS SafeNumber;
نکته کاربردی: برای تبدیلهای بدون Style، TRY_CAST خوانایی استانداردتری دارد؛ سیاست ثابت تیم از ترکیب بیقاعده توابع جلوگیری میکند.
مثال 2: شکست آرام در متن غیرعددی
وجود جداکننده نامعتبر سبب میشود تبدیل به int موفق نباشد. TRY_CONVERT مقدار NULL میدهد و Query را برای پردازش ردیفهای دیگر باز نگه میدارد.
SELECT TRY_CONVERT(int, '4O96') AS SafeNumber;
نکته کاربردی: حرف O و رقم صفر در دادههای OCR زیاد اشتباه میشوند؛ ردیف شکستخورده را برای اصلاح یا بازبینی انسانی ثبت کنید.
مثال 3: اعتبارسنجی تاریخ بریتانیایی با Style 103
با اعلام Style 103 رشته روز/ماه/سال بدون اتکا به SET DATEFORMAT تفسیر میشود. این ویژگی TRY_CONVERT را برای ورودیهایی با قرارداد معلوم بسیار مناسب میکند.
SELECT TRY_CONVERT(date, '19/07/2026', 103) AS ParsedDate;
نکته کاربردی: Style بخشی از قرارداد داده است؛ آن را در یک لایه مشترک یا Procedure مرکزی نگه دارید تا تیم بهصورت ناسازگار از کدها استفاده نکند.
مثال 4: رد کردن تاریخ ناممکن
رشته از نظر شکل شبیه تاریخ است، اما روز 31 برای ماه آوریل وجود ندارد. TRY_CONVERT اعتبار تقویمی را نیز بررسی و NULL برمیگرداند.
SELECT TRY_CONVERT(date, '31/04/2026', 103) AS ParsedDate;
نکته کاربردی: کنترل با LIKE یا طول رشته کافی نیست؛ تبدیل واقعی بهترین راه تشخیص معتبر بودن تاریخ در تقویم مقصد است.
مثال 5: مقایسه دو Style روی یک ورودی
رشته 07/08/2026 مبهم است و با Style آمریکایی و بریتانیایی دو تاریخ متفاوت تولید میکند. جدول خروجی خطر فرض پنهان درباره ترتیب ماه و روز را نشان میدهد.
SELECT TRY_CONVERT(date, '07/08/2026', 101) AS UsDate,
TRY_CONVERT(date, '07/08/2026', 103) AS BritishDate;
| UsDate | BritishDate |
|---|
| 2026-07-08 | 2026-08-07 |
نکته کاربردی: بدون متادیتای منبع نمیتوان معنای درست را حدس زد؛ Culture یا Style را همراه داده نگه دارید.
مثال 6: پاکسازی جدول مرحلهای تاریخ
داده نمونه دارای تاریخ سالم، تاریخ خراب و NULL است. CROSS APPLY یک مقدار تبدیلشده میسازد و گزارش، وضعیت هر ردیف را بدون توقف دسته مشخص میکند.
DECLARE @Stage TABLE (Id int, DateText varchar(20));
INSERT INTO @Stage VALUES (1,'2026-07-19'),(2,'2026-02-30'),(3,NULL);
SELECT s.Id, x.CleanDate,
CASE WHEN s.DateText IS NULL THEN N'خالی'
WHEN x.CleanDate IS NULL THEN N'نامعتبر' ELSE N'معتبر' END AS Status
FROM @Stage AS s
CROSS APPLY (VALUES(TRY_CONVERT(date,s.DateText,23))) AS x(CleanDate);
| Id | CleanDate | Status |
|---|
| 1 | 2026-07-19 | معتبر |
| 2 | NULL | نامعتبر |
| 3 | NULL | خالی |
نکته کاربردی: مرحله Staging جای مناسبی برای نگهداری متن خام، مقدار پاکشده و علت رد است؛ این سه را در جدول نهایی مخلوط نکنید.
مثال 7: فیلتر داده با Style مشخص
در این گزارش فقط رکوردهایی پذیرفته میشوند که تاریخ متنی آنها دقیقاً با قرارداد ISO قابل تبدیل باشد. تبدیل امن از شکست Query به علت یک مقدار خراب جلوگیری میکند.
DECLARE @Events TABLE (Id int, EventDateText varchar(20));
INSERT INTO @Events VALUES (1,'2026-07-19'),(2,'19/07/2026'),(3,'invalid');
SELECT Id, TRY_CONVERT(date, EventDateText, 23) AS EventDate
FROM @Events
WHERE TRY_CONVERT(date, EventDateText, 23) IS NOT NULL;
نکته کاربردی: اگر ورودی چندقالبی است، ترتیب آزمون Styleها را صریح کنید؛ پذیرش بیقاعده قالبها میتواند تاریخ اشتباه اما ظاهراً معتبر بسازد.
مثال 8: کنترل NULL در آرگومان Style
طبق رفتار تابع، اگر Style مقدار NULL داشته باشد، نتیجه TRY_CONVERT نیز NULL میشود. این حالت در Procedureهایی رخ میدهد که کد Style را بهصورت پارامتر اختیاری دریافت میکنند.
DECLARE @Style int = NULL;
SELECT TRY_CONVERT(date, '2026-07-19', @Style) AS ParsedDate;
نکته کاربردی: برای Style پارامتری مقدار پیشفرض معتبر تعریف و دامنه کدهای مجاز را پیش از اجرای تبدیل کنترل کنید.
مثال 9: ساخت گزارش نرخ موفقیت ورود داده
این Query تعداد کل مقدارهای غیرخالی، تبدیلهای موفق و شکستها را محاسبه میکند. چنین شاخصی برای SLA کیفیت فایلهای دریافتی و مذاکره با تأمینکننده داده قابل استفاده است.
DECLARE @Feed TABLE (DateText varchar(20));
INSERT INTO @Feed VALUES ('2026-01-01'),('bad'),('2026-12-31'),(NULL);
SELECT COUNT(DateText) AS ProvidedCount,
COUNT(TRY_CONVERT(date, DateText, 23)) AS ValidCount,
COUNT(DateText) - COUNT(TRY_CONVERT(date, DateText, 23)) AS InvalidCount
FROM @Feed;
| ProvidedCount | ValidCount | InvalidCount |
|---|
| 3 | 2 | 1 |
نکته کاربردی: نرخ موفقیت را در طول زمان مانیتور کنید؛ افزایش ناگهانی InvalidCount معمولاً نشانه تغییر بدون هماهنگی در قالب منبع است.
مثال 10: بهینهسازی فیلتر با ستون پاکشده
اجرای TRY_CONVERT روی هر ردیف در هر گزارش مقیاسپذیر نیست. الگوی بهتر این است که مقدار معتبر در مرحله ورود به ستون date نوشته و سپس روی آن ایندکس ایجاد شود.
-- پس از پاکسازی در فرآیند ETL
CREATE INDEX IX_Stage_CleanDate
ON dbo.StageEvents(CleanDate)
WHERE CleanDate IS NOT NULL;
SELECT EventId, CleanDate
FROM dbo.StageEvents
WHERE CleanDate >= '2026-07-01'
AND CleanDate < '2026-08-01';
| راهکار | اثر |
|---|
| تبدیل هنگام ورود و ایندکس فیلترشده | کاهش CPU گزارش و امکان Index Seek |
نکته کاربردی: TRY_CONVERT را در مرز ورود داده اجرا کنید، نه در همه Queryهای مصرفکننده؛ این تصمیم هم کیفیت و هم کارایی را متمرکز میکند.
NULL، داده مرزی و اعتبارسنجی
NULL نشانه ناشناخته یا نبود مقدار است و نباید بدون تصمیم کسبوکاری با صفر یا رشته خالی جایگزین شود. در کار با TRY_CONVERT ابتدا NULL اصلی را بررسی کنید، سپس شکست تبدیل را بسنجید و در نهایت قواعد دامنه مانند حداقل، حداکثر و تعداد رقم را اعمال کنید. تبدیل شدن یک متن به عدد یا تاریخ فقط اعتبار نحوی و نوعی را نشان میدهد، نه الزاماً معتبر بودن آن برای فرآیند سازمانی.
دادههای مرزی شامل بزرگترین عدد مجاز، متن با طول دقیق مقصد، زمانهای نزدیک تغییر روز، تاریخ ناممکن، نویسههای یونیکد و رشته دارای فاصله هستند. برای هرکدام تست خودکار بنویسید و نتیجه را در نسخه هدف SQL Server کنترل کنید. همچنین Collation، زبان Session و DATEFORMAT را در تست یکپارچگی نادیده نگیرید.
خطاهای رایج
- اعتماد به تبدیل ضمنی و نادیده گرفتن اولویت نوعهای داده در عبارت یا Join.
- ننوشتن طول varchar یا nvarchar و بریده شدن خروجی در یکی از مسیرهای اجرا.
- انتخاب decimal با precision ناکافی و ایجاد سرریز یا گرد شدن ناخواسته.
- استفاده از Style مبهم یا ناسازگار با قرارداد واقعی منبع.
- قرار دادن تابع تبدیل روی ستون ایندکسشده در WHERE و دشوار کردن Index Seek.
- نادیده گرفتن خروجی NULL نسخههای TRY و گزارش کردن جمع ناقص بهعنوان نتیجه کامل.
رفع خطا فقط با پیچیدن عبارت در یک تابع TRY کامل نمیشود. باید مالک داده خراب، مسیر اصلاح، حد قابل قبول نرخ شکست و رفتار تراکنش مشخص باشد. سامانه مقاوم خطا را مدیریت میکند، اما آن را پنهان نمیکند.
نکات Performance و بهینهسازی
هزینه یک تبدیل منفرد معمولاً کم است، ولی ضرب آن در میلیونها ردیف محسوس میشود. توابع بومی تبدیل معمولاً سبکاند، اما محل اجرای آنها در Plan اهمیت زیادی دارد. Actual Execution Plan، زمان CPU، تعداد خواندن منطقی و تخمین Cardinality را پیش و پس از تغییر مقایسه کنید.
اگر Predicate روی CAST یا CONVERT ستون نوشته شود، موتور ممکن است نتواند از ترتیب ایندکس بهطور مستقیم استفاده کند. بهجای آن پارامتر را به نوع ستون تبدیل کنید، برای تاریخ از بازه نیمهباز استفاده کنید یا مقدار استاندارد را در ستون مناسب ذخیره کنید. ستون محاسباتی Persisted و ایندکس فیلترشده گاهی مفیدند، اما باید قطعی بودن عبارت و هزینه نگهداری آنها ارزیابی شود.
در فرآیند ETL، تبدیل و اعتبارسنجی را یکبار در Staging انجام دهید. سپس ردیف سالم را به جدول نهایی و ردیف خراب را با علت و متن خام به Reject بفرستید. این طراحی هم گزارش را سریع میکند و هم امکان حسابرسی و اصلاح دستهای را فراهم میآورد.
بهترین روشها
- نوع مقصد را از مدل کسبوکار انتخاب کنید، نه از یک نمونه محدود داده.
- طول متن و precision و scale عدد را همیشه صریح بنویسید.
- قالب تاریخ ورودی را ISO یا Style مشخص و مستند نگه دارید.
- NULL اصلی، شکست تبدیل و نقض دامنه را سه وضعیت جدا در نظر بگیرید.
- تبدیل را روی پارامتر یا هنگام ورود انجام دهید و ستون ایندکسشده را در شرط دستنخورده نگه دارید.
- برای متن فارسی از nvarchar و رشتههای N استفاده کنید.
- نتیجه و Plan را با داده واقعی و نسخه هدف SQL Server آزمایش کنید.
کاربردهای واقعی
TRY_CONVERT میتواند در ورود فایل فروش، پاکسازی داده CRM، تبدیل تاریخ قرارداد، ساخت خروجی API، مهاجرت سامانه قدیمی، کنترل فرم کاربر و آمادهسازی Data Warehouse استفاده شود. نقطه مشترک همه سناریوها وجود یک قرارداد روشن میان متن خام و نوع استاندارد است.
در پروژه سازمانی بهتر است منطق تبدیل در View یا گزارشهای متعدد کپی نشود. Procedure ورودی، Pipeline ETL یا لایه سرویس مشترک میتواند قرارداد را متمرکز کند. این تمرکز تست، پایش نرخ خطا، تغییر نسخه و ارائه خدمات پشتیبانی پایگاه داده را بسیار سادهتر میسازد.
سؤالات متداول
پرسش متداول 1: TRY_CONVERT در SQL Server دقیقاً چه کاری انجام میدهد؟
TRY_CONVERT مقدار ورودی را به نوع مقصد تبدیل میکند و ویژگی شاخص آن آرگومان Style در SQL Server است. انتخاب نوع مقصد، طول، precision و scale بخشی از قرارداد داده محسوب میشود و نباید به پیشفرضها واگذار شود.
پرسش متداول 2: خروجی و رفتار خطای TRY_CONVERT چگونه است؟
خروجی از نوع مقصد اعلامشده خواهد بود. در شکستهای معمول تبدیل NULL میدهد، هرچند تبدیلهای صریحاً ممنوع همچنان ممکن است خطا ایجاد کنند. برای طراحی درست باید NULL واقعی ورودی، شکست تبدیل و مقدار خارج از دامنه را جداگانه پایش کنید.
پرسش متداول 3: آیا یادگیری TRY_CONVERT برای پروژههای تجاری SQL Server ضروری است؟
بله؛ بسیاری از خطاهای مالی، تاریخی و یکپارچهسازی از تبدیل ضمنی یا نوع مقصد نامناسب ناشی میشوند. آموزش عملی این تابع هزینه رفع خطا و دوبارهکاری گزارشها را کاهش میدهد.
پرسش متداول 4: استفاده حرفهای از TRY_CONVERT چه ارزش تجاری ایجاد میکند؟
قرارداد تبدیل روشن، داده قابل اعتمادتر، گزارش دقیقتر و فرآیند ورود مقاومتر میسازد. در پروژههای سازمانی میتوان با بازبینی Queryها و مشاوره SQL Server نقاط تبدیل پرریسک را پیش از اختلال شناسایی کرد.
پرسش متداول 5: TRY_CONVERT را در مقایسه با سایر توابع تبدیل چه زمانی انتخاب کنیم؟
وقتی کنترل Style بهویژه برای تاریخ یا باینری لازم است این تابع بر CAST برتری دارد؛ در تبدیل ساده CAST گویاتر و استانداردتر است.
پرسش متداول 6: برای پیادهسازی TRY_CONVERT در Procedure موجود چه خدمتی لازم است؟
ابتدا نمونه داده، نوع ستونها، تنظیم زبان Session، حجم ردیف و Plan اجرایی بررسی میشود. سپس میتوان نسخه آزمایشی، تست مرزی و راهکار مهاجرت را در قالب مشاوره یا انجام پروژه SQL Server آماده کرد.
پرسش متداول 7: رایجترین خطا هنگام کار با TRY_CONVERT چیست؟
استفاده از Style مبهم یا تبدیل ستون ایندکسشده در WHERE بسیار رایج است. متن خام و قرارداد منبع را در تستها نگه دارید.
پرسش متداول 8: TRY_CONVERT چه اثری بر Performance دارد؟
خود تبدیل روی تعداد کم ارزان است، اما اجرای آن برای هر ردیف بزرگ یا روی ستون شرط میتواند CPU را افزایش و Index Seek را محدود کند. تبدیل را ترجیحاً در مرز ورود یا روی پارامتر انجام دهید.
پرسش متداول 9: بهترین روش استفاده از TRY_CONVERT چیست؟
نوع مقصد و طول را صریح تعیین کنید، حالتهای NULL و سرریز را تست کنید، شکستها را ثبت کنید و مقدار استاندارد را برای مصرفهای بعدی نگه دارید. قالببندی نمایشی را تا حد امکان به لایه نمایش بسپارید.
پرسش متداول 10: TRY_CONVERT در کدام نسخههای SQL Server قابل استفاده است؟
این تابع از SQL Server 2012 در دسترس است و در نسخههای جدید SQL Server و Azure SQL نیز پشتیبانی میشود؛ سطح سازگاری و محدودیت Remoting را بررسی کنید.
سؤالات مصاحبه SQL Server
سؤال مصاحبه 1: تفاوت تبدیل ضمنی و TRY_CONVERT چیست؟
در تبدیل ضمنی موتور بر اساس اولویت انواع تصمیم میگیرد، اما تابع تبدیل قصد و نوع مقصد را صریح میکند. تبدیل ضمنی روی سمت نامناسب Join یا Predicate میتواند هم خطا و هم افت کارایی ایجاد کند.
سؤال مصاحبه 2: TRY_CONVERT با CONVERT چه تفاوتی دارد؟
نسخه TRY در شکستهای معمول NULL میدهد، در حالی که نسخه قطعی خطا ایجاد میکند؛ هر دو تابع از نظر محدوده تبدیل و نوع مقصد قواعد SQL Server را رعایت میکنند.
سؤال مصاحبه 3: چرا تبدیل ستون در WHERE ممکن است بد باشد؟
چون عبارت روی ستون میتواند جستوجو را غیر SARGable کند و مانع استفاده مستقیم از کلید مرتب ایندکس شود. معمولاً تبدیل پارامتر یا شرط بازهای Plan بهتری میسازد.
سؤال مصاحبه 4: چگونه شکستهای تبدیل را بدون پنهان کردن خطا مدیریت میکنید؟
متن خام، مقدار استاندارد، وضعیت و علت Reject را جدا ذخیره میکنم؛ نرخ شکست را مانیتور و برای عبور از آستانه هشدار تعریف میکنم. NULL حاصل نباید بیگزارش از محاسبات حذف شود.
سؤال مصاحبه 5: برای تست تبدیل چه حالتهایی لازم است؟
مقدار سالم، NULL، رشته خالی، نویسه یونیکد، حداقل و حداکثر نوع، سرریز، طول بیش از مقصد، تاریخ ناممکن، Culture متفاوت و حجم واقعی باید پوشش داده شوند.
چکلیست نهایی
- نوع مقصد TRY_CONVERT با دامنه واقعی داده هماهنگ است.
- طول متن، precision، scale یا دقت زمانی صریح تعیین شده است.
- رفتار NULL، ورودی خراب و سرریز با تست پوشش داده شده است.
- هیچ تابع غیرضروری روی ستون ایندکسشده در Predicate اجرا نمیشود.
- خروجی تبدیل ناموفق ثبت، شمارش و برای اصلاح قابل ردیابی است.
- Query روی نسخه هدف SQL Server و با حجم نزدیک تولید آزمایش شده است.
جمعبندی
TRY_CONVERT زمانی ارزشمند است که با شناخت نوع داده، کیفیت منبع و مسیر مصرف انتخاب شود. مثالهای این مقاله نشان دادند چگونه تبدیل ساده، NULL، داده مرزی، گزارش سازمانی و کارایی را در یک طراحی قابل اعتماد کنار هم قرار دهیم. اصل مهم این است که تبدیل را بخشی از قرارداد داده بدانیم، نه وصلهای برای پوشاندن نوع ستون نامناسب.
برای مقایسه دوباره گزینهها و دسترسی به مقالههای مرتبط، به راهنمای جامع CAST، CONVERT، TRY_CAST، TRY_CONVERT، PARSE و TRY_PARSE بازگردید.