为所有数据库启用查询存储

Jam*_*ins 5 sql-server sql-server-2016 query-store

我想开始使用带有Erin Stellato 建议设置的查询存储。

USE [master]
GO
ALTER DATABASE DatabaseName SET QUERY_STORE = ON
GO
ALTER DATABASE DatabaseName SET QUERY_STORE (OPERATION_MODE = READ_WRITE
, INTERVAL_LENGTH_MINUTES = 30
, MAX_STORAGE_SIZE_MB = 1000
, QUERY_CAPTURE_MODE = AUTO)
GO
Run Code Online (Sandbox Code Playgroud)

但这是一个数据库设置,我希望能够一次激活一个实例的所有数据库。

我找到了SET RECOVERY Model Using sp_msforeachdb (at serverfault)

我可以使用 OP 的解决方案

EXECUTE master.sys.sp_MSforeachdb 'USE [?];
IF DB_ID() >= 5
ALTER DATABASE [?] SET QUERY_STORE = ON
ALTER DATABASE [?] SET QUERY_STORE (OPERATION_MODE = READ_WRITE
, INTERVAL_LENGTH_MINUTES = 30
, MAX_STORAGE_SIZE_MB = 1000
, QUERY_CAPTURE_MODE = AUTO)
'
Run Code Online (Sandbox Code Playgroud)

虽然它有效,但我收到错误

Msg 12438, Level 16, State 1, Line 41

无法执行操作,因为无法在系统数据库主服务器上启用查询存储。

消息 5069,级别 16,状态 1,第 41 行

ALTER DATABASE 语句失败。

Msg 12438, Level 16, State 1, Line 41

无法执行操作,因为无法在系统数据库 tempdb 上启用查询存储。

消息 5069,级别 16,状态 1,第 41 行

ALTER DATABASE 语句失败。

我尝试了Jason Cumberland的解决方案的几种变体,但无法使其正常工作。

set quoted_identifier on

EXECUTE master.sys.sp_MSforeachdb '
IF '?' not in ('tempdb','master','model')
begin
    exec (ALTER DATABASE [?] SET QUERY_STORE = ON
ALTER DATABASE [?] SET QUERY_STORE (OPERATION_MODE = READ_WRITE
, INTERVAL_LENGTH_MINUTES = 30
, MAX_STORAGE_SIZE_MB = 1000
, QUERY_CAPTURE_MODE = AUTO))
end
'
Run Code Online (Sandbox Code Playgroud)

我收到错误

消息 102,级别 15,状态 1,第 25 行

'?' 附近的语法不正确。

这两个工作

  --Turn off on all databases
  EXECUTE master.sys.sp_MSforeachdb 'USE [?]; ALTER DATABASE [?] SET QUERY_STORE = OFF'
Run Code Online (Sandbox Code Playgroud)

--Check all Query Store database settings at once
EXECUTE master.sys.sp_MSforeachdb 'USE [?]; SELECT * FROM sys.database_query_store_options'
Run Code Online (Sandbox Code Playgroud)

问题:如何在一个实例的所有数据库上打开查询存储而不收到错误消息?

注意:在系统数据库中,msdb 是唯一允许查询存储的数据库。我目前不排除它。

我正在对运行 SQL 2016 (SP1) 的 SQL 实例使用 SSMS 17.4

Sol*_*zky 6

在问题中尝试查询的两种情况下,问题都只是语法问题。

在第一种情况下:您有一个IF条件,但不要将它后面的语句组合在一起,因此只有紧跟在 后面的语句IF是有条件的。第二条ALTER DATABASE语句始终执行。要修复,请执行以下操作:

EXECUTE master.sys.sp_MSforeachdb N'USE [?];
IF DB_ID() >= 5
BEGIN
  ALTER DATABASE [?] SET QUERY_STORE = ON;
  ALTER DATABASE [?] SET QUERY_STORE
   (OPERATION_MODE = READ_WRITE,
    INTERVAL_LENGTH_MINUTES = 30,
    MAX_STORAGE_SIZE_MB = 1000,
    QUERY_CAPTURE_MODE = AUTO);
END;
';
Run Code Online (Sandbox Code Playgroud)

您可能也不需要不需要该USE语句。可以删除它,然后DB_ID()可以将其更改为DB_ID(N''?'').

在第二种情况下:您没有转义嵌入的单引号。您还有一个无关紧要的EXEC,并且您没有包含msdb系统数据库。要解决所有这些问题,请执行以下操作:

EXECUTE master.sys.sp_MSforeachdb N'
IF (N''?'' NOT IN (N''tempdb'', N''master'', N''model'', N''msdb''))
BEGIN
   ALTER DATABASE [?] SET QUERY_STORE = ON;
   ALTER DATABASE [?] SET QUERY_STORE
    (OPERATION_MODE = READ_WRITE,
     INTERVAL_LENGTH_MINUTES = 30,
     MAX_STORAGE_SIZE_MB = 1000,
     QUERY_CAPTURE_MODE = AUTO);
END;
';
Run Code Online (Sandbox Code Playgroud)

请注意: @Kris 说“sp_MSForeachDB未记录且不受支持”并没有错,建议使用另一种机制循环通过 DB 是很好的建议。如果这是一次性任务,那么麻烦可能不值得,但是如果要重复使用此代码,那么是的,您可能应该注意该警告。