Jeśli kiedykolwiek będziesz musiał użyć OBJECT_NAME()
funkcji, aby pobrać nazwę obiektu z innej bazy danych w SQL Server, możesz napotkać problemy, jeśli nie wiesz, jak to działa.
Prawdopodobnie wiesz, że OBJECT_NAME()
akceptuje object_id
argument, który mówi SQL Server, z którego obiektu ma pobrać nazwę.
To, co możesz wiedzieć lub nie, to to, że ta funkcja akceptuje również opcjonalny database_id
argument, który mówi SQL Server, która baza danych zawiera object_id
należy do.
Domyślnie SQL Server zakłada, że object_id
jest w kontekście aktualnej bazy danych. W tym przypadku zapytanie, które odwołuje się do object_id
w innej bazie zwróci NULL lub (co gorsza) niepoprawne wyniki.
Przykład 1 – Zapytanie lokalne (z bieżącej bazy danych)
Po pierwsze, oto lokalne zapytanie, które zwraca nazwę obiektu z bieżącej bazy danych:
USE Music; SELECT nazwa AS [klucz obcy], OBJECT_NAME(parent_object_id) AS [nazwa obiektu nadrzędnego], OBJECT_NAME(referenced_object_id) AS [nazwa obiektu, do którego odwołuje się]FROM Music.sys.foreign_keysWHERE name ='FK_Artists_Country';
Wynik:
Zmieniono kontekst bazy danych na „Muzyka”.+--------------------+----------------- -----+--------------------------+| Klucz obcy | Nazwa obiektu nadrzędnego | Nazwa obiektu, do którego się odwołuje ||--------------------+-----------------------+- -------------------------|| FK_Artists_Country | Artyści | Kraj |+---------------------+-----------------------+--- -----------------------+(1 wiersz dotyczy)
Te wyniki są prawidłowe.
To nie jest zapytanie obejmujące wiele baz danych. To tylko przykład pokazujący, jak ta funkcja jest używana podczas pobierania nazwy obiektu z bieżącej bazy danych.
Przykład 2 – Zapytanie między bazami danych z NIEWŁAŚCIWYMI WYNIKAMI!
Oto zapytanie obejmujące wiele baz danych, które daje nieprawidłowe wyniki.
USE WideWorldImportersDW;SELECT nazwa AS [Klucz obcy], OBJECT_NAME(Id_obiektu nadrzędnego) AS [Nazwa obiektu nadrzędnego], OBJECT_NAME(Id_obiektu_referencyjnego) AS [Nazwa obiektu odniesienia]FROM Music.sys.foreign_keysWHERE nazwa ='FK_Artists_Country';>Wynik:
Zmieniono kontekst bazy danych na „WideWorldImportersDW”.+--------------------+----------------- ------+------------------------------+| Klucz obcy | Nazwa obiektu nadrzędnego | Nazwa obiektu, do którego się odwołuje ||--------------------+-----------------------+- ----------------------------|| FK_Artists_Country | CityKey | PK_Dimension_Payment_Method |+---------------------+-----------------------+--- --------------------------+(1 wiersz dotyczy)Wszystko, co zrobiłem, to przełączenie się do innej bazy danych, a następnie ponowne uruchomienie tego samego zapytania.
Zauważysz, że moje
FROM
klauzula używa trzyczęściowej nazwy w celu określenia nazwy bazy danych (Music
). Pozwala to na znalezienie prawidłowego klucza obcego. Jednak to nie wystarczy, aby zapobiec występowaniu problemów.Jak się okazuje,
WideWorldImportersDW
baza danych zawiera obiekty o tym samymobject_id
które są używane wMusic
Baza danych. Jedynym problemem jest to, że są to zupełnie inne obiekty, o różnych nazwach. Więc wyniki w dwóch ostatnich kolumnach są fałszywe. To są nazwy niewłaściwych obiektów w niewłaściwej bazie danych. Moje zapytanie obejmujące wiele baz danych przecięło przewody i zwróciło niewłaściwe obiekty!Jest to szczególnie niebezpieczne, bo gdybym nie zwracał uwagi, te wyniki mogą wydawać się OK. W końcu nie pojawił się błąd.
Gdyby te identyfikatory obiektów nie istniały w tej bazie danych, prawdopodobnie otrzymałbym wartość NULL (co może ułatwić wykrycie, że coś jest nie tak z wynikami).
Tak czy inaczej, wynik jest po prostu niewłaściwy .
Przykład 3 – Zapytanie między bazami danych z poprawnymi wynikami
Aby naprawić poprzedni przykład (bez zmiany bieżącej bazy danych), musimy podać identyfikator bazy danych, z której chcemy uzyskać nazwę obiektu.
Tak:
USE WideWorldImportersDW;SELECT nazwa AS [Klucz obcy], OBJECT_NAME(Id_obiektu nadrzędnego, 5) AS [Nazwa obiektu nadrzędnego], OBJECT_NAME(Id_obiektu, do którego się odnosisz, 5) AS [Nazwa obiektu, do którego odwołuje się]FROM Music.sys.foreign_keysWHERE nazwa =„FK”_Artists_Country;Wynik:
Zmieniono kontekst bazy danych na „WideWorldImportersDW”.+--------------------+----------------- -----+--------------------------+| Klucz obcy | Nazwa obiektu nadrzędnego | Nazwa obiektu, do którego się odwołuje ||--------------------+-----------------------+- -------------------------|| FK_Artists_Country | Artyści | Kraj |+---------------------+-----------------------+--- -----------------------+(1 wiersz dotyczy)Ponownie, żeby było jasne, aktualna baza danych to
WideWorldImportersDW
, ale obiekty znajdują się w innej bazie danych o nazwieMusic
, który ma identyfikator bazy danych równy 5.Przykład 4 – Jak uzyskać identyfikator bazy danych
Jest całkiem prawdopodobne, że nie będziesz wiedział, jaki identyfikator bazy danych jest na górze twojej głowy. Prawdopodobnie będziesz znać nazwę bazy danych, ale nie jej identyfikator.
Na szczęście możesz użyć
DB_ID()
funkcja zwracająca identyfikator bazy danych na podstawie jej nazwy.Dlatego możemy zmodyfikować poprzedni przykład w następujący sposób:
USE WideWorldImportersDW;SELECT nazwa AS [Klucz obcy], OBJECT_NAME(Id_obiektu_nadrzędnego, DB_ID('Muzyka')) AS [Nazwa obiektu nadrzędnego], OBJECT_NAME(Id_obiektu referencyjnego, DB_ID('Muzyka')) AS [Nazwa obiektu, do którego odwołuje się] FROM Music.sys.foreign_keysWHERE nazwa ='FK_Artists_Country';Wynik:
Zmieniono kontekst bazy danych na „WideWorldImportersDW”.+--------------------+----------------- -----+--------------------------+| Klucz obcy | Nazwa obiektu nadrzędnego | Nazwa obiektu, do którego się odwołuje ||--------------------+-----------------------+- -------------------------|| FK_Artists_Country | Artyści | Kraj |+---------------------+-----------------------+--- -----------------------+(1 wiersz dotyczy)