【问题标题】:SQL CLR Function to replace TRY_CONVERTSQL CLR 函数替换 TRY_CONVERT
【发布时间】:2014-04-30 15:43:35
【问题描述】:

我正在尝试编写自己的 CLR 函数来替换内置的“TRY_CONVERT”sql 函数,因为我需要更多地控制日期和数字的转换方式(例如,内置函数无法处理包含科学的 DECIMAL 转换符号)。

我试过这个:

[SqlFunction(IsDeterministic = true, IsPrecise = true)]
public static object TRY_CONVERT(SqlDbType type, SqlString input)
{
    switch (type)
    {
        case SqlDbType.Decimal:
            decimal decimalOutput;
            return decimal.TryParse(input.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out decimalOutput) ? decimalOutput : (decimal?)null;
        case SqlDbType.BigInt:
            long bigIntOutput;
            return long.TryParse(input.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out bigIntOutput) ? bigIntOutput : (long?)null;
        case SqlDbType.Date:
        case SqlDbType.DateTime:
        case SqlDbType.DateTime2:
            DateTime dateTimeOutput;
            return DateTime.TryParse(input.Value, CultureInfo.CreateSpecificCulture("en-GB"), DateTimeStyles.None, out dateTimeOutput) ? dateTimeOutput : (DateTime?)null;
        case SqlDbType.NVarChar:
        case SqlDbType.VarChar:
            return string.IsNullOrWhiteSpace(input.Value) ? null : input.Value;
        default:
            throw new NotImplementedException();
    }
}

但我构建时它不喜欢SqlDbType 类型。

是否可以传递内置函数中使用的“target_type”,还是必须将其作为字符串传递或为我要使用的每种类型创建单独的 TRY_CONVERT 方法?

【问题讨论】:

    标签: c# sql-server-2012 sqlclr


    【解决方案1】:

    object 返回类型转换为sql_variant,因此必须在 SQL 中显式转换为正确的数据类型,所以我认为解决此问题的唯一方法是创建具有正确返回类型的单独 CLR 方法,例如这个:

    [SqlFunction(IsDeterministic = true, IsPrecise = true)]
    public static SqlDecimal TRY_CONVERT_DECIMAL(SqlString input)
    {
        decimal decimalOutput;
        return !input.IsNull && decimal.TryParse(input.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out decimalOutput) ? decimalOutput : SqlDecimal.Null;
    }
    
    [SqlFunction(IsDeterministic = true, IsPrecise = true)]
    public static SqlInt64 TRY_CONVERT_BIGINT(SqlString input)
    {
        long bigIntOutput;
        return !input.IsNull && long.TryParse(input.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out bigIntOutput) ? bigIntOutput : SqlInt64.Null;
    }
    
    [SqlFunction(IsDeterministic = true, IsPrecise = true)]
    public static SqlDateTime TRY_CONVERT_DATE(SqlString input)
    {
        var minSqlDateTime = new DateTime(1753, 1, 1, 0, 0, 0, 0);
        var maxSqlDateTime = new DateTime(9999, 12, 31, 23, 59, 59, 0);
        DateTime dateTimeOutput;
        return !input.IsNull && DateTime.TryParse(input.Value, CultureInfo.CreateSpecificCulture("en-GB"), DateTimeStyles.None, out dateTimeOutput) &&
            dateTimeOutput >= minSqlDateTime && dateTimeOutput <= maxSqlDateTime ? dateTimeOutput : SqlDateTime.Null;
    }
    
    [SqlFunction(IsDeterministic = true, IsPrecise = true)]
    public static SqlString TRY_CONVERT_NVARCHAR(SqlString input)
    {
        return input.IsNull || string.IsNullOrWhiteSpace(input.Value) ? SqlString.Null : input.Value;
    }
    

    【讨论】:

    • 我同意这是最好的方法。由于 SQLCLR API 不允许重载,因此您确实没有太多选择。使用 object / SQL_VARIANT 也存在问题,因为至少对于许多甚至大多数目标数据类型而言,都会有一定的性能损失。
    猜你喜欢
    • 2019-12-31
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 2011-06-24
    • 1970-01-01
    • 2015-12-02
    • 2014-01-27
    相关资源
    最近更新 更多