Pokud budete někdy potřebovat použít OBJECT_NAME()
Funkce pro získání názvu objektu z jiné databáze na SQL Serveru, můžete narazit na problémy, pokud nevíte, jak to funguje.
Pravděpodobně víte, že OBJECT_NAME()
přijímá object_id
argument, který říká serveru SQL Server, ze kterého objektu má získat název.
Co možná víte, ale možná ne, je, že tato funkce přijímá také nepovinné database_id
argument, který říká SQL Serveru, která databáze má object_id
patří.
Ve výchozím nastavení SQL Server předpokládá object_id
je v kontextu aktuální databáze. V tomto případě dotaz, který odkazuje na object_id
v jiné databázi vrátí NULL nebo (ještě hůř) nesprávné výsledky.
Příklad 1 – Místní dotaz (z aktuální databáze)
Nejprve je zde místní dotaz, který vrátí název objektu z aktuální databáze:
POUŽÍVEJTE hudbu; VYBERTE název JAKO [Zahraniční klíč], OBJECT_NAME(id nadřazeného_objektu) AS [Název nadřazeného objektu], OBJECT_NAME(id_referencovaného_objektu) AS [Název odkazovaného objektu]FROM Music.sys.foreign_keysWHERE name ='FK_Artists_Country';
Výsledek:
Kontext databáze byl změněn na „Hudba“.+--------------------+----------------- -----+--------------------------+| Cizí klíč | Název nadřazeného objektu | Název odkazovaného objektu ||--------------------+----------------------+- -------------------------|| FK_Artists_Country | Umělci | Země |+--------------------+----------------------+--- -----------------------+ (dotčen 1 řádek)
Tyto výsledky jsou správné.
Toto není dotaz napříč databázemi. Toto je pouze příklad, který ukazuje, jak se tato funkce používá při získávání názvu objektu z aktuální databáze.
Příklad 2 – Dotaz napříč databázemi s NESPRÁVNÝMI VÝSLEDKY!
Nyní je zde dotaz napříč databázemi, který produkuje nesprávné výsledky.
USE WideWorldImportersDW;SELECT name AS [cizí klíč], OBJECT_NAME(parent_object_id) AS [Parent Object Name], OBJECT_NAME(referenced_object_id) AS [Referenced Object Name]FROM Music.sys.foreign_keysWHERE name ='FK_Artists;Výsledek:
Kontext databáze byl změněn na 'WideWorldImportersDW'.+--------------------+----------------- -----+-----------------------------+| Cizí klíč | Název nadřazeného objektu | Název odkazovaného objektu ||--------------------+----------------------+- ----------------------------|| FK_Artists_Country | CityKey | PK_Dimension_Payment_Metod |+--------------------+----------------------+--- --------------------------+ (dotčen 1 řádek)Vše, co jsem udělal, bylo přepnout na jinou databázi a poté znovu spustit stejný dotaz.
Všimnete si, že můj
FROM
klauzule používá k určení názvu databáze třídílný název (Music
). To umožňuje nalezení správného cizího klíče. To však nestačí k tomu, aby se předešlo problémům.Jak se ukázalo,
WideWorldImportersDW
databáze má objekty se stejnýmobject_id
které se používají vMusic
databáze. Jediným problémem je, že jsou to úplně jiné objekty s různými jmény. Takže výsledky v posledních dvou sloupcích jsou falešné. Toto jsou jména nesprávných objektů ve špatné databázi. Můj dotaz napříč databázemi překřížil dráty a vrátil nesprávné objekty!To je obzvláště nebezpečné, protože kdybych nedával pozor, tyto výsledky by se mohly zdát v pořádku. Koneckonců, chyba se mi nezobrazila.
Pokud by tato ID objektů v této databázi neexistovala, pravděpodobně bych dostal hodnotu NULL (což by mohlo usnadnit zjištění, že s výsledky není něco v pořádku).
Ať tak či onak, výsledek je jednoduše špatný .
Příklad 3 – Dotaz mezi databázemi se SPRÁVNÝMI výsledky
Abychom opravili předchozí příklad (beze změny aktuální databáze), musíme zadat ID databáze, ze které chceme název objektu.
Takhle:
USE WideWorldImportersDW;SELECT name AS [cizí klíč], OBJECT_NAME(parent_object_id, 5) AS [Parent Object Name], OBJECT_NAME(referenced_object_id, 5) AS [Referenced Object Name]FROM Music.sys.foreign_keysWHERE name ='FKArtists;Výsledek:
Kontext databáze byl změněn na 'WideWorldImportersDW'.+--------------------+----------------- -----+--------------------------+| Cizí klíč | Název nadřazeného objektu | Název odkazovaného objektu ||--------------------+----------------------+- -------------------------|| FK_Artists_Country | Umělci | Země |+--------------------+----------------------+--- -----------------------+ (dotčen 1 řádek)Opět pro upřesnění, aktuální databáze je
WideWorldImportersDW
, ale objekty jsou v jiné databázi s názvemMusic
, který má databázi ID 5.Příklad 4 – Jak získat ID databáze
Je docela pravděpodobné, že nebudete vědět, jaké ID databáze máte z hlavy. Pravděpodobně budete znát název databáze, ale ne její ID.
Naštěstí můžete použít
DB_ID()
funkce, která vrátí ID databáze na základě jejího názvu.Proto můžeme předchozí příklad upravit následovně:
USE WideWorldImportersDW;VYBERTE název JAKO [cizí klíč], OBJECT_NAME(id rodičovského_objektu, DB_ID('Hudba')) AS [Název nadřazeného objektu], OBJECT_NAME(id_objektu odkazu, DB_ID('Hudba')) JAKO [Název odkazovaného objektu]FROM Music.sys.foreign_keysWHERE name ='FK_Artists_Country';Výsledek:
Kontext databáze byl změněn na 'WideWorldImportersDW'.+--------------------+----------------- -----+--------------------------+| Cizí klíč | Název nadřazeného objektu | Název odkazovaného objektu ||--------------------+----------------------+- -------------------------|| FK_Artists_Country | Umělci | Země |+--------------------+----------------------+--- -----------------------+ (dotčen 1 řádek)