2

我有一个查询,我正在尝试检查scode列中的代码范围。问题是该scode列包含一些 nvarchar 字符,并且在找到它们时会出错。

如何运行以下查询而不返回错误。

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

我收到的错误:

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

4

3 回答 3

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;
于 2013-02-27T15:45:12.670 回答
3

您的最终问题是您将这些数值存储为nvarchar. 这是有问题的,首先是速度。那里有大量出色的文档和答案表明本网站上的许多情况就是如此。

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

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

于 2013-02-27T15:45:42.600 回答
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 不是数字的条目,还可以创建一个 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]%'
于 2013-02-27T15:26:43.103 回答