TRY CONVERT, TRY CAST, TRY PARSE, TRY PARSE SQL Server, SQL Server, تبدیل نوع داده SQL Server, پاک سازی داده SQL Server, Data Type Conversion, ETL SQL Server, تفاوت TRY CONVERT و TRY CAST, تفاوت TRY CONVERT TRY CAST TRY PARSE, خطای تبدیل نوع داده

در تقریباً هر پروژه سازمانی که با SQL Server کار می‌کند، دیر یا زود به داده‌ای برمی‌خوریم که نوع داده آن با انتظار ما همخوانی ندارد. یک ستون تاریخ که در سیستم منبع به‌صورت رشته متنی ذخیره شده، یک فیلد مبلغ که گاهی حاوی مقادیر غیرعددی است، یا داده‌ای که از یک فایل CSV یا یک سیستم Legacy وارد جدول Staging شده و فرمت آن کاملاً یکدست نیست. در چنین شرایطی، تبدیل مستقیم نوع داده با CONVERT یا CAST می‌تواند به محض برخورد با اولین رکورد نامعتبر، کل Query را با خطا متوقف کند.

این دقیقاً همان مشکلی است که خانواده توابع TRY در SQL Server برای کاهش آن طراحی شده‌اند. TRY_CONVERT، TRY_CAST و TRY_PARSE هر سه یک هدف مشترک دارند: تبدیل نوع داده به شکلی امن‌تر، به‌طوری‌که در صورت ناموفق بودن تبدیل معمول، به‌جای متوقف کردن اجرای Query با یک خطای Runtime، مقدار NULL بازگردانده شود. باید از همین ابتدا روشن باشد که توابع TRY قرار نیست همه خطاهای SQL Server را سرکوب کنند. این توابع شکست معمول Conversion، مانند رشته غیرعددی یا تاریخ نامعتبر، را به NULL تبدیل می‌کنند، اما اگر تبدیل بین دو نوع داده از اساس در SQL Server مجاز نباشد، همچنان ممکن است خطا ایجاد شود.

با این حال، این سه تابع از نظر Syntax، قابلیت‌ها و سناریوهای مناسب استفاده، تفاوت‌های مهمی دارند که شناخت دقیق آن‌ها برای طراحی فرآیندهای پاک‌سازی داده و ETL قابل اعتماد ضروری است. در این مقاله بررسی می‌کنیم هر یک از این سه تابع دقیقاً چگونه کار می‌کند، چه تفاوتی با نسخه معمول خود دارند، در چه سناریوهای واقعی سازمانی کاربرد دارند، چه تفاوت‌های ظریفی بین خودشان دارند، و چه نکاتی از منظر Performance و طراحی فرآیندهای پاک‌سازی داده باید رعایت شود.

چرا خانواده توابع TRY در SQL Server معرفی شدند

پیش از معرفی این توابع در SQL Server 2012، تنها راه تبدیل نوع داده، استفاده از CONVERT یا CAST بود. این دو تابع در صورت برخورد با داده‌ای که قابل تبدیل به نوع مقصد نیست، یک خطای اجرایی تولید می‌کنند و اجرای Query را متوقف می‌کنند.

SELECT CONVERT ( INT, 'ABC' );

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

خانواده توابع TRY_CONVERT، TRY_CAST و TRY_PARSE برای کاهش همین مشکل طراحی شده‌اند: هر سه تلاش می‌کنند تبدیل نوع داده را انجام دهند و در صورت شکست معمول تبدیل، مقدار NULL بازمی‌گردانند تا پردازش باقی رکوردها بدون وقفه ادامه یابد.

تفاوت CAST، CONVERT و PARSE با نسخه‌های TRY آن‌ها

پیش از بررسی جزئیات هر تابع، مفید است رابطه هر تابع TRY با نسخه استاندارد خودش را در یک نگاه ببینیم.

تابع نسخه امن
CAST TRY_CAST
CONVERT TRY_CONVERT
PARSE TRY_PARSE

هر یک از این توابع TRY، دقیقاً همان منطق تبدیل نسخه اصلی خود را دنبال می‌کند، با این تفاوت که در صورت شکست معمول تبدیل، به‌جای پرتاب یک Exception، مقدار NULL بازمی‌گرداند. این تفاوت ساده، در عمل تأثیر زیادی روی پایداری Queryهایی دارد که با داده نامعتبر یا ناهمگون سروکار دارند.

TRY_CONVERT چیست و چگونه کار می‌کند

TRY_CONVERT نسخه امن تابع CONVERT در SQL Server است. Syntax آن دقیقاً مشابه CONVERT است، با این تفاوت که در صورت شکست تبدیل، خطا تولید نمی‌کند.

TRY_CONVERT ( data_type, expression [, style] )

پارامتر اول نوع داده مقصد است، پارامتر دوم مقداری است که باید تبدیل شود و پارامتر سوم، که اختیاری و مخصوص تبدیل تاریخ یا رشته است، فرمت یا Style تبدیل را مشخص می‌کند.

SELECT TRY_CONVERT ( INT, 'ABC' ) AS InvalidConversion;

نتیجه این Query به‌جای خطا، مقدار NULL خواهد بود. اکنون مثالی با داده معتبر و پارامتر Style برای تبدیل تاریخ.

SELECT TRY_CONVERT ( DATE, '2025/13/45', 111 ) AS InvalidDate;

از آنجا که ماه سیزده و روز چهل‌وپنج مقادیر معتبری برای تاریخ نیستند، این Query نیز مقدار NULL بازمی‌گرداند، بدون آنکه اجرای Query متوقف شود.

کاربرد TRY_CONVERT در پاک‌سازی داده

فرض کنید در یک فرآیند ETL سازمانی، داده فروش از یک فایل خارجی وارد جدول Staging شده و ستون OrderDateText به‌صورت رشته متنی ذخیره شده است، اما برخی رکوردها به دلیل خطای سیستم منبع، مقادیر نامعتبر یا خالی دارند.

SELECT
    OrderID,
    OrderDateText,
    TRY_CONVERT ( DATE, OrderDateText, 111 ) AS OrderDateConverted
FROM StagingOrders;

با استفاده از TRY_CONVERT، رکوردهایی که تاریخ آن‌ها قابل تبدیل نیست، مقدار NULL در ستون OrderDateConverted می‌گیرند، در حالی که رکوردهای سالم به‌درستی تبدیل می‌شوند و کل Query متوقف نمی‌شود. سپس می‌توان با یک Query جداگانه، رکوردهای دارای مقدار NULL را برای بررسی دستی یا گزارش خطا شناسایی کرد.

SELECT OrderID, OrderDateText
FROM StagingOrders
WHERE TRY_CONVERT ( DATE, OrderDateText, 111 ) IS NULL
    AND OrderDateText IS NOT NULL;

این Query تمام رکوردهایی را که مقدار OrderDateText آن‌ها خالی نیست اما قابل تبدیل به تاریخ معتبر نیست، شناسایی می‌کند و امکان ردیابی دقیق داده‌های خراب پیش از ورود به جدول نهایی را فراهم می‌آورد.

TRY_CAST چیست و چه تفاوتی با TRY_CONVERT دارد

TRY_CAST نسخه امن CAST در SQL Server است و از همان ساختار رایج CAST ... AS ... استفاده می‌کند.

TRY_CAST ( expression AS data_type )

برخلاف TRY_CONVERT، تابع TRY_CAST پارامتر Style ندارد. این بدان معنا نیست که TRY_CAST از تنظیمات محیطی کاملاً مستقل است؛ TRY_CAST پارامتر Style ندارد و تفسیر برخی رشته‌های تاریخ می‌تواند به فرمت مورد انتظار SQL Server و تنظیمات Session، مانند DATEFORMAT، وابسته باشد.

SELECT TRY_CAST ( '2025-08-09' AS DATE ) AS ValidDate;
SELECT TRY_CAST ( 'not a date' AS DATE ) AS InvalidDate;

Query اول تاریخ معتبر را برمی‌گرداند و Query دوم، به دلیل عدم امکان تبدیل، مقدار NULL تولید می‌کند، بدون توقف اجرا.

برای درک بهتر وابستگی TRY_CAST به تنظیمات Session، مثال زیر را در نظر بگیرید که همان رشته را با دو تنظیم متفاوت DATEFORMAT پردازش می‌کند.

SET DATEFORMAT dmy;
SELECT TRY_CAST ( '09/08/2025' AS DATE ) AS ParsedDate;

SET DATEFORMAT mdy;
SELECT TRY_CAST ( '09/08/2025' AS DATE ) AS ParsedDate;

در حالت اول، با تنظیم DATEFORMAT روی روز/ماه/سال، رشته به‌عنوان نهم آگوست تفسیر می‌شود. در حالت دوم، با تنظیم DATEFORMAT روی ماه/روز/سال، همان رشته به‌عنوان دهم سپتامبر تفسیر می‌شود. این مثال به‌روشنی نشان می‌دهد که نتیجه TRY_CAST برای یک رشته ثابت، می‌تواند بسته به تنظیمات Session کاملاً متفاوت باشد، و به همین دلیل نباید بدون آگاهی از این تنظیمات به رفتار پیش‌فرض آن تکیه کرد.

تفاوت اصلی TRY_CAST با TRY_CONVERT

تفاوت کلیدی این دو تابع، وجود پارامتر Style در TRY_CONVERT است. اگر داده ورودی یک فرمت تاریخ غیراستاندارد یا وابسته به یک قالب مشخص، مانند فرمت‌های اروپایی روز/ماه/سال، داشته باشد، TRY_CONVERT با تعیین صریح Style می‌تواند این فرمت را مستقل از تنظیمات Session به‌درستی تفسیر کند.

