Sql-Server

為什麼 DATABASEPROPERTYEX 的結果與 AdventureWorks 不一致?

  • January 18, 2022

我正在使用函式DATABASEPROPERTYEX來檢查數據庫的恢復屬性,但是數據庫的結果是錯誤的AdventureWorks(後來我注意到ReportServerReportServerTempDB數據庫的同樣奇怪的行為)。

這是我嘗試過的簡化版本:

USE master;
GO

CREATE PROCEDURE [dbo].[sp_isSimpleRecovery] 
AS
BEGIN
   PRINT DB_NAME() + CHAR(13);

   IF DATABASEPROPERTYEX(DB_NAME(), 'Recovery') = 'SIMPLE'
       PRINT '--Database in SIMPLE recovery model' + CHAR(13);
   ELSE
       PRINT '--Database in ANOTHER recovery model' + CHAR(13);
END

我創建了master使用前綴 sp_的過程,以便可以從任何數據庫執行它。但是當我從AdventureWorks結果中執行它時,與沒有該過程執行的相同程式碼不同:

USE AdventureWorks2016;
GO

EXEC sp_isSimpleRecovery;

PRINT DB_NAME() + CHAR(13);

IF DATABASEPROPERTYEX(DB_NAME(), 'Recovery') = 'SIMPLE'
   PRINT '--Database in SIMPLE recovery model' + CHAR(13);
ELSE
   PRINT '--Database in ANOTHER recovery model' + CHAR(13);

它適用於許多其他數據庫,但對於 AdventureWorks,輸出為:

AdventureWorks2016

–另一種恢復模式中的數據庫

AdventureWorks2016

–簡單恢復模型中的數據庫

是什麼導致了這種行為?


我使用的AdventureWorks 範例數據庫:

  • AdventureWorks2014.bak
  • AdventureWorks2016.bak

SQL Server 版本:

  • Microsoft SQL Server 2016 (SP2-GDR) (KB4532097) - 13.0.5102.14 (X64) 2019 年 12 月 31 日
  • Microsoft SQL Server 2014 (SP3-CU4-GDR) (KB4583462) - 12.0.6433.1 (X64) 2020 年 10 月 31 日

我將您的過程重新寫到下面:

CREATE OR ALTER PROCEDURE [dbo].[sp_isSimpleRecovery] 
AS
BEGIN
   PRINT DB_NAME() + CHAR(13);
   PRINT CAST(DATABASEPROPERTYEX(DB_NAME(), 'Recovery') AS varchar(20))

   IF CAST(DATABASEPROPERTYEX(DB_NAME(), 'Recovery') AS varchar(20)) = 'SIMPLE'
       PRINT '--Database in SIMPLE recovery model' + CHAR(13);
   IF CAST(DATABASEPROPERTYEX(DB_NAME(), 'Recovery') AS varchar(20)) = 'FULL'
       PRINT '--Database in FULL recovery model' + CHAR(13);
END
GO

請注意,我忽略了大容量日誌恢復模型。此過程在 SQL Server 2019 上對我有用。即,如果我在一個處於簡單模式的數據庫中,它會返回 SIMPLE,如果我在一個處於完整模式的數據庫中,它會返回 FULL。

如果上述方法在 2016 年對您不起作用,那麼可能在 2016 年和 2019 年之間發生了行為變化。

在某些情況下,僅將過程命名為 sp_ 並將其放在主數據庫中是不夠的。您還必須使用未記錄的 sp_MS_marksystemobject 將其標記為系統過程。請注意,這是未記錄的,因此使用風險自負!

兩者之間的區別在於,如果沒有 sp_MS_marksystemobject, 如果您在 Adventureworks 中,*則會找到該過程,但在主數據庫上下文中執行。*例如,如果您從 sys.tables 中選擇,您將看到主數據庫中的表。

使用 sp_MS_marksystemobject,您可以告訴 SQL Server 在執行過程中的程式碼時處於目前數據庫的上下文中。即,系統表、系統函式等現在將被解析為使用使用者數據庫而不是主數據庫。

那麼為什麼會在 2016 年和 2019 年之間發生行為變化呢?我們不能說,因為我們在無證地區。

一個簡單的事實是,沒有支持的方法來創建解析為您所在數據庫的“全域”系統儲存過程。

引用自:https://dba.stackexchange.com/questions/306210