我有一个查询,我正在尝试检查scode
列中的一系列代码。问题是scode
列包含一些nvarchar字符,以及找到它们时的错误。
如何在不返回错误的情况下运行以下查询。
SELECT dtExpires, dtFirst
FROM Customers
WHERE (scode BETWEEN 10 AND 100) OR
(scode BETWEEN 500 AND 600)
我收到错误:
将nvarchar值转换为数据类型int
时转换失败
答案 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]%'