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

Cad*_*oux 14 sql-server metadata sql-server-2005

例:

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'))
Run Code Online (Sandbox Code Playgroud)

显然,元数据函数需要当前的数据库.对于像以下这样的函数,BOL条目通常具有这样的语言OBJECT_NAME:

Microsoft SQL Server 2005数据库引擎假定object_id位于当前数据库的上下文中.引用另一个数据库中的object_id的查询返回NULL或不正确的结果.

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

  1. 我无法在SP中使用其他数据库

  2. 我不能在其他数据库或master(或我自己的任何其他数据库)中创建代理UDF存根(或更改任何东西)来帮助我.

那么如何从OBJECT_ID('AnotherDB.ASchema.ATable')ThisDB中获取数据库呢?

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

gbn*_*gbn 21

你应该能够做到这一点:

SELECT
   name
FROM
    AnotherDB.sys.objects   --changes context
WHERE
    object_id = OBJECT_ID('AnotherDB.ASchema.ATable')
Run Code Online (Sandbox Code Playgroud)

这就是你有效地做的事情 OBJECT_ID('AnotherDB.ASchema.ATable')

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

注意:新的目录视图旨在使用,而不是根据链接从版本更改为版本.在过去,使用系统表是不好的做法,但耻辱仍然存在.因此,您可以安全地依赖sys.objects而不是元数据功能.


Bri*_*edt 10

我是否正确理解你想要AnotherDB的db id?

SELECT *
FROM    master..sysdatabases
WHERE   name = 'AnotherDB'
Run Code Online (Sandbox Code Playgroud)

否则,如果有帮助,您可以在动态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
Run Code Online (Sandbox Code Playgroud)

或者在其他dbs中执行SP:

EXEC AnotherDB.dbo.ProcedureName 
      @paramX = ...
,     @paramY = ...
Run Code Online (Sandbox Code Playgroud)


boy*_*dc7 5

查看TSQL中的PARSENAME函数 - 将允许您拉出完全(或非完全)限定名称的任何4部分部分.对于示例中的数据库:

select parsename('AnotherDB.ASchema.ATable',3)
Run Code Online (Sandbox Code Playgroud)

收益:

AnotherDB

select parsename('AnotherDB.ASchema.ATable',2)
Run Code Online (Sandbox Code Playgroud)

收益:

ASchema

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

select parsename('ASchema.ATable',3)
Run Code Online (Sandbox Code Playgroud)

收益:

空值

  • 不,本机功能不可能 - 除了检查实例上的每个数据库是否匹配给定的非限定名称的对象之外,真的没办法做到这一点,但是你如何处理可能的冲突呢?您可以轻松地创建一个过程,该过程将遍历系统中的所有数据库,查找与给定模式/名称匹配的对象(或许利用sp_MSforeachdb系统过程,或者只是通过sys.databases的游标) - 这就是您想要的?即如果没有db限定,则返回所有具有与给定模式/名称匹配的对象的数据库? (2认同)