2

我正在观察一种奇怪的行为。以下与 to 的子字符串转换相关的代码可以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 中观察到以下输出:

在此处输入图像描述.

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 
    ...

带有注释行... 在此处输入图像描述

但带有未注释的行(用于转换为tinyintor int)...

在此处输入图像描述

更新:奇怪。我已将最后一行添加到 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'

...突然之间,它也适用于未注释的行。我怎样才能发现导致问题的原因?

Update2:我应该完全按照Hamlet Hakobyan 的答案发布。当查看表格内部时,我可以看到:

在此处输入图像描述

4

3 回答 3

4

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

试试这个查询:

SELECT * FROM [workplace]
WHERE SUBSTRING([identifier], 6, 10) = N'ined'
于 2013-01-22T21:53:42.930 回答
1

如评论和其他答案所示,您有一个[workplace].[identifier]或多行的值,该值无法转换为INT. 当您将以下内容添加到WHERE子句时,您在子句中转换之前消除了包含此数据的行SELECT

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

运行以下命令以获取不同的值列表[workplace].[identifier]

SELECT DISTINCT [workplace].[identifier]
FROM [workplace]
于 2013-01-22T22:19:29.960 回答
1

每当您将 varchar 转换为数字时出现错误,查找数据的最简单方法是使用IsNumeric. 但是IsNumeric并不意味着它值得删除G Mastros此答案IsInteger中描述的科学或十进制格式

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
于 2013-01-22T22:22:11.240 回答