Sql server ORDERBY子句中的强制转换错误

Sql server ORDERBY子句中的强制转换错误,sql-server,sql-server-2016,Sql Server,Sql Server 2016,我有一个导致错误的查询: 无法从nvarchar转换为bigint 但仅限于按区域排序 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

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

无法从nvarchar转换为bigint

但仅限于按区域排序

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)
如果我按注释掉
顺序,它就可以正常工作。顶部浇铸工作并使用相同的数据。显示的数据为:

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

关于它为什么在
SELECT
上转换而不是在
orderby
上转换的原因,有什么想法吗?

您的查询返回的是
前25个
,但当您
orderby
时,您会得到一个转换错误。如果您按
删除
订单,您将获得不同的数据集(显然是…),但没有转换错误

强制转换时,必须首先转换所有值,然后进行排序。因此,在您的值列表中的某个地方,有一些东西无法转换为
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.
*/

您的查询返回的是前25个
项,但当您按
项下订单时,会出现转换错误。如果您按
删除
订单,您将获得不同的数据集(显然是…),但没有转换错误

强制转换时,必须首先转换所有值,然后进行排序。因此,在您的值列表中的某个地方,有一些东西无法转换为
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.
*/

感谢大家的回复,但由于某种原因,
orderby
子句中没有转换我的值。有效的方法是把所有的东西都放到临时表中,然后从那里订购

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

因为出于某种原因,它并没有对某些类型和其他类型的
orderby
施压。但它允许在
选择上施压,然后我把所有东西都放在临时表上,并用它来订购书籍。这就是我的场景的工作原理

谢谢大家的回复,但由于某种原因,
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

因为出于某种原因,它并没有对某些类型和其他类型的
orderby
施压。但它允许在
选择上施压,然后我把所有东西都放在临时表上,并用它来订购书籍。这就是我的场景的工作原理

只需按1给出
…顺序即可。删除强制转换,您有一个无法转换为大整数的值。为什么在订单类别中有强制转换?这将破坏使用索引的希望…不要在条件或订单的左侧使用任何函数。前25个结果(无序)都可以强制转换为bigint,这不会导致错误。当您选择排序时,它必须在排序之前将它们全部转换,并且其中至少有一个值不能转换为bigint。这会导致错误。所有行都必须转换为BigInt,以便TOP子句知道返回哪25行。要识别问题,请尝试“从TableName中选择AttrValue,其中IsNumeric(AttrValue)=0'对于给定的AttrName,此特定类型只有12个值,有或没有前25个值,它给出的值相同。SELECT AttrValue为我提供了上面包含的值。只需尝试按1给出
…order by;
。删除强制转换,您有一个无法转换为大整数的值。为什么在order clase中有强制转换,这将取消希望使用索引…不要在条件或顺序的左侧使用任何函数,以前25个结果为准(无序)都可以转换为bigint,这不会导致错误。当您选择排序时,它必须在排序之前将它们全部转换,并且其中至少有一个值不能转换为bigint。这会导致错误。所有行都必须转换为bigint,以便TOP子句知道返回哪25行。要确定问题,请尝试“从TableName中选择AttrValue,其中IsNumeric(AttrValue)=0'此特定类型对于给定的AttrName只有12个值,无论是否有前25个值,它都会给出相同的值。SELECT AttrValue为我提供了上面包含的值。如果您想知道错误值是什么,请选择“问题值”作为mycl,将tblattributevalue中的ATTRVAL作为attVal,使用(NOLOCK)内部连接TbLatAttribute作为att WITH(NOLOCK)在Att.AttrID=attVal.AttrID和Att.AttrName='Rank Gold'左连接#在P.BookID=attVal.BookID上作为P记账,其中attVal.GenreID=@GenreID和attVal.Active=1,Att.Active=1,P.BookID不为NULL且为数值(AttrValue)!=0实际上,
ISNUMERIC()=0
特别表示“返回非数值的值”,即
ISNUMERIC('123t5')
=0,因此我编写的查询应该返回有问题的值。列的数据类型为NVARCHAR,使用ISNUMERIC时不返回任何值。使用时!=,就像@granadaCoder建议的那样,它返回值。但是,我们希望设置的结果是按值排序的。这一特定体裁,只有12本书以“排名金牌”作为书名。我可以看到上面列出的返回值,它们只有数字。《精选》的演员阵容很好,但《订购人》却没有。现在我很困惑。。。我们在谈论SQL Server,对吗?如果我创建一个包含NVARCHAR(55)列的表,并插入两行,一行只包含数字,另一行包含一些其他字符,那么
ISNUMERIC()
函数