Sql server 对象\另一个数据库中对象的ID-如何查找数据库ID或名称/完全限定的对象名称?

Sql server 对象\另一个数据库中对象的ID-如何查找数据库ID或名称/完全限定的对象名称?,sql-server,sql-server-2005,metadata,Sql Server,Sql Server 2005,Metadata,例如: USE AnotherDB -- This works - same ID as from other DB SELECT OBJECT_ID('AnotherDB.ASchema.ATable') -- This works SELECT OBJECT_NAME(OBJECT_ID('AnotherDB.ASchema.ATable')) USE ThisDB -- This works - same ID as from other DB SELECT OBJECT_ID('Ano

例如:

USE AnotherDB
-- This works - same ID as from other DB
SELECT OBJECT_ID('AnotherDB.ASchema.ATable')
-- This works
SELECT OBJECT_NAME(OBJECT_ID('AnotherDB.ASchema.ATable'))

USE ThisDB
-- This works - same ID as from other DB
SELECT OBJECT_ID('AnotherDB.ASchema.ATable')
-- Gives NULL
SELECT OBJECT_NAME(OBJECT_ID('AnotherDB.ASchema.ATable'))
显然,元数据函数需要一个当前数据库。BOL条目的语言通常与以下函数类似:
OBJECT\u NAME
等:

Microsoft SQL Server 2005数据库 引擎假定对象_id处于 当前数据库的上下文。A. 在中引用对象\u id的查询 另一个数据库返回NULL或 结果不正确

我需要能够做到这一点的原因:

SELECT
   name
FROM
    AnotherDB.sys.objects   --changes context
WHERE
    object_id = OBJECT_ID('AnotherDB.ASchema.ATable')
  • 我无法从SP中使用其他数据库

  • 我无法在其他数据库或master(或除我自己的数据库之外的任何其他数据库)中创建代理UDF存根(或更改任何内容)来帮助我

  • 那么,当我在这个数据库中时,如何从
    OBJECT\u ID('AnotherDB.ASchema.ATable')
    获取数据库呢


    我的目标是从配置表中获取可能部分限定的名称,在当前上下文中将其解析为完全限定的名称,使用PARSENAME获取数据库名称,然后使用动态SQL构建脚本,以便能够使用
    database.sys.*
    use db直接访问元数据表;sys.*

    我是否正确理解您想要另一个db的db id

    SELECT *
    FROM    master..sysdatabases
    WHERE   name = 'AnotherDB'
    
    否则,如果有帮助,您可以在动态SQL中使用其他数据库:

    DECLARE @SQL    NVARCHAR(MAX)
    ,   @objId  INT
    
    SET @SQL = N'
        USE AnotherDB
    
        SELECT  @id = OBJECT_ID(''customer'')
    '
    
    EXEC SP_EXECUTESQL @SQL
        ,   N'@id INT OUTPUT'
        ,   @id = @objId OUTPUT
    
    SELECT  @objId
    
    或通过以下方式在其他数据库中执行SP:

    EXEC AnotherDB.dbo.ProcedureName 
          @paramX = ...
    ,     @paramY = ...
    
    查看-将允许您提取完全(或非完全)限定名称的任何4部分。对于示例中的数据库:

    select parsename('AnotherDB.ASchema.ATable',3)
    
    返回:

    另一个数据库

    select parsename('AnotherDB.ASchema.ATable',2)
    
    返回:

    阿斯切马

    如果是非完全限定的,则如果您请求名称中未包含在字符串中的部分,则将得到null结果:

    select parsename('ASchema.ATable',3)
    
    返回:


    您应该能够执行以下操作:

    SELECT
       name
    FROM
        AnotherDB.sys.objects   --changes context
    WHERE
        object_id = OBJECT_ID('AnotherDB.ASchema.ATable')
    
    这就是使用
    OBJECT\u ID('AnotherDB.ASchema.ATable')有效地执行的操作。

    这意味着您可以依赖dbname.sys.objects并避免与元数据函数混淆

    注意:根据链接,设计用于不同版本,不随版本更改。过去,使用系统表被认为是不好的做法,但耻辱仍然存在。
    因此,您可以安全地依赖sys.objects,而不是元数据功能。

    我也有同样的问题,但OJBECT_SCHEMA_NAME也是如此。下面是chadhoc使用parsename的响应,它与OBJECT_NAME一起工作,如下所示:

    DECLARE @OrigTableName NVARCHAR(MAX);
    
    SELECT @OrigTableName = 'AnotherDB.ASchema.ATable'
    
    SELECT OBJECT_NAME(OBJECT_ID(@OrigTableName), DB_ID(PARSENAME(@OrigTableName, 3)))
    , OBJECT_SCHEMA_NAME(OBJECT_ID(@OrigTableName), DB_ID(PARSENAME(@OrigTableName, 3)))
    

    我使用了以下解决方案:

    DECLARE @SchemaName varchar(255) = 'SchemaName'
    DECLARE @ObjectName varchar(255) = 'ObjectName'
    
    SELECT     o.*
    FROM       AnotherDB.sys.objects AS o
    INNER JOIN AnotherDB.sys.schemas AS s ON o.schema_id = s.schema_id
    WHERE      s.name = @SchemaName
    AND        o.name = @ObjectName
    

    是的,有没有一种方法可以从对象名(可能是完全限定的,也可能不是完全限定的-表、schema.table或db.schema.table)?对-归结起来就是获取一个可能的部分限定名,在当前上下文中解析它,然后使用PARSENAME获取数据库名称,然后类似于动态执行我的其余工作所需的操作。是因为您拥有某个对象的实际id,例如234521345,并且希望从另一个数据库检索id的名称。。但是你有所有dbs的名称吗?我并不需要ID,但是如果我在途中使用了一个,那就好了。如果我可以将部分限定名解析为完全限定名,那就太好了。您知道如何做到这一点吗?不,本机功能不可能做到这一点-除了检查实例上的每个数据库中是否有与给定的非限定名称匹配的对象之外,真的没有其他方法可以做到这一点,但是您如何处理可能的冲突?您可以轻松地创建一个过程,该过程将遍历系统上的所有数据库,查找与给定模式/名称匹配的对象(可能利用sp_MSforeachdb系统过程,或者只是遍历sys.databases的游标)——这就是您想要的吗?i、 e.如果没有db qualified,则返回所有具有与给定架构/名称匹配的对象的数据库?实际上,它非常简单,isnull(parsename('unqualified',3),db_name()。这显然是假设非限定名称应该解析为当前DB,但这不是一个延伸,因为这是预期的行为。如果您已经拥有完全限定的名称,这是毫无意义的。只需像@ChadHoc那样使用一次
    ParseName()
    <代码>选择PARSENAME('AnotherDB.ASchema.ATable',1)将返回
    ATable
    。这比为相同的值调用4个函数(
    Object\u Name
    Object\u ID
    DB\u ID
    ParseName
    )的开销要好得多,也更清晰。