微软SQL Server 2008(SP1)出现意外的“转换失败”错误。
不太确定如何描述这个问题,因此以下是一个简单的例子。使用搜索条件从某些ID中提取数字部分的CTE,以确保实际存在数字部分。然后使用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
);
为什么基本表会导致这个错误?这是已知的问题吗?
更新@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
);
SELECT * FROM ValidIDs
替换您的查询进行测试。错误一定在其他地方... - marc_s