SQL Server子查询行为
我有一个例子,我想检查在一个表的列中是否找到了一个整数值,它是varchar,但它是一个可以是整数的值的混合体,有些只是字符串。我的第一个想法是使用子查询只选择具有数值的行。安装程序如下所示:SQL Server子查询行为,sql,sql-server,Sql,Sql Server,我有一个例子,我想检查在一个表的列中是否找到了一个整数值,它是varchar,但它是一个可以是整数的值的混合体,有些只是字符串。我的第一个想法是使用子查询只选择具有数值的行。安装程序如下所示: CREATE TABLE #tmp ( EmployeeID varchar(50) NOT NULL ) INSERT INTO #tmp VALUES ('aa1234') INSERT INTO #tmp VALUES ('1234') INSERT INTO #tmp VALUES ('5678
CREATE TABLE #tmp (
EmployeeID varchar(50) NOT NULL
)
INSERT INTO #tmp VALUES ('aa1234')
INSERT INTO #tmp VALUES ('1234')
INSERT INTO #tmp VALUES ('5678')
DECLARE @eid int
SET @eid = 5678
SELECT *
FROM (
SELECT EmployeeID
FROM #tmp
WHERE IsNumeric(EmployeeID) = 1) AS UED
WHERE UED.EmployeeID = @eid
DROP TABLE #tmp
但是,此操作失败,原因是:“将varchar值“aa1234”转换为数据类型int时,转换失败。”
我不明白为什么在我只选择了子查询中的行“1234”和“5678”时,它仍在尝试将@eid与“aa1234”进行比较
(我知道我可以将@eid强制转换为varchar,但我对SQL Server在这种情况下的行为很好奇)当SQL Server查看您编写的查询并确定最佳执行计划时,您无法轻松控制事情发生的顺序。它不会总是按照您键入的相同逻辑、相同顺序生成计划 在这种情况下,为了找到要查找的行,SQL Server必须执行两个筛选器:
CASE
表达式强制计算顺序(您也不需要子查询):
在SQL Server的现代版本中(您忘记告诉我们您使用的版本),您也可以使用TRY\u CONVERT()
:
SELECT EmployeeID
FROM #tmp
WHERE TRY_CONVERT(int, EmployeeID) = @eid;
这本质上是CASE
表达式的简写,但它还允许您指定显式类型。AllISNUMERIC()
告诉您该值是否可以转换为任何数字类型。字符串'1e2'
通过ISNUMERIC()
检查,因为它可以转换为float
,但请尝试将其转换为int
为了完整性,最好的解决方案(如果EmployeeID
上有索引)是按照您的建议,只使用与列数据类型匹配的变量
但更好的做法是使用一种数据类型,首先防止垃圾数据(如
'aa1234'
)进入表中。当SQL Server查看您编写的查询并确定最佳执行计划时,您无法轻松控制事情发生的顺序。它不会总是按照您键入的相同逻辑、相同顺序生成计划
在这种情况下,为了找到要查找的行,SQL Server必须执行两个筛选器:
CASE
表达式强制计算顺序(您也不需要子查询):
在SQL Server的现代版本中(您忘记告诉我们您使用的版本),您也可以使用TRY\u CONVERT()
:
SELECT EmployeeID
FROM #tmp
WHERE TRY_CONVERT(int, EmployeeID) = @eid;
这本质上是CASE
表达式的简写,但它还允许您指定显式类型。AllISNUMERIC()
告诉您该值是否可以转换为任何数字类型。字符串'1e2'
通过ISNUMERIC()
检查,因为它可以转换为float
,但请尝试将其转换为int
为了完整性,最好的解决方案(如果EmployeeID
上有索引)是按照您的建议,只使用与列数据类型匹配的变量
但更好的做法是使用一种数据类型,以防止垃圾数据(如
'aa1234'
)首先进入表。,因为SQL正在将查询优化为一个查询。它不会首先执行子查询。虽然这可能是的重复项,但我不会投票关闭,因为我更喜欢这里给出的答案。这会起作用,从#tmp中选择EmployeeID,其中ISNUMERIC(EmployeeID)=1,EmployeeID=@eid@iSR5它不会起作用。请阅读下面的答案以及链接问题中的答案。@iSR5可能有效,但也可能无效。因为SQL正在将查询优化为一个查询。它不会首先执行子查询。虽然这可能是的重复项,但我不会投票关闭,因为我更喜欢这里给出的答案。这会起作用,从#tmp中选择EmployeeID,其中ISNUMERIC(EmployeeID)=1,EmployeeID=@eid@iSR5它不会起作用。请阅读下面的答案以及链接问题中的答案。@iSR5这可能有效,但也可能无效。