I have some queries that run against Query Store, the view sys.query_store_wait_stats is not in SQL Server 2016, but it is in SQL Server 2017. I want my queries to work in SQL Server 2016 and SQL Server 2017+.

To accomplish this I used IF EXISTS as below

EXEC sp_query_store_flush_db;

SELECT * INTO Admin.dbo.query_store_runtime_stats FROM sys.query_store_runtime_stats;
SELECT * INTO Admin.dbo.query_store_runtime_stats_interval FROM sys.query_store_runtime_stats_interval;
SELECT * INTO Admin.dbo.query_store_plan FROM sys.query_store_plan;
SELECT * INTO Admin.dbo.query_store_query FROM sys.query_store_query;
SELECT * INTO Admin.dbo.query_store_query_text FROM sys.query_store_query_text;
IF EXISTS(select * FROM sys.views where name = 'query_store_wait_stats') -- View not in SQL Server 2016
    SELECT * INTO Admin.dbo.query_store_wait_stats FROM sys.query_store_wait_stats; 
SELECT * INTO Admin.dbo.query_context_settings FROM sys.query_context_settings;

Which would seem like a good solution, EXCEPT that, the below does not return any results on SQL Server 2017 database with Query Store active

select * FROM sys.views where name = 'sys.query_store_wait_stats'

Microsoft has this answer: How do I find all views in a database?

USE <database_name>;  
SELECT name AS view_name   
  ,SCHEMA_NAME(schema_id) AS schema_name  
  ,OBJECTPROPERTYEX(object_id,'IsIndexed') AS IsIndexed  
  ,OBJECTPROPERTYEX(object_id,'IsIndexable') AS IsIndexable  
FROM sys.views;  

But it only returns user views, NOT system views.

A couple of simple tests also do not return the system view, which is present. You can try them without a WHERE and not get any system views.

select * FROM sys.views where name = 'sys.query_store_wait_stats'

AND NAME= 'query_store_wait_stats'


I could test for SQL Server version, but If the view gets added to SQL Server 2016 in a Service Pack, I want my query to have only checked for the presence of the view.

How do I find (or test for) the presence of a system view?

3 Answers 3


You just need to remove the schema name and use all_views.

SQL Fiddle: http://www.sqlfiddle.com/#!18/9eecb/50897

select * from sys.all_views where name = 'query_store_wait_stats'

It's not just if objects exist as a whole, you also have to make sure columns line up. Microsoft adds new stuff, and sometimes backports it. It's nice not to rely on version checking, or worry about it failing if someone hasn't rebooted after patching.

As a related example, when dm_exec_query_stats got information about tempdb spills and I wanted to show those columns, I used code like this to test for them.

DECLARE @tempdb_spills BIT = 0;

IF 4 = (   SELECT COUNT(*)
           FROM   sys.all_columns AS ac
           WHERE  ac.name IN ( 'total_spills', 'last_spills', 'min_spills', 'max_spills' )
           AND    OBJECT_NAME(ac.object_id) = 'dm_exec_query_stats' )

SET @tempdb_spills = 1;

You could use the system_views instead of all_views.

SELECT * FROM sys.system_views WHERE name = 'query_store_wait_stats'

That way you can avoid selecting user defined views at the same time.

  • Thank you this works as well. Jul 16, 2019 at 15:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.