将nvarchar值转换为数据类型int时转换失败

时间:2013-02-27 15:18:56

标签: sql sql-server sql-server-2005

我有一个查询,我正在尝试检查scode列中的一系列代码。问题是scode列包含一些nvarchar字符,以及找到它们时的错误。

如何在不返回错误的情况下运行以下查询。

SELECT dtExpires, dtFirst
FROM Customers
WHERE (scode BETWEEN 10 AND 100) OR
      (scode BETWEEN 500 AND 600)

我收到错误:

  

将nvarchar值转换为数据类型int

时转换失败

3 个答案:

答案 0 :(得分:7)

如果你不能修复那些你应该做的数据类型......

唯一可靠的短路方法是将过滤后的结果填充到#temp表中。否则,您无法控制评估顺序。即使您使用子查询或CTE来过滤ISNUMERIC() = 1“first”的行,SQL Server也可能首先评估BETWEEN条件,但仍然会失败并出现相同的错误。这可能不会始终发生,但这是保证避免它的唯一方法:

SELECT dtExpires, dtFirst, scode
INTO #t
FROM dbo.Customers
WHERE scode NOT LIKE '%[^0-9]%'; -- this assumes no decimals allowed

SELECT dtExpires, dtFirst
FROM #t
WHERE (scode BETWEEN 10  AND 100) 
   OR (scode BETWEEN 500 AND 600);

DROP TABLE #t;

答案 1 :(得分:3)

这里的最终问题是您将这些数值存储为nvarchar。这是有问题的,首先是速度的几个原因。有很多很棒的文件和答案显示出这种情况很多就是Website

整数值小于字符串,每个页面可以比使用nvarchar更适合,并且数学更容易在整数上完成。尝试一点实验转到SQLFiddle并输入您的表并给它一些值并运行您的查询。然后尝试将该列更改为整数值并运行相同的查询,它不仅会运行得更快,而且您当前的SELECT语句将正常运行。如果您需要加入此信息,整数也会更快。

我不完全确定天气与否,你有能力做到这一点,但它肯定会解决你的问题并提高你的数据库性能。

答案 2 :(得分:1)

也许使用像

这样的东西
SELECT        dtExpires, dtFirst
FROM            Customers
WHERE        ( cast(fnRemoveNonNumericCharacters(scode) as int) BETWEEN 10 AND 100) OR
                     (cast(fnRemoveNonNumericCharacters(scode) as int)BETWEEN 500 AND 600)

其中函数是:

CREATE Function [fnRemoveNonNumericCharacters](@strText VARCHAR(1000))
RETURNS VARCHAR(1000)
AS
BEGIN
    WHILE PATINDEX('%[^0-9]%', @strText) > 0
    BEGIN
        SET @strText = STUFF(@strText, PATINDEX('%[^0-9]%', @strText), 1, '')
    END
    RETURN @strText
END

或者如果你想排除scode不是数字的那些条目make也是一个bool返回函数,它会告诉你它是否有非数字字符并将它放在where子句中。

也可以解决这个问题的方法:(由Aron启发了一点点

SELECT        dtExpires, dtFirst
FROM            Customers
WHERE        (( case when scode LIKE '%[^0-9]%' then 0 else scode end BETWEEN 10 AND 100) OR
                     (case when scode LIKE '%[^0-9]%' then 0 else scode end BETWEEN 500 AND 600))
and scode not like '%[^0-9]%'