【问题标题】:How to Execute SQL Query without Displaying results如何在不显示结果的情况下执行 SQL 查询
【发布时间】:2021-09-02 14:14:09
【问题描述】:

是否可以执行 SQL 查询而不显示结果?

喜欢

Select * from Table_Name

运行此查询结果后,不应在sql server中显示。

【问题讨论】:

  • 如果那是面试问题,这似乎很奇怪,也没有经过深思熟虑。您可以在 SQL Server Mangement Studio 中“解析”(执行按钮附近的勾号图标)SQL 查询。它不会运行查询,但会检查 SQL 是否有效。也许这就是他们想要的。
  • 关闭屏幕 ;)
  • 有正当(非面试)的理由想要这样做。现在我已经两次尝试找到一种方法来做到这一点,两者的原因几乎相同,而且都是使用糟糕的第 3 方软件的黑客。简而言之:假设您正在使用一些接受用户输入 SQL 的软件(使用自定义查询报告 s/w)。现在想象一下,您想在顶部设置一些 vars 以提高用户的可读性和简单性。现在想象一下这个 STUPID 软件可以让你这样做,但要检查 SQL 中的第一个单词是 SELECT。现在请射我吧,我不能再这样下去了。
  • 我有一个用例。来这里寻找解决方案。我想找到所有包含“ItemID”字段的表......除此之外,我想找到至少有一条记录的所有表,其中“ItemID”包含某些特定值。不是所有的桌子都会有这个。当且仅当存在“ItemID”等于该值的记录时,我只想打印表的名称。我不想要任何会使我的输出变得混乱的结果。
  • 我有另一种情况我想要这个:我正在对数据库中的 100 多个表运行查询以查找自然键中的双精度。然后我保存@@rowcount 值。然后我对结果不感兴趣,只对返回的行数感兴趣

标签: sql sql-server


【解决方案1】:

我很惊讶没有人想出答案:打开“执行后丢弃查询结果”选项; l 我很确定那是面试官想要的。 SET FMT ONLY 恕我直言完全不同。

在 SSMS 中

  • 打开一个新查询
  • 在菜单中选择查询/查询选项
  • 选择结果窗格
  • 检查“执行后丢弃结果”

您可能想要这样做的原因是避免必须等待和浪费资源才能将结果加载到网格中,但仍然能够拥有例如实际执行计划。

【讨论】:

  • 很好的答案。我需要这个来查看查询运行了多长时间,而不需要 SSMS 浪费 CPU 周期来绘制网格、用完显示内存和其他 b/s
  • 这个,正是这个。我需要连续运行 1000 个查询,每个查询都返回一个结果集并同时记录执行时间。如果我显示结果集,我会很容易崩溃 SSMS。
  • 性能调优/基准测试脚本正是您想要这样做的原因 - 您正在跟踪执行时间并且想要忽略将结果返回的时间(您并不是真的in control of),重点关注查询执行时间(由您控制​​)。这是完全合法的!
  • 我已经看到一个存储过程在一个层下被循环调用,它返回一个非常小的结果集。在数百次这样的循环执行并因此返回数百个结果集之后,SSMS 将缓慢爬行,变得完全无响应,并可能因内存不足错误而崩溃。除了修改代码以插入和丢弃所有这些单独的结果之外,我可以看到如上所述设置选项将是一个有用的解决方法。
  • 似乎也丢弃了消息,所以使用 set statistics 对我没有帮助
【解决方案2】:

执行返回一个记录集。它当然可能没有行但得到一个结果

您可以使用SET FMTONLY 抑制行但不能抑制结果集

SET FMTONLY ON
SELECT * FROM sys.tables

SET FMTONLY OFF
SELECT * FROM sys.tables

虽然个人从来没有用过它......

编辑 2018。如前所述,请参阅 @deroby 的答案以获得更好的解决方案

【讨论】:

  • 值得一提的是,从 SQL Server 2012 开始,该功能已被弃用,取而代之的是一些功能。点击帖子中的链接了解更多信息
  • 另外值得一提的是 set fmtonly 实际上不会运行查询。它只获取元数据(因此得名)。例如,运行基准测试不是很有用...
  • WHILE @@FETCH_STATUS = 0 如果我使用 SET FMTONLY ON 则不再用于遍历游标
  • 查看@deroby 对当前解决方案的回答。
