例:
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'))
显然,元数据函数需要当前的数据库。对于像OBJECT_NAME
等函数,BOL条目通常具有这样的语言:
Microsoft SQL Server 2005数据库引擎假定object_id位于当前数据库的上下文中。引用另一个数据库中的object_id的查询返回NULL或不正确的结果。
我需要能够做到这一点的原因:
那么当我在ThisDB中时,如何从OBJECT_ID('AnotherDB.ASchema.ATable')
获取数据库?
我的目标是从配置表中获取一个可能部分限定的名称,在当前上下文中将其解析为完全限定名称,使用PARSENAME获取数据库名称,然后使用动态SQL构建脚本以便能够访问元数据数据表直接与database.sys.*
或USE db; sys.*
我是否正确理解你想要AnotherDB的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
或者在其他dbs中执行SP:
EXEC AnotherDB.dbo.ProcedureName
@paramX = ...
, @paramY = ...
你应该能够做到这一点:
SELECT
name
FROM
AnotherDB.sys.objects --changes context
WHERE
object_id = OBJECT_ID('AnotherDB.ASchema.ATable')
这就是你用OBJECT_ID('AnotherDB.ASchema.ATable')
有效做的事情
这意味着您可以依赖dbname.sys.objects并避免与元数据函数混淆。
注意:new Catalog views旨在使用,而不是根据链接从版本更改为版本。在过去,使用系统表是不好的做法,但耻辱仍然存在。因此,您可以安全地依赖sys.objects而不是元数据功能。
看看PARSENAME function in TSQL - 将允许你拉出完全(或非完全)限定名称的任何4部分。对于示例中的数据库:
select parsename('AnotherDB.ASchema.ATable',3)
收益:
AnotherDB
select parsename('AnotherDB.ASchema.ATable',2)
收益:
架构
如果您是非完全限定的,那么如果您要求未包含在字符串中的名称部分,您将获得null结果:
select parsename('ASchema.ATable',3)
收益:
空值
我有同样的问题,但也有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