آموزش تابع TRY_CAST در SQL Server برای تبدیل امن داده
مقدمه
تابع TRY_CAST یکی از ابزارهای مهم تبدیل داده در Microsoft SQL Server است. تبدیل نوع فقط تغییر ظاهر مقدار نیست؛ نوع مقصد بر مقایسه، دقت محاسبه، مرتبسازی، مصرف حافظه و امکان استفاده از ایندکس اثر میگذارد. در این راهنما از مثال ساده آغاز میکنیم و سپس سناریوهای پاکسازی داده، گزارشگیری، مدیریت NULL و بهینهسازی را بررسی میکنیم.
اگر نوع ستون با معنای واقعی داده هماهنگ باشد، نیاز به تبدیل در Queryها کمتر و طراحی پایدارتر میشود. با این حال در مرزهای سامانه مانند فایل ورودی، API، گزارش متنی و اتصال به نرمافزار قدیمی، استفاده آگاهانه از TRY_CAST ضروری است. هر مثال این مقاله کامل، مستقل و دارای خروجی مورد انتظار است تا بتوانید رفتار را در محیط آزمایشی بررسی کنید.
برای دیدن جایگاه این تابع در کنار پنج گزینه دیگر، راهنمای جامع توابع تبدیل داده در SQL Server را نیز مطالعه کنید. آن مقاله یک جدول تصمیم دارد و نشان میدهد چه زمانی تبدیل استاندارد، نسخه امن، Style یا Culture انتخاب مناسبتری است.
تعریف تابع TRY_CAST
TRY_CAST همان الگوی نحوی CAST را دارد، اما در بیشتر تبدیلهای ناموفق به جای ایجاد خطا مقدار NULL برمیگرداند. این رفتار برای دادههای واردشده از فایل، فرم کاربر، API یا سامانههای قدیمی بسیار مفید است. با این حال، تبدیلهایی که اصولاً از سوی SQL Server مجاز نیستند همچنان میتوانند خطا ایجاد کنند.
وجود واژه TRY به این معنی است که بسیاری از شکستهای قالبی به NULL تبدیل میشوند، اما مسئولیت ثبت و تحلیل شکست از بین نمیرود. مزیت اصلی آن بیان صریح و استاندارد قصد تبدیل است.
نحو یا Syntax
-- Syntax
TRY_CAST ( expression AS data_type [ ( length ) ] )
پارامترها
- expression: مقدار مشکوک یا عبارتی که میخواهیم امکان تبدیل آن را بررسی کنیم.
- data_type: نوع مقصد معتبر در SQL Server.
- length: طول اختیاری برای مقصدهای دارای طول؛ محدودیتهای varchar(max) و nvarchar(max) باید در نظر گرفته شود.
نوع خروجی و رفتار خطا
در موفقیت، مقداری از نوع مقصد برمیگردد؛ در تبدیل ناموفق معمولی، خروجی NULL است. بنابراین لازم است میان NULL اصلی ورودی و NULL حاصل از شکست تبدیل تمایز منطقی ایجاد شود.
| معیار | راهنمای استفاده |
|---|
| نوع مبدأ | نوع واقعی عبارت و اولویت انواع SQL Server را بررسی کنید. |
| نوع مقصد | طول، precision، scale و دقت زمانی را صریح انتخاب کنید. |
| داده نامعتبر | خروجی NULL را ثبت و از NULL اصلی تفکیک کنید. |
| حجم بالا | از اجرای تابع روی ستون ایندکسشده در Predicate پرهیز کنید. |
چه زمانی از TRY_CAST استفاده کنیم؟
این تابع برای تبدیل صریح و بدون نیاز به Style یا Culture مناسب است و قصد Query را برای نگهدارنده بعدی روشن میکند. اگر داده در اختیار شماست، اصلاح نوع ستون در طراحی پایگاه داده معمولاً بهتر از تکرار تبدیل در همه Queryها خواهد بود.
تبدیل را نزدیک مرزی انجام دهید که داده از متن یا سامانه خارجی وارد مدل استاندارد میشود. مقدار خام را برای حسابرسی حفظ کنید، مقدار تبدیلشده را در نوع درست بنویسید و وضعیت اعتبارسنجی را جدا نگه دارید. این الگو سبب میشود گزارشها سادهتر، ایندکسها مؤثرتر و مسئولیت کیفیت داده شفافتر باشد.
در عملیات مالی، precision و scale را از قبل محاسبه کنید. در متن فارسی nvarchar و پیشوند N را بهکار ببرید. برای تاریخوزمان نیز میان date، datetime2 و datetimeoffset تفاوت بگذارید؛ تبدیل یک زمان محلی به متن، آن را خودکار به UTC تبدیل نمیکند و Offset باید در قرارداد سامانه مشخص باشد.
مثالهای عملی
مثال 1: تبدیل موفق متن عددی
TRY_CAST برای ورودی سالم همان نتیجه CAST را تولید میکند. مزیت اصلی زمانی دیده میشود که کیفیت همه مقدارها تضمینشده نیست و میخواهیم Query با نخستین مقدار بد متوقف نشود.
SELECT TRY_CAST('7500' AS int) AS SafeNumber;
نکته کاربردی: اگر قرارداد ورودی کاملاً معتبر و خطا نشانه اشکال جدی برنامه است، CAST میتواند Fail-fast مناسبتری باشد.
مثال 2: بازگشت NULL برای متن نامعتبر
رشته شامل حروف به int قابل تبدیل نیست. TRY_CAST بهجای خطای تبدیل NULL برمیگرداند و به برنامه اجازه میدهد شکست را بهصورت دادهای مدیریت کند.
SELECT TRY_CAST('12A5' AS int) AS SafeNumber;
نکته کاربردی: NULL را بیصدا نادیده نگیرید؛ تعداد شکستها را ثبت کنید تا افت کیفیت داده در فرآیند ETL پنهان نماند.
مثال 3: جدا کردن ردیفهای سالم فایل ورودی
جدول نمونه شامل عدد سالم، متن خراب و NULL است. شرط TRY_CAST فقط ردیفهای قابل تبدیل را برمیگرداند و از شکست کل دسته ورودی جلوگیری میکند.
DECLARE @Import TABLE (RowId int, QtyText varchar(20));
INSERT INTO @Import VALUES (1,'12'),(2,'N/A'),(3,'35'),(4,NULL);
SELECT RowId, TRY_CAST(QtyText AS int) AS Quantity
FROM @Import
WHERE TRY_CAST(QtyText AS int) IS NOT NULL;
نکته کاربردی: در حجم بالا تبدیل را یکبار با CROSS APPLY یا مرحله Staging محاسبه کنید تا عبارت یکسان در SELECT و WHERE تکرار نشود.
مثال 4: تشخیص ردیفهای خراب برای گزارش کیفیت
بهجای حذف داده نامعتبر، این Query آن را همراه شناسه ردیف گزارش میکند. شرط دوم باعث میشود NULL واقعی با شکست تبدیل اشتباه گرفته نشود.
DECLARE @Import TABLE (RowId int, QtyText varchar(20));
INSERT INTO @Import VALUES (1,'12'),(2,'N/A'),(3,'35'),(4,NULL);
SELECT RowId, QtyText
FROM @Import
WHERE QtyText IS NOT NULL
AND TRY_CAST(QtyText AS int) IS NULL;
نکته کاربردی: این الگو برای ساخت جدول Reject و بازخورد به تأمینکننده داده بسیار مفید است و قابلیت حسابرسی فرآیند ورود را بالا میبرد.
مثال 5: تبدیل امن تاریخ ISO
تاریخ ISO معمولاً مستقل از زبان Session و برای تبادل داده مناسب است. TRY_CAST رشته معتبر را به date تبدیل میکند و امکان مقایسه زمانی واقعی را فراهم میآورد.
SELECT TRY_CAST('2026-07-19' AS date) AS ValidDate;
نکته کاربردی: اگر قالب مشخصی مانند dd/mm/yyyy دارید و باید آن را صریح اعلام کنید، TRY_CONVERT با Style انتخاب دقیقتری است.
مثال 6: رفتار NULL اصلی و شکست تبدیل
هر دو حالت ممکن است NULL تولید کنند، اما علت آنها متفاوت است. ستون وضعیت با CASE میان نبود ورودی، تبدیل موفق و مقدار نامعتبر تمایز ایجاد میکند.
DECLARE @Input varchar(20) = NULL;
SELECT CASE
WHEN @Input IS NULL THEN N'ورودی خالی'
WHEN TRY_CAST(@Input AS int) IS NULL THEN N'نامعتبر'
ELSE N'معتبر'
END AS ValidationStatus;
| ValidationStatus |
|---|
| ورودی خالی |
نکته کاربردی: در مدل داده و گزارش کیفیت، NULL منبع را از Reject تبدیل جدا نگه دارید تا شاخصهای خطا دقیق باشند.
مثال 7: کنترل سرریز عددی
حتی یک رشته کاملاً عددی ممکن است خارج از محدوده int باشد. TRY_CAST این سرریز را به NULL تبدیل میکند و نشان میدهد اعتبار نحوی بهتنهایی برای اعتبار دامنه کافی نیست.
SELECT TRY_CAST('999999999999' AS int) AS AsInt,
TRY_CAST('999999999999' AS bigint) AS AsBigInt;
| AsInt | AsBigInt |
|---|
| NULL | 999999999999 |
نکته کاربردی: نوع مقصد را با دامنه کسبوکار هماهنگ کنید؛ استفاده از TRY_CAST نباید انتخاب نوع نامناسب را پنهان کند.
مثال 8: محاسبه مجموع همراه شمارش خطاها
گزارش سازمانی باید هم جمع مقدارهای سالم و هم تعداد رکوردهای خراب را نشان دهد. تبدیل امن اجازه میدهد هر دو شاخص در یک پیمایش محاسبه شوند.
DECLARE @Feed TABLE (AmountText varchar(20));
INSERT INTO @Feed VALUES ('10.50'),('bad'),('20.00'),(NULL);
SELECT SUM(TRY_CAST(AmountText AS decimal(10,2))) AS ValidTotal,
SUM(CASE WHEN AmountText IS NOT NULL
AND TRY_CAST(AmountText AS decimal(10,2)) IS NULL
THEN 1 ELSE 0 END) AS InvalidCount
FROM @Feed;
| ValidTotal | InvalidCount |
|---|
| 30.50 | 1 |
نکته کاربردی: SUM مقدارهای NULL را نادیده میگیرد؛ InvalidCount ضروری است تا حذف شدن داده خراب از جمع برای تصمیمگیرنده شفاف بماند.
مثال 9: تفاوت تبدیل ناموفق و تبدیل ممنوع
TRY_CAST بسیاری از شکستهای قالبی را به NULL تبدیل میکند، اما تبدیلهایی که صریحاً در SQL Server مجاز نیستند همچنان خطا میدهند. نمونه زیر عمداً روش ممنوع را مستند میکند و سپس مسیر متنی اصلاحشده را نشان میدهد.
-- این عبارت مجاز نیست و خطا میدهد:
-- SELECT TRY_CAST(4 AS xml);
-- مسیر معتبر از متن XML:
SELECT TRY_CAST('<root id=''4'' />' AS xml) AS XmlValue;
| XmlValue |
|---|
| عنصر root با شناسه 4 |
نکته کاربردی: TRY را معادل TRY/CATCH عمومی ندانید؛ ماتریس تبدیل نوعهای SQL Server همچنان بر تابع حاکم است.
مثال 10: محاسبه یکباره تبدیل با CROSS APPLY
تکرار TRY_CAST در چند بخش Query هزینه CPU و پیچیدگی را بالا میبرد. CROSS APPLY نتیجه تبدیل را یکبار نامگذاری میکند تا فیلتر و خروجی از همان مقدار استفاده کنند.
DECLARE @Raw TABLE (Id int, ValueText varchar(20));
INSERT INTO @Raw VALUES (1,'15'),(2,'oops'),(3,'40');
SELECT r.Id, x.ValueInt
FROM @Raw AS r
CROSS APPLY (VALUES (TRY_CAST(r.ValueText AS int))) AS x(ValueInt)
WHERE x.ValueInt >= 20;
نکته کاربردی: برای میلیونها ردیف، بهترین راه اصلاح نوع داده در مبدأ یا تبدیل در Staging و ایندکس کردن مقدار پاکشده است؛ APPLY فقط تکرار عبارت را کاهش میدهد.
NULL، داده مرزی و اعتبارسنجی
NULL نشانه ناشناخته یا نبود مقدار است و نباید بدون تصمیم کسبوکاری با صفر یا رشته خالی جایگزین شود. در کار با TRY_CAST ابتدا NULL اصلی را بررسی کنید، سپس شکست تبدیل را بسنجید و در نهایت قواعد دامنه مانند حداقل، حداکثر و تعداد رقم را اعمال کنید. تبدیل شدن یک متن به عدد یا تاریخ فقط اعتبار نحوی و نوعی را نشان میدهد، نه الزاماً معتبر بودن آن برای فرآیند سازمانی.
دادههای مرزی شامل بزرگترین عدد مجاز، متن با طول دقیق مقصد، زمانهای نزدیک تغییر روز، تاریخ ناممکن، نویسههای یونیکد و رشته دارای فاصله هستند. برای هرکدام تست خودکار بنویسید و نتیجه را در نسخه هدف SQL Server کنترل کنید. همچنین Collation، زبان Session و DATEFORMAT را در تست یکپارچگی نادیده نگیرید.
خطاهای رایج
- اعتماد به تبدیل ضمنی و نادیده گرفتن اولویت نوعهای داده در عبارت یا Join.
- ننوشتن طول varchar یا nvarchar و بریده شدن خروجی در یکی از مسیرهای اجرا.
- انتخاب decimal با precision ناکافی و ایجاد سرریز یا گرد شدن ناخواسته.
- استفاده از تبدیل قطعی روی فایل یا ورودی کاربر بدون کنترل کیفیت.
- قرار دادن تابع تبدیل روی ستون ایندکسشده در 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_CAST میتواند در ورود فایل فروش، پاکسازی داده CRM، تبدیل تاریخ قرارداد، ساخت خروجی API، مهاجرت سامانه قدیمی، کنترل فرم کاربر و آمادهسازی Data Warehouse استفاده شود. نقطه مشترک همه سناریوها وجود یک قرارداد روشن میان متن خام و نوع استاندارد است.
در پروژه سازمانی بهتر است منطق تبدیل در View یا گزارشهای متعدد کپی نشود. Procedure ورودی، Pipeline ETL یا لایه سرویس مشترک میتواند قرارداد را متمرکز کند. این تمرکز تست، پایش نرخ خطا، تغییر نسخه و ارائه خدمات پشتیبانی پایگاه داده را بسیار سادهتر میسازد.
سؤالات متداول
پرسش متداول 1: TRY_CAST در SQL Server دقیقاً چه کاری انجام میدهد؟
TRY_CAST مقدار ورودی را به نوع مقصد تبدیل میکند و ویژگی شاخص آن نحو صریح تبدیل نوع است. انتخاب نوع مقصد، طول، precision و scale بخشی از قرارداد داده محسوب میشود و نباید به پیشفرضها واگذار شود.
پرسش متداول 2: خروجی و رفتار خطای TRY_CAST چگونه است؟
خروجی از نوع مقصد اعلامشده خواهد بود. در شکستهای معمول تبدیل NULL میدهد، هرچند تبدیلهای صریحاً ممنوع همچنان ممکن است خطا ایجاد کنند. برای طراحی درست باید NULL واقعی ورودی، شکست تبدیل و مقدار خارج از دامنه را جداگانه پایش کنید.
پرسش متداول 3: آیا یادگیری TRY_CAST برای پروژههای تجاری SQL Server ضروری است؟
بله؛ بسیاری از خطاهای مالی، تاریخی و یکپارچهسازی از تبدیل ضمنی یا نوع مقصد نامناسب ناشی میشوند. آموزش عملی این تابع هزینه رفع خطا و دوبارهکاری گزارشها را کاهش میدهد.
پرسش متداول 4: استفاده حرفهای از TRY_CAST چه ارزش تجاری ایجاد میکند؟
قرارداد تبدیل روشن، داده قابل اعتمادتر، گزارش دقیقتر و فرآیند ورود مقاومتر میسازد. در پروژههای سازمانی میتوان با بازبینی Queryها و مشاوره SQL Server نقاط تبدیل پرریسک را پیش از اختلال شناسایی کرد.
پرسش متداول 5: TRY_CAST را در مقایسه با سایر توابع تبدیل چه زمانی انتخاب کنیم؟
وقتی تبدیل استاندارد و بدون Style میخواهید انتخاب خوبی است؛ برای داده ناسالم نسخه TRY و برای متن Culture محور خانواده PARSE را بررسی کنید.
پرسش متداول 6: برای پیادهسازی TRY_CAST در Procedure موجود چه خدمتی لازم است؟
ابتدا نمونه داده، نوع ستونها، تنظیم زبان Session، حجم ردیف و Plan اجرایی بررسی میشود. سپس میتوان نسخه آزمایشی، تست مرزی و راهکار مهاجرت را در قالب مشاوره یا انجام پروژه SQL Server آماده کرد.
پرسش متداول 7: رایجترین خطا هنگام کار با TRY_CAST چیست؟
کوچک گرفتن طول یا precision مقصد و اعتماد به معتبر بودن همه رشتهها خطای رایج است. متن خام و قرارداد منبع را در تستها نگه دارید.
پرسش متداول 8: TRY_CAST چه اثری بر Performance دارد؟
خود تبدیل روی تعداد کم ارزان است، اما اجرای آن برای هر ردیف بزرگ یا روی ستون شرط میتواند CPU را افزایش و Index Seek را محدود کند. تبدیل را ترجیحاً در مرز ورود یا روی پارامتر انجام دهید.
پرسش متداول 9: بهترین روش استفاده از TRY_CAST چیست؟
نوع مقصد و طول را صریح تعیین کنید، حالتهای NULL و سرریز را تست کنید، شکستها را ثبت کنید و مقدار استاندارد را برای مصرفهای بعدی نگه دارید. قالببندی نمایشی را تا حد امکان به لایه نمایش بسپارید.
پرسش متداول 10: TRY_CAST در کدام نسخههای SQL Server قابل استفاده است؟
این تابع از SQL Server 2012 در دسترس است و در نسخههای جدید SQL Server و Azure SQL نیز پشتیبانی میشود؛ سطح سازگاری و محدودیت Remoting را بررسی کنید.
سؤالات مصاحبه SQL Server
سؤال مصاحبه 1: تفاوت تبدیل ضمنی و TRY_CAST چیست؟
در تبدیل ضمنی موتور بر اساس اولویت انواع تصمیم میگیرد، اما تابع تبدیل قصد و نوع مقصد را صریح میکند. تبدیل ضمنی روی سمت نامناسب Join یا Predicate میتواند هم خطا و هم افت کارایی ایجاد کند.
سؤال مصاحبه 2: TRY_CAST با CAST چه تفاوتی دارد؟
نسخه TRY در شکستهای معمول NULL میدهد، در حالی که نسخه قطعی خطا ایجاد میکند؛ هر دو تابع از نظر محدوده تبدیل و نوع مقصد قواعد SQL Server را رعایت میکنند.
سؤال مصاحبه 3: چرا تبدیل ستون در WHERE ممکن است بد باشد؟
چون عبارت روی ستون میتواند جستوجو را غیر SARGable کند و مانع استفاده مستقیم از کلید مرتب ایندکس شود. معمولاً تبدیل پارامتر یا شرط بازهای Plan بهتری میسازد.
سؤال مصاحبه 4: چگونه شکستهای تبدیل را بدون پنهان کردن خطا مدیریت میکنید؟
متن خام، مقدار استاندارد، وضعیت و علت Reject را جدا ذخیره میکنم؛ نرخ شکست را مانیتور و برای عبور از آستانه هشدار تعریف میکنم. NULL حاصل نباید بیگزارش از محاسبات حذف شود.
سؤال مصاحبه 5: برای تست تبدیل چه حالتهایی لازم است؟
مقدار سالم، NULL، رشته خالی، نویسه یونیکد، حداقل و حداکثر نوع، سرریز، طول بیش از مقصد، تاریخ ناممکن، Culture متفاوت و حجم واقعی باید پوشش داده شوند.
چکلیست نهایی
- نوع مقصد TRY_CAST با دامنه واقعی داده هماهنگ است.
- طول متن، precision، scale یا دقت زمانی صریح تعیین شده است.
- رفتار NULL، ورودی خراب و سرریز با تست پوشش داده شده است.
- هیچ تابع غیرضروری روی ستون ایندکسشده در Predicate اجرا نمیشود.
- خروجی تبدیل ناموفق ثبت، شمارش و برای اصلاح قابل ردیابی است.
- Query روی نسخه هدف SQL Server و با حجم نزدیک تولید آزمایش شده است.
جمعبندی
TRY_CAST زمانی ارزشمند است که با شناخت نوع داده، کیفیت منبع و مسیر مصرف انتخاب شود. مثالهای این مقاله نشان دادند چگونه تبدیل ساده، NULL، داده مرزی، گزارش سازمانی و کارایی را در یک طراحی قابل اعتماد کنار هم قرار دهیم. اصل مهم این است که تبدیل را بخشی از قرارداد داده بدانیم، نه وصلهای برای پوشاندن نوع ستون نامناسب.
برای مقایسه دوباره گزینهها و دسترسی به مقالههای مرتبط، به راهنمای جامع CAST، CONVERT، TRY_CAST، TRY_CONVERT، PARSE و TRY_PARSE بازگردید.