OBJECT_ID объекта в другой базе данных - как найти идентификатор базы данных или имя / полное имя объекта? - PullRequest
14 голосов
/ 04 декабря 2009

Пример:

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_NAME и т. Д.

База данных Microsoft SQL Server 2005 Двигатель предполагает, что object_id находится в контекст текущей базы данных. запрос, который ссылается на object_id в другая база данных возвращает NULL или неверные результаты.

Причины, по которым мне нужно это сделать:

  1. Я не могу использовать другую базу данных из SP

  2. Я не могу создать заглушку прокси UDF (или изменить что-либо) в других базах данных или в master (или любой другой базе данных, кроме моей), чтобы выручить меня.

Так как я могу получить базу данных из OBJECT_ID('AnotherDB.ASchema.ATable'), когда я нахожусь в ThisDB?

Моя цель - взять, возможно, частично определенное имя из таблицы конфигурации, преобразовав его в текущем контексте в полное имя, использовать PARSENAME, чтобы получить имя базы данных, а затем динамический SQL, чтобы построить сценарий, чтобы получить непосредственно к таблицам метаданных с помощью database.sys.* или USE db; sys.*

Ответы [ 5 ]

20 голосов
/ 05 декабря 2009

Вы должны быть в состоянии сделать это:

SELECT
   name
FROM
    AnotherDB.sys.objects   --changes context
WHERE
    object_id = OBJECT_ID('AnotherDB.ASchema.ATable')

Это то, что вы эффективно делаете с OBJECT_ID('AnotherDB.ASchema.ATable')

Это означает, что вы можете положиться на объекты dbname.sys.object и избежать путаницы с функциями метаданных.

Примечание: новые каталоги предназначены для использования и не меняются от версии к версии согласно ссылке. В старые времена считалось плохой практикой использовать системные таблицы, но клеймо все еще остается. Таким образом, вы можете смело полагаться на sys.objects, а не на метаданные.

10 голосов
/ 04 декабря 2009

Правильно ли я понимаю, что вам нужен идентификатор базы данных AnotherDB?

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 = ...
5 голосов
/ 04 декабря 2009

Взгляните на функцию PARSENAME в TSQL - она ​​позволит вам извлечь любую из четырех частей полностью (или не полностью) квалифицированного имени. Для базы данных в вашем примере:

select parsename('AnotherDB.ASchema.ATable',3)

возвращается:

AnotherDB

select parsename('AnotherDB.ASchema.ATable',2)

возвращается:

ASchema

Если вы не полностью квалифицированы, вы получите нулевые результаты, если попросите часть имени, которая не включена в строку:

select parsename('ASchema.ATable',3)

возвращается:

NULL

2 голосов
/ 02 ноября 2016

У меня была такая же проблема, но и с 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)))
0 голосов
/ 21 февраля 2019

Я использовал следующее решение:

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
...