با TRY_CONVERT و Style مشخص:
SELECT TRY_CONVERT ( DATE, '09/08/2025', 103 ) AS DateWithStyle;

در این مثال، Style شماره ۱۰۳ صراحتاً مشخص می‌کند که فرمت ورودی روز/ماه/سال است، بنابراین نهم آگوست به‌درستی تفسیر می‌شود، صرف‌نظر از تنظیم DATEFORMAT جاری. به همین دلیل، در سناریوهایی که فرمت دقیق داده ورودی از قبل مشخص است، به‌خصوص در پردازش داده‌های وارداتی از سیستم‌های خارجی با فرمت‌های غیر پیش‌فرض، TRY_CONVERT به دلیل کنترل صریح Style، انتخاب مطمئن‌تری نسبت به TRY_CAST است. برای تبدیل‌های ساده و استاندارد که به Style یا Culture نیاز ندارند، TRY_CAST به دلیل Syntax ساده و خوانایی مناسب، معمولاً انتخاب خوبی است.

کاربرد TRY_CAST در اعتبارسنجی ورودی

فرض کنید یک Stored Procedure پارامترهای ورودی خود را به‌صورت NVARCHAR از یک لایه اپلیکیشن دریافت می‌کند و باید این مقادیر را به نوع عددی مناسب تبدیل کند، بدون اینکه یک ورودی نامعتبر باعث خطای کامل Procedure شود.

CREATE PROCEDURE UpdateProductPrice
    @ProductID NVARCHAR(20),
    @NewPrice NVARCHAR(20)
AS
BEGIN
    DECLARE @ProductIDInt INT = TRY_CAST ( @ProductID AS INT );
    DECLARE @NewPriceDecimal DECIMAL(18,2) = TRY_CAST ( @NewPrice AS DECIMAL(18,2) );

    IF @ProductIDInt IS NULL OR @NewPriceDecimal IS NULL
    BEGIN
        THROW 51000, N'مقادیر ورودی نامعتبر است.', 1;
        RETURN;
    END

    UPDATE Products
    SET UnitPrice = @NewPriceDecimal
    WHERE ProductID = @ProductIDInt;
END;

در این Procedure، TRY_CAST تلاش می‌کند پارامترهای متنی ورودی را به نوع عددی مناسب تبدیل کند. اگر هر یک از این تبدیل‌ها ناموفق باشد، مقدار NULL بازگردانده می‌شود و Procedure می‌تواند این وضعیت را به‌صورت کنترل‌شده با یک پیام خطای مشخص مدیریت کند، به‌جای آنکه اجازه دهد یک خطای اجرایی مبهم در میانه Procedure رخ دهد.

TRY_PARSE چیست و چه زمانی استفاده می‌شود

TRY_PARSE نسخه امن تابع PARSE است و برخلاف دو تابع قبلی، برای تبدیل رشته‌های متنی به انواع داده‌های تاریخ، زمان و عدد طراحی شده است و امکان تفسیر مقدار بر اساس یک Culture مشخص را فراهم می‌کند. این ویژگی باعث می‌شود TRY_PARSE در سناریوهایی که قالب ورودی به تنظیمات زبانی و منطقه‌ای وابسته است، کاربرد ویژه‌ای داشته باشد.

TRY_PARSE ( string_value AS data_type [ USING culture ] )

پارامتر اول رشته ورودی است، پارامتر دوم نوع داده مقصد است و پارامتر سوم، که اختیاری است، مشخص می‌کند رشته ورودی باید بر اساس چه Culture یا فرهنگ زبانی تفسیر شود.

SELECT TRY_PARSE ( '09/08/2025' AS DATE USING 'en-GB' ) AS ParsedDateUK;
SELECT TRY_PARSE ( '08/09/2025' AS DATE USING 'en-US' ) AS ParsedDateUS;

در Query اول، با استفاده از فرهنگ انگلیسی بریتانیا که فرمت روز/ماه/سال دارد، رشته به‌عنوان نهم آگوست تفسیر می‌شود. در Query دوم، با استفاده از فرهنگ انگلیسی آمریکا که فرمت ماه/روز/سال دارد، همان رشته به شکل متفاوتی، به‌عنوان هشتم سپتامبر، تفسیر می‌شود. این قابلیت کنترل دقیق بر اساس فرهنگ زبانی، یکی از مناسب‌ترین گزینه‌ها برای تفسیر داده‌های متنی وابسته به Culture را از TRY_PARSE می‌سازد.

تفاوت Culture و Style

TRY_CONVERT از پارامتر Style که یک عدد ثابت از پیش تعریف‌شده در SQL Server است استفاده می‌کند، در حالی که TRY_PARSE از نام واقعی Culture، مانند de-DE برای آلمانی آلمان، استفاده می‌کند. این تفاوت باعث می‌شود TRY_PARSE برای سناریوهایی که داده از کاربران یا سیستم‌هایی با تنظیمات زبانی مشخص و متنوع دریافت می‌شود، انعطاف بیشتری داشته باشد.

