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)