2009-06-26 125 views
0

在下面的情况下,Combine视图中的最终选择失败,有什么想法为什么?为什么sql select语句失败?

子集表没有对应于MasterCodes中不会转换为整数值的行。

CREATE TABLE MasterCodes (
    ID INT 
, Code VARCHAR(10)) 
GO 

CREATE TABLE Subset (
    ID INT) 
GO 


CREATE VIEW Combine AS 
SELECT S.ID 
, M.Code 
, CAST(M.Code AS INT) IntCode 
FROM Subset S 
INNER JOIN MasterCodes M ON M.ID = S.ID 
GO 

INSERT MasterCodes (ID, Code) VALUES (1, '1') 
INSERT MasterCodes (ID, Code) VALUES (2, '2') 
INSERT MasterCodes (ID, Code) VALUES (3, 'three') 
INSERT MasterCodes (ID, Code) VALUES (4, '4') 
INSERT Subset (ID) VALUES (1) 
INSERT Subset (ID) VALUES (2) 
INSERT Subset (ID) VALUES (4) 


SELECT * FROM Combine -- 3 rows returned 

SELECT * FROM Combine WHERE Code = '2' -- 1 row returned 

SELECT * FROM Combine WHERE Code = '3' -- 0 rows returned 

SELECT * FROM Combine WHERE IntCode = 2 -- fails, error msg is 

Msg 245, Level 16, State 1, Line 15 
Conversion failed when converting the varchar value 'three' to data type int. 

环境是Sql2k5标准(64位)ON WIN2K3服务器R2

+0

有点格式化会让你更多的回应。 – pugmarx 2009-06-26 21:54:43

回答

6

可能是因为在某些行,M.Code包含字面单词“三”,并认为是试图投非 - 将数字看成一个int(你可能会把“3”变成一个int,但不是“puppy”或“three”等)。

编辑:添加了评论,但值得在此处添加。 SQL Server将尝试并尽可能高效地执行和加入,并且它会尝试在加入之前显式应用where子句。

如果您认为现今的VIEW几乎完全像真正的桌子一样工作,这是有道理的。它必须做些与此相似的事情;否则,它会加入所有内容并在被滤除之前返回所有值。

非常昂贵。

我不确定的是如果执行计划会显示这个级别的细节。

2

您将字符串“three”插入MasterCodes.Code,并且您的视图试图将此值转换为整数。这个SQL应该给出相同的错误:

select cast("three" as int) 

解决方法?在您的插入语句中将“three”替换为“3”。

+0

'三'值不应该由视图首先选择,子集表没有ID = 3的行,并且内部连接到MasterCodes表。我的问题是,为什么系统在Combine视图中无法返回时尝试将“三”值转换为第一个整数。 – jsr 2009-06-26 21:54:58

+0

可能是因为它在加入之前将您的WHERE子句应用于MasterCOdes(因此,投射所有行)。原则上,它应该更有效率,这就是SQL Server将要尝试的。 曾经有一段时间,视图仅仅是一些奇特的存储过程,但事情发生了变化,它们确实是一个虚拟表。 – hythlodayr 2009-06-26 23:44:07

0

因为当你尝试在条件逻辑中使用IntCode时,视图试图将“three”作为int来投射。

使用ISNUMERIC()有一个case语句如果结果集是精确到创建视图

case when isnumeric(field) then 
    cast(field as int) 
else 
    null 
end AS IntCode 
0

: “SELECT * FROM结合其代码= '2' - 返回1行 SELECT * FROM Combine WHERE Code ='3' - 0行返回 SELECT * FROM Combine WHERE IntCode = 2 - 失败,错误消息isMsg 245,级别16,状态1,行15转换varchar值'3'为数据时转换失败键入int“。

然后唯一一次失败的情况是当你尝试与IntCode字段进行比较时,它几乎看起来像是在尝试将非数字值放在“IntCode = 2”比较左侧时失败,因为这是唯一需要在代码字段中提取每个值的时间。

希望有帮助!