SELECT TRY_PARSE ( '1.234,56' AS DECIMAL(18,2) USING 'de-DE' ) AS GermanNumber;

در این مثال، فرمت آلمانی که از نقطه برای جداکننده هزارگان و از ویرگول برای جداکننده اعشار استفاده می‌کند، به‌درستی به یک عدد اعشاری استاندارد SQL Server تبدیل می‌شود. چنین قابلیتی در TRY_CONVERT یا TRY_CAST به این سادگی و با این دقت وجود ندارد.

کاربرد TRY_PARSE در پردازش داده چندزبانه

فرض کنید یک سازمان بین‌المللی داده فروش را از چند شعبه در کشورهای مختلف دریافت می‌کند و هر شعبه، بسته به تنظیمات محلی سیستم خود، اعداد را با فرمت متفاوتی ارسال می‌کند.

SELECT
    BranchCountry,
    RawAmount,
    CASE BranchCountry
        WHEN 'Germany' THEN TRY_PARSE ( RawAmount AS DECIMAL(18,2) USING 'de-DE' )
        WHEN 'USA' THEN TRY_PARSE ( RawAmount AS DECIMAL(18,2) USING 'en-US' )
        ELSE TRY_CAST ( RawAmount AS DECIMAL(18,2) )
    END AS ParsedAmount
FROM InternationalSalesStaging;

در این Query، بسته به کشور شعبه، از Culture مناسب برای تفسیر صحیح فرمت عددی استفاده می‌شود. این الگو در فرآیندهای Integration سازمان‌های چندملیتی که داده از منابع با تنظیمات زبانی متفاوت دریافت می‌کنند، ارزش عملی بالایی دارد. باید توجه داشت استفاده از یک Culture مشخص، مانند fa-IR برای فارسی، به‌تنهایی به معنای پشتیبانی از همه قالب‌های بومی یا تقویم‌های غیرمیلادی نیست؛ داده واقعی ورودی از سیستم‌های ایرانی ممکن است شامل ارقام فارسی یا عربی، جداکننده‌های متفاوت یا تاریخ شمسی باشد که هرکدام نیازمند بررسی و تست جداگانه با نمونه‌های واقعی داده منبع است، پیش از آنکه به Culture برای تفسیر صحیح آن اتکا شود.

مقایسه TRY_CONVERT، TRY_CAST و TRY_PARSE

برای جمع‌بندی تفاوت‌های این سه تابع، جدول زیر ویژگی‌های اصلی آن‌ها را در کنار هم قرار می‌دهد.

ویژگی TRY_CONVERT TRY_CAST TRY_PARSE
نسخه امن از CONVERT CAST PARSE
کنترل فرمت Style عددی ندارد Culture متنی
مناسب برای تبدیل با فرمت مشخص تبدیل ساده و استاندارد تبدیل وابسته به Culture
نوع ورودی Expression Expression String / NVARCHAR
ملاحظات Performance معمولاً مناسب معمولاً مناسب معمولاً پرهزینه‌تر

نکته مهمی که این جدول نشان می‌دهد این است که TRY_PARSE، برخلاف دو تابع دیگر، تنها ورودی از نوع رشته متنی می‌پذیرد و برای تبدیل بین دو نوع داده غیرمتنی، مانند تبدیل INT به DECIMAL، اصلاً کاربرد ندارد و باید از TRY_CONVERT یا TRY_CAST استفاده شود.

اشتباه رایج: استفاده از TRY_PARSE برای تبدیل‌های ساده غیرمرتبط با فرهنگ زبانی

یکی از اشتباهات رایج، استفاده از TRY_PARSE برای تبدیل‌های ساده‌ای است که هیچ وابستگی به فرهنگ زبانی ندارند، مانند تبدیل یک رشته عددی ساده انگلیسی به عدد صحیح.

SELECT TRY_PARSE ( '12345' AS INT ) AS ParsedNumber;
SELECT TRY_CAST ( '12345' AS INT ) AS CastedNumber;

از آنجا که TRY_PARSE برای پشتیبانی از فرهنگ‌های مختلف طراحی شده، این تابع برای تبدیل داده‌های متنی به کمک قابلیت‌های CLR در SQL Server پیاده‌سازی شده و در سناریوهای پردازش حجیم می‌تواند هزینه بیشتری نسبت به TRY_CAST و TRY_CONVERT داشته باشد. علاوه بر این، TRY_PARSE به CLR وابسته است و قابلیت اجرای Remote روی سروری که CLR موردنیاز را ندارد، ندارد؛ بنابراین در سناریوهای Linked Server و Remote Query باید این محدودیت را در طراحی Query در نظر گرفت. برای تبدیل‌های ساده که فرمت آن‌ها به‌طور طبیعی استاندارد و بدون ابهام فرهنگی است، استفاده از TRY_CAST یا TRY_CONVERT معمولاً انتخاب مناسب‌تری است.

