Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL Server子查询行为_Sql_Sql Server - Fatal编程技术网

SQL Server子查询行为

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

我有一个例子,我想检查在一个表的列中是否找到了一个整数值,它是varchar,但它是一个可以是整数的值的混合体,有些只是字符串。我的第一个想法是使用子查询只选择具有数值的行。安装程序如下所示:

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必须执行两个筛选器:

  • 仅标识与变量匹配的行
  • 仅标识数字行
  • 它可以按任意顺序执行此操作,因此这也是有效的:

  • 仅标识数字行
  • 仅标识与变量匹配的行
  • 如果查看此执行计划的属性,您会发现与变量匹配的谓词首先列出(这仍然不能保证操作顺序),但在任何情况下,由于数据类型的优先级,它必须尝试将列数据转换为变量的类型:

    子查询、CTE或以不同的方式编写查询(特别是在这样的简单情况下)不太可能改变SQL Server执行这些操作的顺序

    在大多数情况下,您可以使用
    CASE
    表达式强制计算顺序(您也不需要子查询):

    在SQL Server的现代版本中(您忘记告诉我们您使用的版本),您也可以使用
    TRY\u CONVERT()

    SELECT EmployeeID
    FROM #tmp
    WHERE TRY_CONVERT(int, EmployeeID) = @eid;
    
    这本质上是
    CASE
    表达式的简写,但它还允许您指定显式类型。All
    ISNUMERIC()
    告诉您该值是否可以转换为任何数字类型。字符串
    '1e2'
    通过
    ISNUMERIC()
    检查,因为它可以转换为
    float
    ,但请尝试将其转换为
    int

    为了完整性,最好的解决方案(如果
    EmployeeID
    上有索引)是按照您的建议,只使用与列数据类型匹配的变量


    但更好的做法是使用一种数据类型,首先防止垃圾数据(如
    'aa1234'
    )进入表中。

    当SQL Server查看您编写的查询并确定最佳执行计划时,您无法轻松控制事情发生的顺序。它不会总是按照您键入的相同逻辑、相同顺序生成计划

    在这种情况下,为了找到要查找的行,SQL Server必须执行两个筛选器:

  • 仅标识与变量匹配的行
  • 仅标识数字行
  • 它可以按任意顺序执行此操作,因此这也是有效的:

  • 仅标识数字行
  • 仅标识与变量匹配的行
  • 如果查看此执行计划的属性,您会发现与变量匹配的谓词首先列出(这仍然不能保证操作顺序),但在任何情况下,由于数据类型的优先级,它必须尝试将列数据转换为变量的类型:

    子查询、CTE或以不同的方式编写查询(特别是在这样的简单情况下)不太可能改变SQL Server执行这些操作的顺序

    在大多数情况下,您可以使用
    CASE
    表达式强制计算顺序(您也不需要子查询):

    在SQL Server的现代版本中(您忘记告诉我们您使用的版本),您也可以使用
    TRY\u CONVERT()

    SELECT EmployeeID
    FROM #tmp
    WHERE TRY_CONVERT(int, EmployeeID) = @eid;
    
    这本质上是
    CASE
    表达式的简写,但它还允许您指定显式类型。All
    ISNUMERIC()
    告诉您该值是否可以转换为任何数字类型。字符串
    '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这可能有效,但也可能无效。