ORDER BY子句中的强制转换错误

时间:2017-02-21 17:58:56

标签: sql-server sql-server-2016

我有这个导致错误的查询:

  

无法从nvarchar转换为bigint

但仅限于ORDER BY区域。

SELECT TOP (25)  
    CAST(AttrValue AS BIGINT) AttrValue 
FROM 
    tblattributevalue AS attVal WITH (NOLOCK)
INNER JOIN 
    tblattribute AS att WITH (NOLOCK) ON Att.AttrID = attVal.AttrID
                                      AND att.AttrName = 'Rank Gold'
LEFT JOIN 
    #books AS P ON P.BookID = attVal.BookId
WHERE 
    attVal.GenreID = @GenreID
    AND attVal.Active = 1
    AND att.Active = 1
    AND P.BookID IS NOT NULL
ORDER BY 
    CAST(AttrValue AS BIGINT)

如果我发表评论ORDER BY,它就可以了。顶部转换工作并使用相同的数据。显示的数据是:

AttrValue:
28,
24,
2,
6,
89,
27,
1,
4,
234,
3,
7,
9 

关于为什么它会在SELECT而非ORDER BY上转换的任何想法?

2 个答案:

答案 0 :(得分:2)

您的查询返回TOP 25,但当您ORDER BY时,您会收到转化错误。如果删除ORDER BY,则会得到一组不同的数据(显然......),但没有转换错误。

投射时,必须先转换所有值,然后再进行排序。因此,在值列表中的某处,有些内容无法转换为BIGINT数据类型。

尝试运行此查询:

SELECT AttrValue 
FROM tblattributevalue AS attVal WITH (NOLOCK)
INNER JOIN tblattribute AS att WITH (NOLOCK) ON Att.AttrID = attVal.AttrID
            AND att.AttrName = 'Rank Gold'
LEFT JOIN #books AS P ON P.BookID = attVal.BookId
WHERE attVal.GenreID = @GenreID
AND attVal.Active = 1
AND att.Active = 1
AND P.BookID IS NOT NULL
AND ISNUMERIC(AttrValue) = 0

修改

检查时另一个重要的考虑因素是某些特殊字符(如逗号,句点,美元符号和连字符)会计为数值,但可能会对某些转换造成问题。例如,运行:

CREATE TABLE NumericTestTable (String NVARCHAR(55))
;
INSERT INTO NumericTestTable (string) VALUES (N'1234567890')
;
INSERT INTO NumericTestTable (string) VALUES (N'$1234567890')
;
INSERT INTO NumericTestTable (string) VALUES (N'12.34567890')
;
INSERT INTO NumericTestTable (string) VALUES (N'-1234567890')
;
INSERT INTO NumericTestTable (string) VALUES (N't1234567890')
;
INSERT INTO NumericTestTable (string) VALUES (N'1*234567890')
;
INSERT INTO NumericTestTable (string) VALUES (N'@1234567890')
;
INSERT INTO NumericTestTable (string) VALUES (N'#1234567890')
;
SELECT string, ISNUMERIC(string) FROM NumericTestTable
;
SELECT string, ISNUMERIC(string), CAST(string AS BIGINT) 
FROM NumericTestTable 
WHERE ISNUMERIC(string) = 1
; 
/* Returns error: 
Error converting data type nvarchar to bigint.. 
Error 8114. SQLSTATE 42000. Severity 16. MsgState 5. Line 1.
*/

答案 1 :(得分:0)

感谢大家的回复,但由于某些原因,我的值没有转换ORDER BY子句。什么工作是将所有东西放入临时表,然后从那里订购。

SELECT 
CAST(AttrValue as BIGINT) AttrValue
,BookID
INTO #sortBooks
FROM tblattributevalue AS attVal WITH (NOLOCK)
INNER JOIN tblattribute AS att WITH (NOLOCK) ON Att.AttrID = attVal.AttrID
            AND att.AttrName = 'Rank Gold'
LEFT JOIN #books AS P ON P.BookID = attVal.BookId
WHERE attVal.GenreID = @GenreID
AND attVal.Active = 1
AND att.Active = 1
AND P.BookID IS NOT NULL

然后,我抓住了要订购的那些值。

SELECT TOP (25) BookID
FROM #sortBooks
ORDER BY AttValue

由于某种原因,它不会在某些类型的ORDER BY上投射,而其他类型则是如此。但它允许在SELECT上进行投射,然后我将所有内容放在临时表上并使用它来订购书籍。这是我的方案的工作。