مدیریت داده نامعتبر در ETL

از آنجا که هر سه تابع TRY در صورت شکست تبدیل، مقدار NULL بازمی‌گردانند، ترکیب آن‌ها با ISNULL یا COALESCE برای تعیین یک مقدار پیش‌فرض جایگزین، الگویی رایج در فرآیندهای پاک‌سازی داده است.

SELECT
    OrderID,
    TRY_CONVERT ( DATE, OrderDateText, 111 ) AS OrderDateSafe
FROM StagingOrders;

در بسیاری از فرآیندهای تحلیلی، نگه‌داشتن NULL معمولاً گزینه بهتری نسبت به قرار دادن یک تاریخ ساختگی مانند 1900-01-01 است، زیرا چنین مقداری در صورت ورود ناخواسته به محاسبات بعدی، می‌تواند به‌اشتباه به‌عنوان یک تاریخ واقعی تفسیر شود و کیفیت تحلیل را خدشه‌دار کند. اگر سیستم واقعاً به یک مقدار نشانگر نیاز دارد، بهتر است این وضعیت در یک ستون جداگانه، مانند یک Data Quality Flag یا ستون وضعیت، نگهداری شود، نه در قالب یک تاریخ ساختگی درون همان ستون داده اصلی.

SELECT
    OrderID,
    TRY_CONVERT ( DATE, OrderDateText, 111 ) AS OrderDateSafe,
    CASE
        WHEN OrderDateText IS NOT NULL
            AND TRY_CONVERT ( DATE, OrderDateText, 111 ) IS NULL
        THEN 1
        ELSE 0
    END AS IsInvalidDateFlag
FROM StagingOrders;

در این نسخه، ستون OrderDateSafe مقدار واقعی یا NULL را نگه می‌دارد و ستون جداگانه IsInvalidDateFlag به‌صراحت مشخص می‌کند که آیا مقدار اصلی نامعتبر بوده یا خیر، بدون آنکه داده اصلی با یک مقدار ساختگی آلوده شود.

یکی از کاربردهای عملی مهم این خانواده توابع، شناسایی رکوردهای دارای داده نامعتبر پیش از انتقال آن‌ها به جدول نهایی در یک فرآیند ETL.

SELECT
    OrderID,
    OrderDateText,
    RawAmount
FROM StagingOrders
WHERE TRY_CONVERT ( DATE, OrderDateText, 111 ) IS NULL
    OR TRY_CAST ( RawAmount AS DECIMAL(18,2) ) IS NULL;

این Query تمام رکوردهایی را که حداقل یکی از ستون‌های تاریخ یا مبلغ آن‌ها قابل تبدیل به نوع داده هدف نیست، شناسایی می‌کند. چنین Queryای می‌تواند بخشی از یک لایه اعتبارسنجی پیش از بارگذاری داده در جدول اصلی باشد، به‌طوری‌که تنها رکوردهای سالم وارد جدول نهایی شوند و رکوردهای مشکل‌دار در یک جدول خطا یا Log جداگانه ثبت شوند.

INSERT INTO DataQualityErrors ( SourceTable, RecordID, ErrorColumn, RawValue, ErrorDate )
SELECT
    'StagingOrders',
    OrderID,
    'OrderDateText',
    OrderDateText,
    SYSDATETIME()
FROM StagingOrders
WHERE TRY_CONVERT ( DATE, OrderDateText, 111 ) IS NULL
    AND OrderDateText IS NOT NULL;

این الگو به تیم‌های داده امکان می‌دهد نه‌تنها از توقف فرآیند ETL به دلیل داده نامعتبر جلوگیری کنند، بلکه به‌طور سیستماتیک کیفیت داده منبع را نیز رصد و مستند کنند.

نکته مهم دیگری که در طراحی این نوع Query باید در نظر گرفت، تفکیک NULL طبیعی از NULL ناشی از شکست تبدیل است.

SELECT
    OrderID,
    OrderDateText,
    CASE
        WHEN OrderDateText IS NULL THEN N'مقدار اصلی خالی است'
        WHEN TRY_CONVERT ( DATE, OrderDateText, 111 ) IS NULL THEN N'فرمت نامعتبر است'
        ELSE N'معتبر'
    END AS ValidationStatus
FROM StagingOrders;

این الگو به‌خصوص در Data Quality Pipeline اهمیت دارد، زیرا خروجی NULL توابع TRY به‌تنهایی نمی‌تواند مشخص کند که آیا داده اصلی از ابتدا NULL بوده یا تبدیل یک مقدار غیر NULL شکست خورده است. این تمایز برای گزارش‌دهی دقیق درباره کیفیت داده منبع ضروری است.

