Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Como obter um OBJECT_NAME() de um banco de dados diferente no SQL Server


Se você precisar usar o OBJECT_NAME() função para obter o nome de um objeto de um banco de dados diferente no SQL Server, você pode ter problemas se não souber como ele funciona.

Você provavelmente sabe que OBJECT_NAME() aceita um object_id argumento que informa ao SQL Server de qual objeto obter o nome.

O que você pode ou não saber é que esta função também aceita um database_id opcional argumento que informa ao SQL Server qual banco de dados o object_id pertence a.

Por padrão, o SQL Server assume que object_id está no contexto do banco de dados atual. Nesse caso, uma consulta que faz referência a um object_id em outro banco de dados retornará NULL ou (pior ainda) resultados incorretos.


Exemplo 1 – Consulta local (do banco de dados atual)


Primeiro, aqui está uma consulta local que retorna o nome do objeto do banco de dados atual:
USE Music;
SELECT
  name AS [Foreign Key],
  OBJECT_NAME(parent_object_id) AS [Parent Object Name],
  OBJECT_NAME(referenced_object_id) AS [Referenced Object Name]
FROM Music.sys.foreign_keys
WHERE name = 'FK_Artists_Country';

Resultado:
Changed database context to 'Music'.
+--------------------+----------------------+--------------------------+
| Foreign Key        | Parent Object Name   | Referenced Object Name   |
|--------------------+----------------------+--------------------------|
| FK_Artists_Country | Artists              | Country                  |
+--------------------+----------------------+--------------------------+
(1 row affected)

Esses resultados estão corretos.

Esta não é uma consulta entre bancos de dados. Este é apenas um exemplo para mostrar como esta função é usada ao obter o nome de um objeto do banco de dados atual.

Exemplo 2 – Consulta entre bancos de dados com RESULTADOS ERRADOS!


Agora, aqui está uma consulta entre bancos de dados que produz resultados incorretos.
USE WideWorldImportersDW;
SELECT
  name AS [Foreign Key],
  OBJECT_NAME(parent_object_id) AS [Parent Object Name],
  OBJECT_NAME(referenced_object_id) AS [Referenced Object Name]
FROM Music.sys.foreign_keys
WHERE name = 'FK_Artists_Country';

Resultado:
Changed database context to 'WideWorldImportersDW'.
+--------------------+----------------------+-----------------------------+
| Foreign Key        | Parent Object Name   | Referenced Object Name      |
|--------------------+----------------------+-----------------------------|
| FK_Artists_Country | CityKey              | PK_Dimension_Payment_Method |
+--------------------+----------------------+-----------------------------+
(1 row affected)

Tudo o que fiz foi mudar para um banco de dados diferente e executar a mesma consulta novamente.

Você notará que meu FROM cláusula usa um nome de três partes para especificar o nome do banco de dados (Music ). Isso permite que a chave estrangeira correta seja encontrada. No entanto, isso não é suficiente para evitar que problemas ocorram.

Acontece que o WideWorldImportersDW banco de dados tem objetos com o mesmo object_id que são usados ​​no Music base de dados. O único problema é que são objetos completamente diferentes, com nomes diferentes. Portanto, os resultados nas duas últimas colunas são falsos. Esses são os nomes dos objetos errados, no banco de dados errado. Minha consulta entre bancos de dados cruzou os fios e retornou os objetos errados!

Isso é particularmente perigoso, porque se eu não estivesse prestando atenção, esses resultados poderiam parecer bons. Afinal, não recebi nenhum erro.

Se esses IDs de objeto não existissem neste banco de dados, eu provavelmente teria obtido um valor NULL (o que pode facilitar a detecção de que algo está errado com os resultados).

De qualquer forma, o resultado é simplesmente errado .

Exemplo 3 – Consulta entre bancos de dados com resultados CORRETOS


Para corrigir o exemplo anterior (sem alterar o banco de dados atual), precisamos fornecer o ID do banco de dados do qual queremos o nome do objeto.

Assim:
USE WideWorldImportersDW;
SELECT
  name AS [Foreign Key],
  OBJECT_NAME(parent_object_id, 5) AS [Parent Object Name],
  OBJECT_NAME(referenced_object_id, 5) AS [Referenced Object Name]
FROM Music.sys.foreign_keys
WHERE name = 'FK_Artists_Country';

Resultado:
Changed database context to 'WideWorldImportersDW'.
+--------------------+----------------------+--------------------------+
| Foreign Key        | Parent Object Name   | Referenced Object Name   |
|--------------------+----------------------+--------------------------|
| FK_Artists_Country | Artists              | Country                  |
+--------------------+----------------------+--------------------------+
(1 row affected)

Novamente, apenas para esclarecer, o banco de dados atual é WideWorldImportersDW , mas os objetos estão em um banco de dados diferente chamado Music , que tem um ID de banco de dados de 5.

Exemplo 4 – Como obter o ID do banco de dados


É bem provável que você não saiba qual é o ID do banco de dados de cabeça. Você provavelmente saberá o nome do banco de dados, mas não seu ID.

Felizmente você pode usar o DB_ID() função para retornar o ID do banco de dados, com base em seu nome.

Portanto, podemos modificar o exemplo anterior da seguinte forma:
USE WideWorldImportersDW;
SELECT
  name AS [Foreign Key],
  OBJECT_NAME(parent_object_id, DB_ID('Music')) AS [Parent Object Name],
  OBJECT_NAME(referenced_object_id, DB_ID('Music')) AS [Referenced Object Name]
FROM Music.sys.foreign_keys
WHERE name = 'FK_Artists_Country';

Resultado:
Changed database context to 'WideWorldImportersDW'.
+--------------------+----------------------+--------------------------+
| Foreign Key        | Parent Object Name   | Referenced Object Name   |
|--------------------+----------------------+--------------------------|
| FK_Artists_Country | Artists              | Country                  |
+--------------------+----------------------+--------------------------+
(1 row affected)