我有一个奇怪的问题,当在类型转换varchar列上执行聚合函数时,我收到“消息8114,级别16,状态5,第1行。将数据类型nvarchar转换为bigint时出错。” query where子句应该过滤掉非数字值。
表结构类似于:
IF EXISTS (SELECT * FROM sys.all_objects ao WHERE ao.name = 'Identifier' AND ao.type = 'U') BEGIN DROP TABLE Identifier END
IF EXISTS (SELECT * FROM sys.all_objects ao WHERE ao.name = 'IdentifierType' AND ao.type = 'U') BEGIN DROP TABLE IdentifierType END
CREATE TABLE IdentifierType
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[Style] [int] NULL,
CONSTRAINT [PK_IdentifierType_ID] PRIMARY KEY CLUSTERED ([ID] ASC)
) ON [PRIMARY]
CREATE TABLE Identifier
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[IdentifierTypeID] [int] NOT NULL,
[Value] [nvarchar](4000) NOT NULL,
CONSTRAINT [PK_Identifier_ID] PRIMARY KEY CLUSTERED ([ID] ASC)
) ON [PRIMARY]
ALTER TABLE Identifier WITH CHECK ADD CONSTRAINT [FK_Identifier_IdentifierTypeID] FOREIGN KEY([IdentifierTypeID]) REFERENCES IdentifierType ([ID])
GO
Identifier.Value是一个VARCHAR列,它可以并且确实包含非数字数据。将查询过滤为IdentifierType.Style = 0应该意味着'Value'仅返回整数的字符串表示。下面的查询失败,显示“消息8114,级别16,状态5,第1行。将数据类型nvarchar转换为bigint时出错。”
SELECT
MAX(CAST(Value AS BIGINT))
FROM
Identifier i,
IdentifierType it
WHERE
i.IdentifierTypeID = it.ID AND
it.Style = 0
如果我扩展WHERE子句以包含'AND ISNUMERIC(i.Value)= 1',它将返回最大整数值。这对我来说意味着我的结果集中有一个非数字字符串。然而我没有从中返回任何行:
SELECT
*
FROM
Identifier i,
IdentifierType it
WHERE
i.IdentifierTypeID = it.ID AND
it.Style = 0 AND
ISNUMERIC(i.Value) <> 1
我一直无法识别绊倒类型转换的行。上面的查询应该暴露了异常行。此外,也没有空字符串或极长字符串(最大字符串长度为6个字符)
MSSQL是否可能尝试对所有行执行CAST而不是先通过WHERE子句进行过滤?
或者有其他人见过类似的东西吗?
还有第二种方法是将查询组件实例化为临时表,然后从中选择MAX值。
SELECT
Value
INTO
IdentifierClone
FROM
Identifier i,
IdentifierType it
WHERE
i.IdentifierTypeID = it.ID AND
it.Style = 0
SELECT MAX(CAST(Value as BIGINT)) FROM IdentifierClone
但子查询不起作用。
任何帮助或想法都将不胜感激。
答案 0 :(得分:0)
尝试使用REGEX表达式查找问题记录。这是一个ISNUMERIC没有检测到问题但是正则表达式确实
的例子CREATE TABLE tst (value nvarchar(4000))
INSERT INTO tst select '£'
-- Record found ...
SELECT * FROM tst WHERE value NOT LIKE '%[0-9]%'
-- No record found ...
SELECT * from tst where isnumeric(value) <> 1