تفاوت توابع TRY با ISDATE و ISNUMERIC

پیش از معرفی خانواده توابع TRY، توابعی مانند ISDATE و ISNUMERIC برای بررسی معتبر بودن یک رشته پیش از تبدیل استفاده می‌شدند.

با ISDATE:
SELECT
    OrderDateText,
    CASE
        WHEN ISDATE ( OrderDateText ) = 1 THEN CONVERT ( DATE, OrderDateText )
        ELSE NULL
    END AS OrderDateSafe
FROM StagingOrders;

با TRY_CONVERT:
SELECT
    OrderDateText,
    TRY_CONVERT ( DATE, OrderDateText ) AS OrderDateSafe
FROM StagingOrders;

در بسیاری از سناریوهای اعتبارسنجی تاریخ، هر دو روش می‌توانند به نتیجه مشابهی برسند، اما TRY_CONVERT ساختار ساده‌تر و یکپارچه‌تری برای انجام هم‌زمان اعتبارسنجی و تبدیل ارائه می‌دهد، زیرا نیازی به دو مرحله جداگانه بررسی و سپس تبدیل ندارد. علاوه بر این، ISNUMERIC یک محدودیت شناخته‌شده دارد: این تابع برخی رشته‌های خاص مانند علائم پولی یا نماد علمی را به‌اشتباه به‌عنوان عدد معتبر تشخیص می‌دهد، در حالی که تلاش برای تبدیل واقعی آن‌ها به یک نوع عددی مشخص می‌تواند ناموفق باشد. TRY_CAST و TRY_CONVERT، به دلیل انجام تبدیل واقعی به‌جای صرفاً بررسی الگو، از این نظر قابل اعتمادتر از ISNUMERIC هستند.

Performance توابع TRY در SQL Server

هزینه واقعی TRY_CONVERT و TRY_CAST به نوع داده، حجم داده و شکل Query وابسته است و در بسیاری از سناریوها اختلاف آن‌ها با نسخه معمولی تبدیل، عامل اصلی Performance محسوب نمی‌شود؛ منطق داخلی تبدیل مشابه نسخه استاندارد است و تفاوت اصلی صرفاً در نحوه برخورد با شکست تبدیل است.

در مقابل، TRY_PARSE به دلیل استفاده از قابلیت‌های CLR معمولاً برای پردازش حجیم گزینه مناسبی نیست. در پردازش جداول بسیار بزرگ که TRY_PARSE روی میلیون‌ها رکورد اجرا می‌شود، این تفاوت Performance می‌تواند قابل توجه شود.

پرهزینه‌تر در حجم بالا اگر فرهنگ زبانی اهمیت نداشته باشد:
SELECT TRY_PARSE ( AmountText AS DECIMAL(18,2) USING 'en-US' )
FROM LargeStagingTable;

معمولاً مناسب‌تر در صورت عدم نیاز به فرهنگ زبانی خاص:
SELECT TRY_CAST ( AmountText AS DECIMAL(18,2) )
FROM LargeStagingTable;

توصیه کلی این است که TRY_PARSE تنها زمانی استفاده شود که واقعاً نیاز به تفسیر یک فرمت وابسته به فرهنگ زبانی خاص وجود دارد. برای تبدیل‌های ساده و استاندارد، به‌خصوص در پردازش حجم بالا، TRY_CAST یا TRY_CONVERT انتخاب مناسب‌تری هستند.

یکی از کاربردهای پیشرفته‌تر این توابع، تعریف یک ستون محاسباتی است که به‌طور خودکار مقدار یک ستون متنی را به نوع داده مناسب تبدیل می‌کند، بدون آنکه رکوردهای دارای داده نامعتبر باعث خطا در ساختار جدول شوند.

ALTER TABLE StagingOrders
ADD OrderDateParsed AS TRY_CONVERT ( DATE, OrderDateText, 111 );

این ستون به‌صورت Computed Column تعریف می‌شود و به‌طور پیش‌فرض مقدار آن به‌صورت فیزیکی در جدول ذخیره نمی‌شود، بلکه در هر بار خواندن محاسبه می‌شود. در صورت نیاز به ذخیره فیزیکی مقدار محاسبه‌شده، برای مثال برای Indexگذاری روی همین ستون، می‌توان بسته به شرایط و الزامات Determinism از گزینه PERSISTED استفاده کرد. با این تعریف، هر بار که رکورد جدیدی درج یا به‌روزرسانی می‌شود، مقدار OrderDateParsed به‌طور خودکار محاسبه می‌شود و در صورت نامعتبر بودن OrderDateText، مقدار NULL خواهد داشت، بدون آنکه عملیات INSERT یا UPDATE با خطا مواجه شود. این الگو به‌خصوص در جداول Staging که داده ورودی از منابع خارجی با کیفیت متغیر دریافت می‌شود، کاربرد عملی زیادی دارد.

اشتباهات رایج در استفاده از خانواده توابع TRY

