50

Is it possible that Execute SQL Query without Displaying results?

like

Select * from Table_Name

after running this query result should not be displayed in sql server.

Cyril Gandon
  • 16,830
  • 14
  • 78
  • 122
Rajesh Kumar
  • 2,443
  • 3
  • 28
  • 43
  • this question was asked in Interview. – Rajesh Kumar Jun 17 '11 at 13:40
  • It would help if we understood what you were trying to accomplish. In other words, why would you run a query like this if you didn't want results? Do you just want the "X rows affected." message? If so, you could just so a `select count(*) from Table_Name`. – Jerad Rose Jun 17 '11 at 13:40
  • Yeah - if you don't run the query you get no results. What are your actual requirements as what you have stated here doesn't make any sense – Chris Gill Jun 17 '11 at 13:41
  • Interviewer just asked me that is there any way that I run a select query and it should not display result :( – Rajesh Kumar Jun 17 '11 at 13:43
  • 2
    If that was the interview question it seems very odd an not very well thought out. You can "Parse" (the tick icon near the Execute button) a SQL Query in the SQL Server Mangement Studio. It won't run the query but it does check that the SQL is valid. Maybe that's what they were getting at. – Colin Mackay Jun 17 '11 at 13:47
  • 9
    Turning off the screen ;) – Guido Jun 17 '11 at 16:22
  • 5
    There are legitimate (non-interview) reasons for wanting to do this. Twice now I have tried to find a way to do this, both for almost the same reason and both as a hack for working with poor 3rd party software. In brief: say you are working with some piece of software that accepts user input SQL (reporting s/w with custom queries). Now imagine you want to set some vars at the top for readability and simplicity for users. Now imagine this STUPID piece of software would let you do this, but for a check that the first word in the SQL is SELECT. Now shoot me, please, I can't go on like this. – DaveRandom Jul 14 '15 at 17:09
  • 2
    I have a use case for this. Came here looking for a solution. I want to find all tables containing an "ItemID" field... and further to that, I want to find all tables for which there is at least one record where 'ItemID' contains some specific value. Not all tables will have this. I want to print out only the name of the table if and only if there are records where 'ItemID' equals this value. I don't want any of the results which simply clutter my output. – Luke Sep 01 '15 at 14:14
  • 1
    I have another case where I want this: I'm running a query against 100+ tables in a database to look for doubles in natural key. I then save the @@rowcount value. Then I'm not interested in the result, just the number of rows returned – Tech Jun 08 '16 at 12:34
  • 1
    Personnally I just want a quick benchmark of a sproc and I don't care about the (large) results. @Luke: your use case is better answered with `sys.columns` and looping on the results. – thomasb Jan 09 '17 at 13:39
  • I came here looking for an answer because I can't directly put my results into a table since the procedure I'm executing (procedure B) already wraps something (procedure A). So I took the procedure I'm executing (procedure B) and at the end I dumped everything to a global temp table. So now I have to execute procedure B to populate the global temp table in order to read the data. But then the initial EXEC of procedure B also shows data, and I don't want it to. – DaveX Jun 21 '17 at 22:07
  • Wouldn't SELECT INTO if you don't care about the results but just about the into part be another use case? – A_Arnold Aug 29 '17 at 18:07
  • @A_Arnold that's exactly what I was doing that led me to this. I have a stored procedure that inserts into a temp table (for breaking down a complex task into steps) - and I didn't want the `SELECT INTO` to be part of the result set (obviously). There's probably some other way to do it with output parameters or something like that but for me what I wanted was `SET NOCOUNT ON` to achieve this – Simon_Weaver Nov 09 '18 at 23:41
  • I happen to think this is a great interview question - if the goal is to see how the interviewee responds and reasons through some options and possible motivations - could be a great discussion whether they know the 'magic sql' the interviewer has or not. – Simon_Weaver Nov 09 '18 at 23:42

12 Answers12

94

I'm surprised nobody came up with the answer : switch on the "discard query results after execution" option; l I'm pretty sure that was what the interviewer was after. SET FMT ONLY is totally different thing IMHO.

In SSMS

  • open a new query
  • in the menu select Query / Query options
  • select the Results pane
  • check the "discard result after execution"

