Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Comment obtenir un OBJECT_NAME() à partir d'une autre base de données dans SQL Server

Si jamais vous avez besoin d'utiliser le OBJECT_NAME() pour obtenir le nom d'un objet à partir d'une base de données différente dans SQL Server, vous pourriez rencontrer des problèmes si vous ne savez pas comment cela fonctionne.

Vous savez probablement que OBJECT_NAME() accepte un object_id argument qui indique à SQL Server de quel objet obtenir le nom.

Ce que vous savez peut-être ou non, c'est que cette fonction accepte également un database_id facultatif argument qui indique à SQL Server quelle base de données le object_id appartient à.

Par défaut, SQL Server suppose que object_id est dans le contexte de la base de données actuelle. Dans ce cas, une requête qui référence un object_id dans une autre base de données renverra NULL ou (pire encore) des résultats incorrects.

Exemple 1 - Requête locale (à partir de la base de données actuelle)

Tout d'abord, voici une requête locale qui renvoie le nom de l'objet de la base de données actuelle :

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';

Résultat :

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

Ces résultats sont corrects.

Il ne s'agit pas d'une requête inter-base de données. Ceci est juste un exemple pour montrer comment cette fonction est utilisée lors de l'obtention du nom d'un objet à partir de la base de données actuelle.

Exemple 2 – Requête inter-base de données avec des RÉSULTATS INCORRECTS !

Maintenant, voici une requête inter-base de données qui produit des résultats incorrects.

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';

Résultat :

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

Tout ce que j'ai fait, c'est passer à une autre base de données, puis exécuter à nouveau la même requête.

Vous remarquerez que mon FROM La clause utilise un nom en trois parties afin de spécifier le nom de la base de données (Music ). Cela permet de trouver la bonne clé étrangère. Cependant, cela ne suffit pas pour empêcher les problèmes de se produire.

Il s'avère que le WideWorldImportersDW la base de données a des objets avec le même object_id qui sont utilisés dans la Music base de données. Le seul problème est que ce sont des objets complètement différents, avec des noms différents. Les résultats des deux dernières colonnes sont donc faux. Ce sont les noms des mauvais objets, sur la mauvaise base de données. Ma requête cross-database s'est croisée les fils et a renvoyé les mauvais objets !

C'est particulièrement dangereux, car si je n'y prêtais pas attention, ces résultats pourraient sembler corrects. Après tout, je n'ai pas eu d'erreur.

Si ces ID d'objet n'existaient pas dans cette base de données, j'aurais probablement obtenu une valeur NULL (ce qui pourrait faciliter la détection d'un problème avec les résultats).

Dans tous les cas, le résultat est simplement faux .

Exemple 3 - Requête inter-base de données avec des résultats CORRECTS

Pour corriger l'exemple précédent (sans changer la base de données actuelle), nous devons fournir l'ID de la base de données dont nous voulons le nom de l'objet.

Comme ceci :

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';

Résultat :

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

Encore une fois, juste pour être clair, la base de données actuelle est WideWorldImportersDW , mais les objets sont sur une base de données différente appelée Music , dont l'ID de base de données est 5.

Exemple 4 - Comment obtenir l'ID de la base de données

Il est fort probable que vous ne sachiez pas quel est l'ID de la base de données par tête. Vous connaîtrez probablement le nom de la base de données, mais pas son ID.

Heureusement, vous pouvez utiliser le DB_ID() fonction pour renvoyer l'ID de la base de données, en fonction de son nom.

Par conséquent, nous pouvons modifier l'exemple précédent comme suit :

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';

Résultat :

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