【解决方案3】:

对我来说,这听起来像是一个可疑的面试问题。我已经做到了,我需要这样做,但你只需要在非常模糊的情况下这样做。晦涩难懂,但有时非常重要。

正如@gbn 所说,一种编程方式是使用SET FMTONLY(谢谢,现在我不必从旧脚本文件中挖掘它)。一些程序和实用程序在查询 SQL 时会这样做;首先,他们在 FMTONLY ON 的情况下提交查询,以确定结果表结构的布局,然后当他们准备好在 FMTONLY OFF 的情况下运行它时,以获取实际数据。 (我在程序调用第二个程序时发现了这一点,第二个程序返回了数据集,并且由于不明原因整个纸牌屋都倒塌了。)

这也可以在 SSMS 中完成。对于所有查询窗口,在Tools/Options,Query Results/SQL Server/Results to XX下,勾选“Discard results after query executions”;仅适用于当前窗口,在 Query/Query Options、Results/XX 下,相同的复选框。这里的好处是查询将在数据库服务器上运行,但不会返回 data 结果。如果您正在检查查询计划但不想接收生成的 10GB 数据(通过网络到您的笔记本电脑上),或者您正在做一些严重的循环测试,这可能是非常宝贵的,因为 SSMS 只能接受在使用“太多结果集”消息停止查询之前,来自给定“运行”的结果集如此之多。 [嗯,请仔细检查我的“仅查询计划”位——我认为它可以做到这一点,但已经很久了。]

【讨论】:

  • “放弃结果”似乎是正确执行此操作的唯一方法 - 所有其他选项实际上并未执行 SQL:|
  • 我认为这是一个有效的问题,它帮助我解决了我的问题。我遇到了 SQL 内存不足异常,这很有帮助。
【解决方案4】:
insert anothertable
Select * from Table_Name

执行选择但不返回任何内容

set noexec on 
Select * from Table_Name

解析但不执行,因此不返回任何内容。

【讨论】:

  • SET NOEXEC ON; SELECT 1 FROM MyTable WHERE 1 = 2; SET NOEXEC OFF;。完美运行,在链接服务器上查看损坏的动态 SQL 或丢失的表
【解决方案5】:

也许面试官打算问一个不同的问题:

如何在不返回数量结果的情况下执行 SQL 查询?

在这种情况下,答案是SET NOCOUNT ON

【讨论】:

  • 这很好用,但请记住在运行查询或过程后设置“SET NOCOUNT OFF”
  • 这就是我想要的 :-) 只是不记得语法
【解决方案6】:

如果您需要执行查询但不需要实际结果集,您可以将查询包装在 EXISTS(或 NOT EXISTS)语句中:IF EXISTS(SELECT * FROM TABLE_NAME...)。或者,您可以选择 INTO #temp,然后删除临时表。

【讨论】:

  • IF EXISTS (SELECT 1 FROM MyTable WHERE 1 = 2) BEGIN DoNothingHere: END;
  • 虽然这也可以避免复制大量数据;这不完全一样。 WHERE EXISTS() 可能会在匹配条件的第一条记录之后停止。但是,您可能会遇到“低于”的 1000 条记录(例如)除以零错误,当像这样工作时,该错误仍然不会被注意到。
【解决方案7】:

目标是抑制所有行吗?然后使用对每一行评估为 false 的过滤器:

SELECT * FROM Table_Name WHERE 1 = 2

