SQL Server 2008 R2的bug还是什么?

时间:2013-01-22 21:44:40

标签: sql-server sql-server-2008

我正在观察一种奇怪的行为。以下与将nvarchar的子字符串转换为tinyint相关的代码运行正常:

DECLARE @s nvarchar(50) = N'Line 1'
DECLARE @n tinyint = SUBSTRING(@s, 6, 10)

SELECT
        N'Line 1' AS explicit_nvarchar,
        @s AS nvarchar_variable,
        SUBSTRING(@s, 6, 10) AS nvarchar_substring
        , @n AS tinyint_var_converted_earlier
        , CAST(SUBSTRING(@s, 6, 10) AS tinyint) AS cast_sub_var
        , CAST(SUBSTRING(N'Line 1', 6, 10) AS tinyint) AS cast_nvarchar_substr

我可以在Microsoft SQL Server Management Studio中观察以下输出:

enter image description here

但是,如果注释行被取消注释,那么尝试使用表中的SELECT的代码将失败:

Select 
    [order].[identifier] As [order_identifier],
    [plan_data].[starts_on] As [from],
    [plan_data].[ends_on] As [to],
    [workplace].[identifier] AS line_identifier,
    SUBSTRING([workplace].[identifier], 6, 10) AS line_no_str
    --, CAST(SUBSTRING([workplace].[identifier], 6, 10) AS int) AS line_no
From 
    ...

用评论线... enter image description here

但使用未注释的行(转换为tinyintint)...

enter image description here

更新:奇怪。我已将最后一行添加到WHERE以检查是否所有行 包含'Line...

Where
    [plan].[identifier] = @lPlanIdentifier And
    (
        [plan_data].[starts_on] Between @fromUTC And @toUTC Or
        [plan_data].[ends_on] Between @fromUTC And @toUTC)
    AND LEFT([workplace].[identifier], 4) = N'Line'

......突然间它也与未注释的线一起工作。我怎样才能发现导致问题的原因?

更新2:我应该完全按照发布时的Hamlet Hakobyan's answer进行操作。当看到桌子内部时,我可以看到:

enter image description here

3 个答案:

答案 0 :(得分:4)

identifier列中有SUBSTRING([workplace].[identifier], 6, 10)返回ined的值。

尝试此查询:

SELECT * FROM [workplace]
WHERE SUBSTRING([identifier], 6, 10) = N'ined'

答案 1 :(得分:1)

如评论和其他答案所示,对于未能投放到[workplace].[identifier]的一行或多行,您在INT中有一个值。将以下内容添加到WHERE子句时,在SELECT子句中转换之前删除了包含此数据的行:

LEFT([workplace].[identifier], 4) = N'Line'

运行以下内容以获取[workplace].[identifier]

中不同的值列表
SELECT DISTINCT [workplace].[identifier]
FROM [workplace]

答案 2 :(得分:1)

每当您将varchar转换为数字时,找到数据的最简单方法是使用IsNumeric。但IsNumeric并不代表IsInteger,因此G Mastros

this answer所述的科学或十进制格式的删除值得
SELECT
    [order].[identifier] As [order_identifier],
    [plan_data].[starts_on] As [from],
    [plan_data].[ends_on] As [to],
    [workplace].[identifier] AS line_identifier,
    SUBSTRING([workplace].[identifier], 6, 10) AS line_no_str
    --, CAST(SUBSTRING([workplace].[identifier], 6, 10) AS int) AS line_no
FROM
  ...

WHERE 

   IsNumeric(SUBSTRING([workplace].[identifier], 6, 10) + '.0e0') = 0

如果您无法修复它,但是您可以使用默认值,那么只有在合法的情况下才能使用case语句进行转换。

SELECT
    [order].[identifier] As [order_identifier],
    [plan_data].[starts_on] As [from],
    [plan_data].[ends_on] As [to],
    [workplace].[identifier] AS line_identifier,
    CASE WHEN IsNumeric(SUBSTRING([workplace].[identifier], 6, 10) + '.0e0') = 1
             THEN CAST(SUBSTRING([workplace].[identifier], 6, 10) AS int) 
             ELSE Null --Default to null in this example
    END as line_no