Als u ooit de OBJECT_NAME()
. moet gebruiken functie om de naam van een object uit een andere database in SQL Server te halen, kunt u problemen tegenkomen als u niet weet hoe het werkt.
U weet waarschijnlijk dat OBJECT_NAME()
accepteert een object_id
argument dat SQL Server vertelt van welk object de naam moet worden opgehaald.
Wat je wel of niet weet, is dat deze functie ook een optionele database_id
. accepteert argument dat SQL Server vertelt welke database de object_id
behoort.
Standaard gaat SQL Server ervan uit dat object_id
is in de context van de huidige database. In dit geval een query die verwijst naar een object_id
in een andere database zal NULL of (nog erger) onjuiste resultaten opleveren.
Voorbeeld 1 – Lokale zoekopdracht (van huidige database)
Ten eerste is hier een lokale query die de objectnaam uit de huidige database retourneert:
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';
Resultaat:
Changed database context to 'Music'. +--------------------+----------------------+--------------------------+ | Foreign Key | Parent Object Name | Referenced Object Name | |--------------------+----------------------+--------------------------| | FK_Artists_Country | Artists | Country | +--------------------+----------------------+--------------------------+ (1 row affected)
Deze resultaten zijn correct.
Dit is geen cross-databasequery. Dit is slechts een voorbeeld om te laten zien hoe deze functie wordt gebruikt bij het ophalen van de naam van een object uit de huidige database.
Voorbeeld 2 – Cross-databasequery met VERKEERDE RESULTATEN!
Nu, hier is een cross-databasequery die onjuiste resultaten oplevert.
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';>
Resultaat:
Changed database context to 'WideWorldImportersDW'. +--------------------+----------------------+-----------------------------+ | Foreign Key | Parent Object Name | Referenced Object Name | |--------------------+----------------------+-----------------------------| | FK_Artists_Country | CityKey | PK_Dimension_Payment_Method | +--------------------+----------------------+-----------------------------+ (1 row affected)
Het enige wat ik deed was overschakelen naar een andere database en dezelfde query opnieuw uitvoeren.
Je zult merken dat mijn FROM
clausule gebruikt een driedelige naam om de naam van de database te specificeren (Music
). Hierdoor kan de juiste externe sleutel worden gevonden. Dit is echter niet voldoende om problemen te voorkomen.
Het blijkt dat de WideWorldImportersDW
database heeft objecten met dezelfde object_id
die worden gebruikt in de Music
databank. Het enige probleem is dat het totaal verschillende objecten zijn, met verschillende namen. Dus de resultaten in de laatste twee kolommen zijn nep. Dit zijn de namen van de verkeerde objecten, in de verkeerde database. Mijn cross-database query heeft de draden gekruist en de verkeerde objecten geretourneerd!
Dit is bijzonder gevaarlijk, want als ik niet oplette, zouden deze resultaten in orde kunnen lijken. Ik kreeg tenslotte geen foutmelding.
Als deze object-ID's niet in deze database bestonden, zou ik waarschijnlijk een NULL-waarde hebben gekregen (waardoor het gemakkelijker zou kunnen zijn om te detecteren dat er iets mis is met de resultaten).
Hoe dan ook, het resultaat is gewoon fout .
Voorbeeld 3 – Cross-databasequery met JUISTE resultaten
Om het vorige voorbeeld te corrigeren (zonder de huidige database te wijzigen), moeten we de ID opgeven van de database waarvan we de naam van het object willen hebben.
Zoals dit:
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';
Resultaat:
Changed database context to 'WideWorldImportersDW'. +--------------------+----------------------+--------------------------+ | Foreign Key | Parent Object Name | Referenced Object Name | |--------------------+----------------------+--------------------------| | FK_Artists_Country | Artists | Country | +--------------------+----------------------+--------------------------+ (1 row affected)
Nogmaals, voor alle duidelijkheid:de huidige database is WideWorldImportersDW
, maar de objecten bevinden zich in een andere database genaamd Music
, die een database-ID van 5 heeft.
Voorbeeld 4 – Hoe de database-ID te verkrijgen
Het is vrij waarschijnlijk dat u niet weet wat de ID van de database is uit uw hoofd. U kent waarschijnlijk de naam van de database, maar niet de ID.
Gelukkig kun je de DB_ID()
. gebruiken functie om de ID van de database te retourneren, gebaseerd op de naam.
Daarom kunnen we het vorige voorbeeld als volgt wijzigen:
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';
Resultaat:
Changed database context to 'WideWorldImportersDW'. +--------------------+----------------------+--------------------------+ | Foreign Key | Parent Object Name | Referenced Object Name | |--------------------+----------------------+--------------------------| | FK_Artists_Country | Artists | Country | +--------------------+----------------------+--------------------------+ (1 row affected)