【讨论】:

    【解决方案8】:

    就我而言,我正在测试数据在所有视图中的行为,例如任何 cast() 函数都不会导致转换错误等,因此无法选择抑制实际数据,显示效果还不错,但有点浪费资源,如果仅以文本形式发送结果,最好不要重复。

    我想出了以下脚本以这种方式测试所有视图,唯一的问题是当它遇到具有 text/ntext 列的视图时。

    declare csr cursor local for select name from sys.views order by name
    declare @viewname sysname
    declare @sql nvarchar(max)
    
    open csr
    fetch next from csr into @viewname
    while @@fetch_status = 0 begin
        --set @sql = 'select top 1 * from ' + @viewname 
    
        set @sql = 'declare @test nvarchar(max) select @test = checksum(*) from ' + @viewname 
    
        print @viewname
    
        exec sp_executesql @sql
        fetch next from csr into @viewname
    end
    close csr
    deallocate csr
    

    【讨论】:

      【解决方案9】:

      如果您使用的是 PostgreSQL,您可以将您的选择放在一个函数中并使用 履行 PERFORM 语句执行一个参数并忘记了结果。

      A PERFORM statement sets FOUND true if it produces (and discards) one or more rows, false if no row is produced.
      

      https://www.postgresql.org/docs/9.1/plpgsql-statements.html#:~:text=A%20PERFORM%20statement%20sets%20FOUND,if%20no%20row%20is%20returned.

      【讨论】:

      • OP 请求 SQL Server
      【解决方案10】:

      另一个用例是当您只想读取表的所有行时,例如针对损坏进行测试。在这种情况下,您不需要数据本身,只需要它是否可读的事实。 但是,选项名称“执行后丢弃结果”有点令人困惑 - 它告诉我结果已被提取,然后才被丢弃。相反,它肯定会获取数据,但不会将其存储在任何地方(默认情况下,行被放入网格,或您选择的任何输出) - 接收到的行被即时丢弃(而不是在执行后)。

      【讨论】:

        【解决方案11】:

        我很惊讶社区无法轻易找到这方面的用例。大型结果集占用客户端内存,如果许多 SSMS 窗口处于活动状态,这可能会成为问题(我经常打开 2-3 个 SSMS 实例,每个实例有 50-70 个活动窗口)。在某些情况下,例如 Cyril 的示例,SSMS 可能会耗尽内存并且根本无法处理大型结果集。例如,我有一个案例需要调试返回数亿行的存储过程。在我的开发机器上运行 SSMS 而不丢弃结果是不可能的。该过程适用于 SSIS 包,它用作加载数据仓库表的数据源。 SSMS 中的调试涉及进行非功能性更改(因此我对结果集不感兴趣)并检查执行统计信息和实际查询执行计划。

        【讨论】:

        • 不太确定这是评论还是问题的答案?
        • 我的用例是对返回 lot 行的功能进行计时,但我不想包括 SSMS 明显显示结果需要多长时间。
        【解决方案12】:

        我需要一个 proc 来返回指定用户在某个时间点后更新的所有记录,只显示存在记录的结果。这里是:

        -- Written by David Zanke
        -- Return all records modified by a specified user on or after a specified date. 
        
        
        If mod date does not exist, return row anyhow
        
        Set Nocount on 
        
        Declare @UserName varchar(128) = 'zanked'
            , @UpdatedAfterDate Varchar( 30)  = '2016-10-08'
            , @TableName varchar( 128)
            , @ModUser varchar( 128)
            , @ModTime varchar( 128)
            , @sql varchar( 2000 )
        
        
        -- In a perfect world, left join would be unecessary since every row that captures the last mod user would have last mod date.
        
        -- Unfortunately, I do not work in a perfect world and rows w/ last mod user exist w/o last mod date
        
        Declare UserRows Cursor for Select distinct c1.table_name, c1.column_name, c2.column_name  From INFORMATION_SCHEMA.COLUMNS c1
        
        Left Join INFORMATION_SCHEMA.COLUMNS c2 On c1.Table_Name = c2.Table_Name And c2.Column_name like '%DTTM_RCD_LAST_UPD%'
                Where c1.column_name like '%UPDATED_BY_USER%'
        
        
        Open UserRows
        
        Fetch UserRows Into  @tablename, @ModUser, @ModTime
        
        While ( @@FETCH_STATUS = 0 )
        Begin
            -- capture output from query into a temp table
        
            Select @sql = 'Select ''' + @TableName + ''' TableName, * Into ##HoldResults From ' + @TableName + ' Where ' + @ModUser + ' = ''' + @userName + ''''
                    + Case When @ModTime Is Null Then '' Else   ' And ' + @ModTime + ' >= ''' + @UpdatedAfterDate + '''' End
        
            Exec ( @sql)
        
            -- only output where rows exist
            If @@ROWCOUNT > 0
            Begin
                Select * from ##HoldResults
            End
            Drop Table ##HoldResults
        
            Fetch UserRows Into  @tablename, @ModUser, @ModTime
        
        End
        Close UserRows;
        Deallocate UserRows
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-08-03
          • 1970-01-01
          • 2017-10-31
          • 1970-01-01
          • 1970-01-01
          • 2015-03-17
          • 1970-01-01
          相关资源
          最近更新 更多