The reason you might want to do this is to avoid having to wait and waste resources for the results to be loaded into the grid but still be able to have e.g. the Actual Execution Plan.

deroby
  • 5,902
  • 2
  • 19
  • 33
  • I agree the answer is ambiguous. It's missing "Why would you want to do this" and "Where do I want to do this". If he's talking about SMSS and simply wants to execute a query without displaying the results (for whatever reasons - I can imagine a few) I would prefer your answer. – marsze Nov 10 '15 at 10:29
  • 30
    Great answer. I needed this to see **how long the query runs** without SSMS wasting CPU cycles to draw the grid, use up display memory and other b/s – Alex from Jitbit Jan 08 '16 at 20:16
  • 8
    This, exactly this. I needed to run 1000 queries consecutively, each returning a result set and at the same time logging execution times. If I had the result sets displayed, I would have crashed SSMS easily. – John B May 05 '16 at 00:06
  • 3
    Performance tuning/benchmarking scripts are exactly the reason you'd want to do this - you're tracking execution times and want to ignore the time it takes to pump results back (which you're not really in control of), focusing on the query execution time (which you are in control of). This is completely legitimate! – SqlRyan Jun 21 '16 at 14:47
  • 1
    I've seen where a stored proc a layer down is being called in a loop, and it returns a very small result set. After a few hundred of these looped executions and therefore a few hundred result sets returned, SSMS will slow to a crawl, become totally unresponsive, and potentially crash with an out of memory error. Aside from modifying the code to insert into and discard all those individual retuls, I can see setting the option as described above would be a useful workaround. – Larry Smith Jun 23 '16 at 21:49
  • 1
    Seems to discard messages too, so no help for me using set statistics – Paul Feb 19 '18 at 10:57
37

Executing will return a recordset. It may have no rows of course but get a result

You can suppress rows but not the resultset with SET FMTONLY

SET FMTONLY ON
SELECT * FROM sys.tables

SET FMTONLY OFF
SELECT * FROM sys.tables

Never had a use for it personally though...

Edit 2018. As noted, see @deroby's answer for a better solution these days

gbn
  • 422,506
  • 82
  • 585
  • 676
  • 2
    Worth mentioning is that from SQL Server 2012 this feature is deprecated and replaced with some functions instead. Follow the link in the post for more information – Tech Jun 08 '16 at 12:42
  • 8
    Also worth mentionin is that set fmtonly will NOT actually run the query. It only fetches metadata (hence the name). Not very useful to run a benchmark for instance... – thomasb Jan 09 '17 at 13:43
  • 1
    WHILE @@FETCH_STATUS = 0 does not work any more to itterate through a cursore if I use SET FMTONLY ON – profimedica Jul 05 '17 at 16:03
  • 2
    Look at @deroby 's answer for current solution. – Jon McEroy Sep 27 '18 at 16:24
15

Sounds like a dubious interview question to me. I've done it, I've needed to do it, but you'd only need to do so under pretty obscure circumstances. Obscure, but sometimes very important.

As @gbn says, one programmatic way is with SET FMTONLY (thanks, now I don't have to dig it out of my old script files). Some programs and utilities do this when querying SQL; first they submit a query with FMTONLY ON, to determine the layout of the resulting table structure, then when they've prepared that they run it gain with FMTONLY OFF, to get the actual data. (I found this out when the procedure called a second procedure, the second procedure returned the data set, and for obscure reasons the whole house of cards fell down.)

This can also be done in SSMS. For all querying windows, under Tools/Options, Query Results/SQL Server/Results to XX, check "Discard results after query executes"; for only the current window, under Query/Query Options, Results/XX, same checkbox. The advantage here is that the query will run on the database server, but the data results will not be returned. This can be invaluable if you're checking the query plan but don't want to receive the resulting 10GB of of data (across the network onto your laptop), or if you're doing some seriously looped testing, as SSMS can only accept so many result sets from a given "run" before stopping the query with a "too many result sets" message. [Hmm, double-check me on that "query plan only" bit--I think it does this, but it's been a long time.]

Philip Kelley
  • 39,426
  • 11
  • 57
  • 92
  • 4
    "Discard Results" seems to be the only way to do this properly - all the other options don't actually execute the SQL :| – Spikeh Jan 28 '14 at 10:03
  • 1
    i think it is a valid question, and it helped me solve my problem. I was getting SQL out of memory exception and this helped. – Kalpesh Popat Feb 17 '17 at 14:26
9
insert anothertable
Select * from Table_Name

Executes the select but returns nothing

set noexec on 
Select * from Table_Name

Parses but does not execute and so returns nothing.

Alex K.
  • 171,639
  • 30
  • 264
  • 288
  • `SET NOEXEC ON; SELECT 1 FROM MyTable WHERE 1 = 2; SET NOEXEC OFF;`. Works perfect and see broken dynamic SQL or lost tables on a Linked Server – it3xl Aug 26 '18 at 20:39
9

Perhaps the interviewer intended to ask a different question:

How would you execute a SQL query without returning the number of results?

In that case the answer would be SET NOCOUNT ON.

Anthony Faull
  • 17,549
  • 5
  • 55
  • 73
5

If you need the query to execute but don't need the actual resultset, you can wrap the query in an EXISTS (or NOT EXISTS) statement: IF EXISTS(SELECT * FROM TABLE_NAME...). Or alternately, you could select INTO #temp, then later drop the temp table.

Cogitator
  • 154
  • 1
  • 1
  • `IF EXISTS (SELECT 1 FROM MyTable WHERE 1 = 2) BEGIN DoNothingHere: END;` – it3xl Aug 27 '18 at 03:21
  • Although this could be a way to avoid copying lots of data too; it's not entirely the same thing. The `WHERE EXISTS()` probably will stop after the first record that matches the criteria. However, it could be that 1000 records "below" you run into a (e.g.) Divide By Zero error that would remain unnoticed when working like this. – deroby Jan 11 '19 at 20:15
3

In my case I was testing that the data was behaving in all views, e.g. any cast() functions weren't causing conversion errors, etc. so supressing the actual data wasn't an option, displaying wasn't too bad but a bit of wasted resource and better not to diplsay if sending results only in text.

I came up with the following script to test all the views in this way, the only problem is when it encounters views that have text/ntext columns.

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
3

Is the goal to suppress all rows? Then use a filter that evaluates to false for every row:

SELECT * FROM Table_Name WHERE 1 = 2
Dennis Traub
  • 50,557
  • 7
  • 93
  • 108
1

If you are using PostgreSQL you can put your select in a function and use PERFORM The PERFORM statements execute a parameter and forgot result.

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.

Hard Worker
  • 995
  • 11
  • 33
0

Yet another use case is when you just want to read all the rows of the table, for example testing against corruptions. In this case you don't need the data itself, only the fact that it is readable or not. However, the option name "Discard results AFTER execution" is a bit confusing - it tells me that the result is fetched and only then discarded. In contrary, it fetches the data for sure but does not store it anywhere (by default the rows are put into the grid, or whatever output you have chosen) - the received rows are discarded on the fly (and not AFTER execution).

S.E.
  • 145
  • 1
  • 7
0

I am surprised the community can't easily find a use case for this. Large result sets take memory on the client, which may become a problem if many SSMS windows are active (it is not unusual for me to have 2-3 instances of SSMS opened, each with 50-70 active windows). In some cases, like in Cyril's example, SSMS can run out of memory and simply unable to handle a large result set. For instance, I had a case when I needed to debug a stored procedure returning hundreds of millions of rows. It would be impossible to run in SSMS on my development machine without discarding results. The procedure was for an SSIS package where it was used as a data source for loading a data warehouse table. Debugging in SSMS involved making non-functional changes (so the result set was of no interest to me) and inspecting execution statistics and actual query execution plans.

  • 2
    Not quite sure if this is a comment, or an answer to the question? – roelofs Dec 21 '17 at 23:30
  • 2
    My use case is to time a functionality that returns a *lot* of rows, but I don't want to include how long it takes SSMS to display the results obviously. – Elaskanator Jun 13 '18 at 15:17
-2

I needed a proc to return all records updated by a specified user after a certain point in time, only showing results where records existed. Here it is:

-- 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
Adam
  • 5,403
  • 6
  • 31
  • 38
David
  • 31
  • 2