Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

So erhalten Sie ein OBJECT_NAME() aus einer anderen Datenbank in SQL Server

Falls Sie jemals OBJECT_NAME() verwenden müssen Funktion, um den Namen eines Objekts aus einer anderen Datenbank in SQL Server abzurufen, könnten Probleme auftreten, wenn Sie nicht wissen, wie sie funktioniert.

Sie kennen wahrscheinlich das OBJECT_NAME() akzeptiert eine object_id Argument, das SQL Server mitteilt, von welchem ​​Objekt der Name abgerufen werden soll.

Was Sie vielleicht wissen oder nicht wissen, ist, dass diese Funktion auch eine optionale database_id akzeptiert Argument, das SQL Server mitteilt, welcher Datenbank die object_id entspricht gehört.

Standardmäßig geht SQL Server davon aus, dass object_id steht im Kontext der aktuellen Datenbank. In diesem Fall eine Abfrage, die auf eine object_id verweist in einer anderen Datenbank NULL oder (noch schlimmer) falsche Ergebnisse zurückgibt.

Beispiel 1 – Lokale Abfrage (aus aktueller Datenbank)

Hier ist zunächst eine lokale Abfrage, die den Objektnamen aus der aktuellen Datenbank zurückgibt:

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

Ergebnis:

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

Diese Ergebnisse sind korrekt.

Dies ist keine datenbankübergreifende Abfrage. Dies ist nur ein Beispiel, um zu zeigen, wie diese Funktion verwendet wird, wenn der Name eines Objekts aus der aktuellen Datenbank abgerufen wird.

Beispiel 2 – Datenbankübergreifende Abfrage mit FALSCHEN ERGEBNISSEN!

Nun, hier ist eine datenbankübergreifende Abfrage, die falsche Ergebnisse liefert.

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

Ergebnis:

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

Ich habe lediglich zu einer anderen Datenbank gewechselt und dann dieselbe Abfrage erneut ausgeführt.

Sie werden feststellen, dass mein FROM -Klausel verwendet einen dreiteiligen Namen, um den Namen der Datenbank anzugeben (Music ). Dadurch kann der richtige Fremdschlüssel gefunden werden. Dies reicht jedoch nicht aus, um Probleme zu vermeiden.

Wie sich herausstellt, ist die Datei WideWorldImportersDW Datenbank hat Objekte mit derselben object_id die in der Music verwendet werden Datenbank. Das einzige Problem ist, dass es sich um völlig unterschiedliche Objekte mit unterschiedlichen Namen handelt. Die Ergebnisse in den letzten beiden Spalten sind also falsch. Dies sind die Namen der falschen Objekte in der falschen Datenbank. Bei meiner datenbankübergreifenden Abfrage haben sich die Drähte gekreuzt und die falschen Objekte zurückgegeben!

Das ist besonders gefährlich, denn wenn ich nicht aufgepasst hätte, könnten diese Ergebnisse in Ordnung erscheinen. Immerhin habe ich keine Fehlermeldung erhalten.

Wenn diese Objekt-IDs in dieser Datenbank nicht vorhanden wären, hätte ich wahrscheinlich einen NULL-Wert erhalten (was es möglicherweise einfacher macht, zu erkennen, dass etwas mit den Ergebnissen nicht stimmt).

So oder so ist das Ergebnis einfach falsch .

Beispiel 3 – Datenbankübergreifende Abfrage mit RICHTIGEN Ergebnissen

Um das vorherige Beispiel zu reparieren (ohne die aktuelle Datenbank zu ändern), müssen wir die ID der Datenbank angeben, aus der wir den Namen des Objekts haben möchten.

So:

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

Ergebnis:

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

Um es noch einmal klarzustellen:Die aktuelle Datenbank ist WideWorldImportersDW , aber die Objekte befinden sich in einer anderen Datenbank namens Music , die eine Datenbank-ID von 5 hat.

Beispiel 4 – So erhalten Sie die Datenbank-ID

Es ist sehr wahrscheinlich, dass Sie die ID der Datenbank nicht auf Anhieb wissen. Wahrscheinlich kennen Sie den Namen der Datenbank, aber nicht ihre ID.

Glücklicherweise können Sie die DB_ID() verwenden Funktion, um die ID der Datenbank basierend auf ihrem Namen zurückzugeben.

Daher können wir das vorherige Beispiel wie folgt ändern:

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

Ergebnis:

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