10

使用存储过程sp_msforeachtable可以为数据库中的所有表执行脚本。

但是,我想从中排除一些系统表。本能地,我会检查属性IsSystemTableIsMSShipped. 这些不像我期望的那样工作 - 例如,我有一个名为__RefactorLog

系统表

但是当我查询这是一个系统表还是 MS Shipped 表时,SQL Server 报告我的表都不是系统表:

exec (N'EXEC Database..sp_msforeachtable "PRINT ''? = '' + CAST(ObjectProperty(Object_ID(''?''), ''IsSystemTable'') AS VARCHAR(MAX))"') AS LOGIN = 'MyETLUser'
-- Results of IsSystemTable:
[dbo].[__RefactorLog] = 0
[schema].[myUserTable] = 0

exec (N'EXEC Database..sp_msforeachtable "PRINT ''? = '' + CAST(ObjectProperty(Object_ID(''?''), ''IsMSShipped'') AS VARCHAR(MAX))"') AS LOGIN = 'MyETLUser'

-- Results of IsMSShipped:
[dbo].[__RefactorLog] = 0
[schema].[myUserTable] = 0

当我查看表的属性(在 SSMS 内)时,该表被标记为系统对象。IsSystemObject但是不存在类似的对象属性(AFAIK)。

除了对象属性之外,如何检查表是否是系统对象?SSMS 如何检查表是否为系统对象?

4

4 回答 4

12

在对象资源管理器中打开“系统表”文件夹时,Management Studio 2008 似乎运行了一些非常难看的代码,关键位似乎是:

CAST(
 case 
    when tbl.is_ms_shipped = 1 then 1
    when (
        select 
            major_id 
        from 
            sys.extended_properties 
        where 
            major_id = tbl.object_id and 
            minor_id = 0 and 
            class = 1 and 
            name = N''microsoft_database_tools_support'') 
        is not null then 1
    else 0
end          
             AS bit) AS [IsSystemObject]

tbl(的别名在哪里sys.tables

所以它似乎是一个组合——要么is_ms_shippedsys.tables1,要么具有特定的扩展属性集。

于 2012-04-05T14:05:59.517 回答
2

__refactorlog 与 SSMS 所建议的相反,是一个用户表。它用于在部署期间跟踪无法从当前数据库状态推断出的架构更改,例如重命名表。

如果所有其他用户表都在自定义(非 dbo)模式中,则可以使用 isMSshipped/isSystemTable 属性和模式名称的组合来确定表是否在脚本的“范围内”。

于 2012-04-05T17:29:41.260 回答
1

在过去,我一直假设在 sys.objects 表中,列 is_ms_shipped 指示对象是否是系统对象。(此列被其他系统表继承,例如 sys.tables。)

该标志可以由过程 sp_ms_markSystemObject 设置。然而,这是一个未记录的过程,不受 Microsoft 支持,我认为我们不应该知道它,所以我没有告诉你。

于 2012-04-05T14:06:53.307 回答
0

我错过了什么吗?

但是,我想从中排除一些系统表

至少在 SQL Server 2008 上,sp_MSforeachtable 已经排除了系统表,正如它的摘录所示:

+ N' where OBJECTPROPERTY(o.id, N''IsUserTable'') = 1 ' + N' and o.category & ' + @mscat + N' = 0 '
于 2012-04-05T14:15:13.053 回答