Microsoft SQL Server 2008(SP1),出现意外的“转换失败”错误。
不太清楚如何描述这个问题,所以下面是一个简单的例子。 CTE使用搜索条件提取某些ID的数字部分,以确保数字部分实际存在。然后使用CTE找到最低的未使用序列号(种类):
CREATE TABLE IDs (ID CHAR(3) NOT NULL UNIQUE);
INSERT INTO IDs (ID) VALUES ('A01'), ('A02'), ('A04'), ('ERR');
WITH ValidIDs (ID, seq)
AS
(
SELECT ID, CAST(RIGHT(ID, 2) AS INTEGER)
FROM IDs
WHERE ID LIKE 'A[0-9][0-9]'
)
SELECT MIN(V1.seq) + 1 AS next_seq
FROM ValidIDs AS V1
WHERE NOT EXISTS (
SELECT *
FROM ValidIDs AS V2
WHERE V2.seq = V1.seq + 1
);
错误是'将varchar值'RR'转换为数据类型int时转换失败。'
我无法理解为什么应该考虑将值ID = 'ERR'
用于转换,因为谓词ID LIKE 'A[0-9][0-9]'
应该已从结果集中删除了无效行。
当基表用等效的CTE代替时,问题就会消失,即
WITH IDs (ID)
AS
(
SELECT 'A01'
UNION ALL
SELECT 'A02'
UNION ALL
SELECT 'A04'
UNION ALL
SELECT 'ERR'
),
ValidIDs (ID, seq)
AS
(
SELECT ID, CAST(RIGHT(ID, 2) AS INTEGER)
FROM IDs
WHERE ID LIKE 'A[0-9][0-9]'
)
SELECT MIN(V1.seq) + 1 AS next_seq
FROM ValidIDs AS V1
WHERE NOT EXISTS (
SELECT *
FROM ValidIDs AS V2
WHERE V2.seq = V1.seq + 1
);
为什么基表会导致此错误?这是一个已知的问题吗?
UPDATE @sgmoore:不,在一个CTE中进行过滤而在另一个CTE中进行过滤仍会导致相同的错误,例如
WITH FilteredIDs (ID)
AS
(
SELECT ID
FROM IDs
WHERE ID LIKE 'A[0-9][0-9]'
),
ValidIDs (ID, seq)
AS
(
SELECT ID, CAST(RIGHT(ID, 2) AS INTEGER)
FROM FilteredIDs
)
SELECT MIN(V1.seq) + 1 AS next_seq
FROM ValidIDs AS V1
WHERE NOT EXISTS (
SELECT *
FROM ValidIDs AS V2
WHERE V2.seq = V1.seq + 1
);
答案 0 :(得分:4)
这是一个错误,已被报告为SQL Server should not raise illogical errors(正如我所说,很难描述这个!)由Erland Sommarskog报道。
来自SQL Server可编程性团队的响应是,“问题是SQL Server急切地引发错误[由于在查询执行期间推送预测/表达式而不考虑查询的逻辑结果。”
我现在已经投票支持修复,每个人都这样做了。)
答案 1 :(得分:0)
如果替换
部分该怎么办?SELECT ID, CAST(RIGHT(ID, 2) AS INTEGER)
FROM IDs
WHERE ID LIKE 'A[0-9][0-9]'
使用
SELECT ID, CAST(RIGHT(ID, 2) AS INTEGER)
FROM
(
select ID from IDs
WHERE ID LIKE 'A[0-9][0-9]'
)
答案 2 :(得分:0)
这发生在我身上,因为我做了一个联盟并且不小心确保两个查询的字段顺序相同。一旦我修好了,就可以了。