استفاده از TRY_CAST برای تاریخ‌هایی با فرمت غیراستاندارد

از آنجا که TRY_CAST پارامتر Style ندارد و به تنظیمات Session مانند DATEFORMAT وابسته است، استفاده از آن برای تاریخ‌هایی با فرمت غیر پیش‌فرض Session می‌تواند نتیجه‌ای نادرست یا NULL غیرمنتظره تولید کند. در چنین شرایطی، TRY_CONVERT با Style مشخص یا TRY_PARSE با Culture مشخص، انتخاب مطمئن‌تری است.

استفاده گسترده از TRY_PARSE بدون نیاز واقعی به فرهنگ زبانی

استفاده از TRY_PARSE برای تبدیل‌های ساده که هیچ وابستگی فرهنگی ندارند، هزینه اجرایی غیرضروری به Query تحمیل می‌کند و در سناریوهای Remote Query نیز با محدودیت مواجه است. این تابع باید صرفاً برای سناریوهایی رزرو شود که تفسیر بر اساس یک فرهنگ زبانی خاص واقعاً موردنیاز است.

نادیده گرفتن تفاوت NULL طبیعی و NULL ناشی از شکست تبدیل

اگر ستون منبع خودش می‌تواند به‌طور طبیعی مقدار NULL داشته باشد، پس از عبور از TRY_CONVERT یا TRY_CAST، دیگر نمی‌توان تشخیص داد که آیا NULL نتیجه به دلیل NULL بودن داده اصلی است یا به دلیل شکست تبدیل یک مقدار غیر NULL. در سناریوهایی که این تمایز اهمیت دارد، باید یک شرط جداگانه برای بررسی NULL بودن مقدار اصلی، پیش از یا مستقل از عملیات تبدیل، لحاظ شود.

استفاده از توابع TRY به‌جای رفع مشکل ریشه‌ای در فرآیند تولید داده

مشابه بسیاری از توابع مدیریت خطا، توابع TRY نیز گاهی صرفاً برای پنهان کردن یک مشکل ساختاری در فرآیند تولید یا Import داده استفاده می‌شوند. اگر بخش بزرگی از داده ورودی به‌طور مداوم قابل تبدیل نیست، باید فرآیند تولید داده در سیستم منبع یا مرحله ETL بررسی و اصلاح شود، نه اینکه صرفاً با NULL کردن مقادیر نامعتبر، مشکل زیر فرش پنهان شود.

Best Practiceهای استفاده از خانواده توابع TRY

برای تبدیل ساده و استاندارد نوع داده که فرمت ورودی وابستگی به فرهنگ زبانی ندارد، TRY_CAST به دلیل Syntax ساده معمولاً انتخاب مناسبی است.

برای تبدیل تاریخ یا رشته‌هایی با فرمت مشخص و ثابت که با یکی از Styleهای استاندارد SQL Server مطابقت دارد، TRY_CONVERT با تعیین صریح پارامتر Style، انتخاب مطمئن‌تری نسبت به TRY_CAST است، زیرا مستقل از تنظیمات Session عمل می‌کند.

TRY_PARSE باید تنها در سناریوهایی استفاده شود که واقعاً نیاز به تفسیر داده بر اساس یک فرهنگ زبانی خاص و متغیر وجود دارد، و باید به محدودیت آن در سناریوهای Remote Query و هزینه اجرایی ناشی از CLR توجه شود. پیش از اتکا به یک Culture خاص برای داده‌های بومی، باید فرمت واقعی داده منبع با نمونه‌های واقعی آزمایش شود.

در فرآیندهای ETL و پاک‌سازی داده، ترکیب توابع TRY با یک لایه ثبت خطا، مانند درج رکوردهای مشکل‌دار در یک جدول Log مجزا، به تیم‌های داده امکان می‌دهد کیفیت داده منبع را به‌طور سیستماتیک رصد کنند، نه صرفاً آن را نادیده بگیرند.

به‌جای جایگزین کردن مقادیر نامعتبر با یک مقدار ساختگی درون همان ستون داده، بهتر است وضعیت اعتبار داده در یک ستون یا Flag جداگانه نگهداری شود تا NULL واقعی حفظ شده و ریسک تفسیر نادرست یک مقدار نشانگر به‌عنوان داده واقعی کاهش یابد.

پیش از استفاده گسترده از TRY_PARSE روی جداول بزرگ، هزینه اجرایی آن باید با ابزارهایی مانند Execution Plan و آمار زمان اجرا مقایسه شود، به‌خصوص در مقایسه با معادل‌های TRY_CONVERT یا TRY_CAST که ممکن است برای همان سناریو کافی باشند.

جمع‌بندی

