Подтвердить что ты не робот

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

Пример:

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 Engine предполагает, что object_id находится в контекст текущей базы данных. запрос, ссылающийся на object_id в другая база данных возвращает NULL или неправильные результаты.

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

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

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

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

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

4b9b3361

Ответ 1

Правильно ли я понимаю, что вам нужен идентификатор db из другогоDB?

SELECT *
FROM    master..sysdatabases
WHERE   name = 'AnotherDB'

В противном случае вы можете использовать другой db в динамическом 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 в других dbs с помощью:

EXEC AnotherDB.dbo.ProcedureName 
      @paramX = ...
,     @paramY = ...

Ответ 2

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

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.object, а не на функции метаданных.

Ответ 3

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

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

возвращает:

AnotherDB

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

возвращает:

ASchema

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

select parsename('ASchema.ATable',3)

возвращает:

NULL

Ответ 4

У меня была такая же проблема, но с OJBECT_SCHEMA_NAME. После ответа chadhoc с использованием parseame работает с 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)))