可以通过 DMV 检查 NOEXEC 的状态吗?

Mat*_*DBA 5 sql-server t-sql session

在用于部署的大型 DDL 脚本中,将 SET NOEXEC ON 作为错误处理的一部分使用是很常见的,以防止下游代码的执行。如果与 SET NOCOUNT ON 结合使用,则除非进行适当的部署后检查,否则可能会无意中抑制代码执行。我检查了 sys.dm_exec_sessions 并且没有任何 SET 语句的属性。从 DBA 的角度来看,是否有其他方法可以检查当前会话或任何用户会话的任一语句的状态?

这是一个快速示例...

CREATE TABLE dbo.MJZTest
    (Col1 int)
ON [PRIMARY2]
GO
IF @@ERROR<>0
    SET NOEXEC ON

INSERT INTO dbo.MJZTest (Col1)
VALUES (1)
GO
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,如果[PRIMARY2]文件组不存在,阻止了表的创建,@@ERROR检查将调用SET NOEXEC ON阻止后续INSERT语句实际执行的语句。我见过使用 RedGate SQL Compare 等工具生成这种类型的代码。

问题是,如果执行代码的人SET NOEXEC OFF在调试期间忽略运行以重置会话,他们可能会收到一条Command(s) completed successfully.消息,而不管实际结果如何。

spa*_*dba 1

NOCOUNT@@OPTIONS可以通过解析或运行来确定当前会话DBCC USEROPTIONS。不幸的是,我能找到的确定不同会话的此选项值的唯一方法是通过捕获ExistingConnectionSQLTrace 或扩展事件中的事件。

示例1:

DBCC USEROPTIONS
Run Code Online (Sandbox Code Playgroud)

输出:

+-------------------------+----------------+
|       Set Option        |     Value      |
+-------------------------+----------------+
| textsize                | 2147483647     |
| language                | us_english     |
| dateformat              | mdy            |
| datefirst               | 7              |
| lock_timeout            | -1             |
| quoted_identifier       | SET            |
| arithabort              | SET            |
| ansi_null_dflt_on       | SET            |
| ansi_warnings           | SET            |
| ansi_padding            | SET            |
| ansi_nulls              | SET            |
| concat_null_yields_null | SET            |
| isolation level         | read committed |
+-------------------------+----------------+
Run Code Online (Sandbox Code Playgroud)

示例2:

SELECT *
FROM (
    VALUES  
    (1     ,'DISABLE_DEF_CNST_CHK'),
    (2     ,'IMPLICIT_TRANSACTIONS'),
    (4     ,'CURSOR_CLOSE_ON_COMMIT'),
    (8     ,'ANSI_WARNINGS'),
    (16    ,'ANSI_PADDING'),
    (32    ,'ANSI_NULLS'),
    (64    ,'ARITHABORT'),
    (128   ,'ARITHIGNORE'),
    (256   ,'QUOTED_IDENTIFIER'),
    (512   ,'NOCOUNT'),
    (1024  ,'ANSI_NULL_DFLT_ON'),
    (2048  ,'ANSI_NULL_DFLT_OFF'),
    (4096  ,'CONCAT_NULL_YIELDS_NULL'),
    (8192  ,'NUMERIC_ROUNDABORT'),
    (16384 ,'XACT_ABORT')
) AS v(num, descr)
WHERE @@OPTIONS & num = num;
Run Code Online (Sandbox Code Playgroud)

输出:

+------+-------------------------+
| num  |          descr          |
+------+-------------------------+
|    8 | ANSI_WARNINGS           |
|   16 | ANSI_PADDING            |
|   32 | ANSI_NULLS              |
|   64 | ARITHABORT              |
|  256 | QUOTED_IDENTIFIER       |
|  512 | NOCOUNT                 |
| 1024 | ANSI_NULL_DFLT_ON       |
| 4096 | CONCAT_NULL_YIELDS_NULL |
+------+-------------------------+
Run Code Online (Sandbox Code Playgroud)

不幸的是,我找不到一种方法来判断是NOEXEC打开还是关闭。