【问题标题】:How to identify system objects when viewing list of SQL Server database objects?查看 SQL Server 数据库对象列表时如何识别系统对象?
【发布时间】:2025-12-19 19:10:12
【问题描述】:

我正在尝试列出服务器上所有数据库中的所有存储过程,但我似乎无法可靠地过滤掉系统对象。我正在使用:

SELECT *
  FROM sysobjects
 WHERE id > 100

这似乎在除 MSDB 之外的每个数据库中都能正常工作,MSDB 充满了大量具有正常 ID 的存储过程,但它们是系统存储的过程。据我所知,我无法使用 sysobjects 表中的任何值过滤掉系统存储的过程 - 有没有人知道可以用来过滤的值?

它们都被标记为 type="P",这意味着它是一个存储过程,但似乎没有标志来指定它是系统存储过程还是用户存储过程。我可以使用 sys.objects 视图并筛选“IsMsShipped=0”,但我想要一些也适用于 SQL 2000 的东西,所以如果可能的话,我更喜欢使用旧视图(如 sysobjects)。

【问题讨论】:

    标签: sql-server sql-server-2008 database-schema


    【解决方案1】:

    这适用于我的 SQL Server 2008 R2 安装。除了用户数据库,我什么都看不到

    SELECT 
        *
    FROM
       sys.objects
    WHERE
       OBJECTPROPERTY(object_id, 'IsMSShipped') = 0
    

    您可以将sys.objects 更改为 sys.tables 并且它仍然有效,或者使用“类型”列进行过滤。或者使用 OBJECTPROPERTY(object_id, 'IsProcedure') 等。

    注意:在 SQL Server 2005+ 中是 sys.objects

    注意 2:OBJECTPROPERTY 也适用于 SQL Server 2000:

    SELECT 
        *
    FROM
       sysobjects
    WHERE
       OBJECTPROPERTY(id, 'IsMSShipped') = 0
    

    【讨论】:

    • 这可能是我必须使用的,因为我在较新的系统视图中注意到该属性,但我希望有一个易于访问的属性在 2000 年作为好吧。
    • er... OBJECTPROPERTY 也在 SQL Server 2000 中 msdn.microsoft.com/en-us/library/aa276849(SQL.80).aspx
    • 嗯 - 确实如此,而且我刚刚确认我的脚本仍在 2000 服务器上运行。感谢您的帮助!
    • 我认为@gbn 是对的,所以我相信SELECT * FROM sysobjects WHERE OBJECTPROPERTY(id, 'IsMSShipped') = 0 会在2000 年发挥作用。对吧?
    【解决方案2】:

    SQL Server 2005 及更高版本

    SELECT
      SCHEMA_NAME(obj.schema_id) AS schema_name,
      obj.name AS proc_name
    FROM
      sys.procedures obj WITH(NOLOCK)
    ORDER BY
      schema_name,
      proc_name
    

    SQL Server 2000

    SELECT
      USER_NAME(obj.uid) AS user_name,
      obj.name AS proc_name,
    FROM
      sysobjects obj WITH(NOLOCK)
    WHERE
      (obj.status & 0x80000000) = 0
      AND RTRIM(obj.xtype) IN ('P', 'RF')
    ORDER BY
      user_name,
      proc_name
    

    【讨论】:

      【解决方案3】:

      在某些 SQL 版本中(我不知道这是从哪个版本开始的),至少在一种情况下,数据库可以包含具有设置为 false 的 IsMSShipped 属性的系统对象.

      由于能够将数据库图表添加到数据库,因此通常会在初始安装后添加后续对象,此时用户(例如,在 SSMS 中)发起创建数据库图表的请求。

      我会将之前接受的答案修改如下:

      SELECT 
          *
      FROM
         sysobjects obj
      WHERE
         OBJECTPROPERTY(obj.id, 'IsMSShipped') = 0
      AND (CAST(
          CASE
              WHEN (
                  SELECT 
                      major_id 
                  FROM 
                      sys.extended_properties 
                  WHERE 
                      major_id = obj.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)) = 0
      

      这个额外的子查询取自 SSMS 在获取(非)系统对象列表时执行的代码。

      【讨论】: