我正在使用函数DATABASEPROPERTYEX来检查数据库的恢复属性,但是数据库的结果是错误的AdventureWorks
(后来我注意到ReportServer
和ReportServerTempDB
数据库的同样奇怪的行为)。
这是我尝试过的简化版本:
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
--简单恢复模型中的数据库
是什么导致了这种行为?
- 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 日
我将您的过程重新写到下面:
请注意,我忽略了大容量日志恢复模型。此过程在 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 年之间发生行为变化呢?我们不能说,因为我们在无证地区。
一个简单的事实是,没有支持的方法来创建解析为您所在数据库的“全局”系统存储过程。