Ron*_*ldo 8 sql-server system-databases objectid
据我所知,SQL Server系统数据库总是具有相同的 ID,而且我在 Internet 上看到许多维护脚本依赖谓词WHERE database_id > 4将它们从脚本的操作中排除。
另外,如果我SELECT name, schema_id FROM sys.schemas;在新的用户数据库上运行,我会得到:
name schema_id
dbo 1
guest 2
INFORMATION_SCHEMA 3
sys 4
db_owner 16384
db_accessadmin 16385
db_securityadmin 16386
db_ddladmin 16387
db_backupoperator 16389
db_datareader 16390
db_datawriter 16391
db_denydatareader 16392
db_denydatawriter 16393
Run Code Online (Sandbox Code Playgroud)
我在两个不同的实例上运行了该查询,一个是 SQL Server 2016,另一个是 SQL Server 2005,并且都返回了相同的结果。
Ran*_*gen 15
理论上
以下操作仅用于测试目的。如果您对数据库实例变得不可用、无响应和/或数据丢失感到不满意,请不要尝试任何这些
分离master数据库以尝试重用它的 database_id 是不可能的。
分离model 将导致实例崩溃并且您无法将其重新连接。这导致您必须重建所有系统数据库。此过程会删除所有信息,例如登录名、工作……并且您的用户数据库已分离。
分离Tempdb以尝试重用它的 database_id,通过将其附加回不同的名称导致 database_id 2 未被重用且tempdb无法工作。
name database_id
master 1
model 3
msdb 4
test3_2__ 5
test3_2_ 6
tempdb 7
Run Code Online (Sandbox Code Playgroud)
我能把名字改回tempdb,但是实例很乱,我无法正常启动它。
找不到数据库 ID 2。数据库可能尚未激活或正在转换中。一旦数据库可用,重新发出查询。
--->重建所有系统数据库。
但是,理论上有 2 个(或更多)选项可以更改msdb系统数据库 ID:
您可以更改msdb通过分离数据库ID msdb,创建新的用户数据库,并最终创建一个新的msdb数据库,而下面的记录的步骤来创建一个新的msdb数据库。
您可以msdb通过分离msdb、重新附加到不同的名称并将名称改回msdb.
不支持,请不要这样做
首先以“仅主恢复模式”启动 sql server
NET START MSSQL$InstanceName /f /T3608"
Run Code Online (Sandbox Code Playgroud)
分离 msdb 并创建一个新数据库
EXEC sp_detach_db msdb;
GO
CREATE DATABASE test3;
GO
Run Code Online (Sandbox Code Playgroud)
更改msdb文件名,正常重启实例
初始化 msdb:
SQLCMD -E -S<servername> -i"C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Install\instmsdb.sql" -o"C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Install\instmsdb.out"£
Run Code Online (Sandbox Code Playgroud)
查看数据库ID:
SELECT name,database_id
FROM sys.Databases;
name database_id
master 1
tempdb 2
model 3
test3 4
...
msdb 12
Run Code Online (Sandbox Code Playgroud)
不支持的方法
2.正常的附着过程
sp_attach_db,并create database ... for attach试图连接时不工作msdb。
错误信息:
无法在系统数据库上设置 FILESTREAM 数据库选项,例如“msdb”
您可以做的,仅用于测试目的是创建一个用户数据库, msdb2
CREATE DATABASE msdb2
ON (FILENAME = N'X:\MSSQL\DATA\MSDBData.mdf'),
(FILENAME = N'X:\MSSQL\DATA\MSDBLog.ldf')
FOR ATTACH;
Run Code Online (Sandbox Code Playgroud)
将数据库重命名为 msdb
ALTER DATABASE msdb2 SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO
ALTER DATABASE msdb2 MODIFY NAME = msdb ;
GO
ALTER DATABASE msdb SET MULTI_USER
Run Code Online (Sandbox Code Playgroud)
正常重启实例
NET STOP MSSQL$InstanceName
NET START MSSQL$InstanceName
Run Code Online (Sandbox Code Playgroud)
并查看database_id's:
SELECT name, database_id
FROM sys.databases;
Run Code Online (Sandbox Code Playgroud)
结果
name database_id
master 1
tempdb 2
model 3
test 4
...
msdb 10
Run Code Online (Sandbox Code Playgroud)
在实践中
幸运的是,我没有在任何地方看到过这种情况,但是 database_id 4 理论上可以被用户数据库重用。如果发生这种情况,在我的查询中过滤掉系统数据库可能是我遇到的最少的问题。
也就是说,使用WHERE DB_NAME(database_id) NOT IN ('master','tempdb','model','msdb','distribution','ssisdb')是肯定的选择。
实际上,对于所有当前发布的 SQL Server 版本,这些 ID 将是相同的。
请注意,
distribution&SSISDB数据库也是系统数据库,但没有可预测的database_id。
但是,不能保证情况会一直如此,或者将来会继续如此。Microsoft 不提供文档,也不保证这些 ID 始终相同。可以保证有人进入了数据库并弄乱了这些系统模式。
在 SQL Server 的下一版本中,产品团队可以决定对 ID 编号方案进行更改。该更改可以反向移植到 Service Pack 或累积更新中的现有版本。
这在不久的将来可能不太可能发生,因此您可能不必担心。但是,如果您编写了很棒的代码,那么当这种情况发生时,您的代码可能会在十年或两年后仍在使用。然后,你的继任者将有一个老鼠窝需要解开,你的代码不再是“很棒的代码”。
撇开未来的变化不谈,依赖于神秘的、硬编码的 ID 值的代码是不可读的。不是每个人都知道这schema_id > 16384表示一系列特殊模式。(自世纪之交以来,我一直在使用 SQL Server,我会对那行代码感到困惑。)
让您的代码读起来像散文,您将拥有更好、更易于维护的代码。
| 归档时间: |
|
| 查看次数: |
1005 次 |
| 最近记录: |