TRY_CONVERT، TRY_CAST و TRY_PARSE سه ابزار مکمل در SQL Server هستند که همگی هدف مشترک تبدیل امن‌تر نوع داده، بدون توقف اجرای Query در برابر شکست معمول تبدیل، را دنبال می‌کنند، اما هرکدام برای سناریوی متفاوتی مناسب‌ترند. TRY_CAST برای تبدیل‌های ساده و استاندارد گزینه‌ای مناسب است، هرچند رفتار آن در تفسیر تاریخ می‌تواند به تنظیمات Session وابسته باشد. TRY_CONVERT با پشتیبانی از پارامتر Style، کنترل دقیق‌تر و مستقل از Session روی فرمت‌های تاریخ و رشته ثابت فراهم می‌کند. TRY_PARSE با پشتیبانی از Culture، مناسب‌ترین ابزار برای تفسیر داده وابسته به فرهنگ زبانی متغیر است، اما به دلیل وابستگی به CLR هزینه اجرایی بالاتری دارد و در سناریوهای Remote Query نیز محدودیت دارد، بنابراین نباید بدون نیاز واقعی استفاده شود.

در پروژه‌های سازمانی که با داده ورودی از منابع متنوع و با کیفیت متغیر سروکار دارند، استفاده هوشمندانه از این سه تابع، همراه با یک لایه ثبت و رصد خطای داده، می‌تواند فرآیندهای ETL را از یک نقطه شکست شکننده به یک سیستم پایدارتر و قابل نظارت تبدیل کند.

سوالات متداول FAQ

تفاوت اصلی TRY_CONVERT و TRY_CAST چیست؟
TRY_CONVERT پارامتر Style اختیاری دارد که امکان کنترل دقیق و مستقل از تنظیمات Session روی فرمت تبدیل، به‌خصوص برای تاریخ، را فراهم می‌کند. TRY_CAST چنین پارامتری ندارد و تفسیر آن می‌تواند به تنظیماتی مانند DATEFORMAT وابسته باشد.

چرا TRY_PARSE برای تبدیل‌های ساده توصیه نمی‌شود؟
زیرا TRY_PARSE برای پشتیبانی از فرهنگ‌های زبانی مختلف طراحی شده و از قابلیت‌های CLR استفاده می‌کند که هزینه اجرایی آن معمولاً بیشتر از TRY_CAST یا TRY_CONVERT است و در سناریوهای Remote Query نیز محدودیت دارد. برای تبدیل‌های ساده و بدون وابستگی فرهنگی، توابع دیگر انتخاب مناسب‌تری هستند.

آیا توابع TRY همیشه از بروز هر نوع خطا جلوگیری می‌کنند؟
خیر. توابع TRY شکست معمول تبدیل داده را به NULL تبدیل می‌کنند، اما اگر تبدیل بین دو نوع داده از اساس در SQL Server مجاز نباشد، همچنان می‌تواند خطای اجرایی رخ دهد. این توابع جایگزین طراحی صحیح Schema و بررسی سازگاری نوع داده نیستند.

چگونه می‌توان بین NULL طبیعی و NULL ناشی از شکست تبدیل تمایز قائل شد؟
با افزودن یک شرط جداگانه که ابتدا NULL بودن مقدار اصلی ورودی را بررسی می‌کند و سپس نتیجه تابع TRY را ارزیابی می‌کند، مانند استفاده از یک عبارت CASE که این دو حالت را به‌طور مجزا مدیریت کند.

آیا استفاده از توابع TRY در ستون‌های محاسباتی مجاز است؟
بله. یکی از کاربردهای رایج این توابع، تعریف ستون‌های محاسباتی است که به‌طور خودکار داده متنی را به نوع مناسب تبدیل می‌کنند. این ستون‌ها به‌صورت پیش‌فرض Virtual هستند و در صورت نیاز به ذخیره فیزیکی، مثلاً برای Indexگذاری، باید از گزینه PERSISTED استفاده شود.

پاک‌سازی و اعتبارسنجی داده در SQL Server را اصولی انجام دهید

اگر داده‌های سازمان شما از Excel، CSV، API یا سیستم‌های Legacy وارد SQL Server می‌شوند و خطاهای تبدیل نوع داده باعث شکست فرآیندهای ETL، ورود داده‌های نامعتبر یا کاهش کیفیت گزارش‌ها شده‌اند، استفاده از توابعی مانند TRY_CONVERT، TRY_CAST و TRY_PARSE تنها بخشی از راه‌حل است.

توسعه فناوری اطلاعات لاندا می‌تواند در طراحی و بهینه‌سازی فرآیندهای پاک‌سازی و اعتبارسنجی داده، کنترل کیفیت داده، طراحی ETL و پیاده‌سازی راهکارهای SQL Server به سازمان شما کمک کند تا داده‌های نامعتبر پیش از ورود به لایه‌های عملیاتی و تحلیلی شناسایی و مدیریت شوند.

اگر کیفیت داده و پایداری فرآیندهای ETL برای سازمان شما اهمیت دارد، با لاندا در ارتباط باشید.

No comment

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *