Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Come ottenere un OBJECT_NAME() da un database diverso in SQL Server

Se hai bisogno di usare OBJECT_NAME() funzione per ottenere il nome di un oggetto da un database diverso in SQL Server, potresti riscontrare problemi se non sai come funziona.

Probabilmente conosci quel OBJECT_NAME() accetta un object_id argomento che indica a SQL Server da quale oggetto ottenere il nome.

Quello che potresti sapere o meno è che questa funzione accetta anche un database_id opzionale argomento che indica a SQL Server quale database è object_id appartiene a.

Per impostazione predefinita, SQL Server presuppone che object_id è nel contesto del database corrente. In questo caso, una query che fa riferimento a un object_id in un altro database restituirà NULL o (ancora peggio) risultati errati.

Esempio 1 – Query locale (dal database corrente)

Innanzitutto, ecco una query locale che restituisce il nome dell'oggetto dal database corrente:

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

Risultato:

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

Questi risultati sono corretti.

Questa non è una query tra database. Questo è solo un esempio per mostrare come questa funzione viene utilizzata quando si ottiene il nome di un oggetto dal database corrente.

Esempio 2 – Query su più database con RISULTATI ERRATI!

Ora, ecco una query su più database che produce risultati errati.

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

Risultato:

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

Tutto quello che ho fatto è stato passare a un database diverso, quindi eseguire di nuovo la stessa query.

Noterai che il mio FROM La clausola utilizza un nome in tre parti per specificare il nome del database (Music ). Ciò consente di trovare la chiave esterna corretta. Tuttavia, questo non è sufficiente per evitare che si verifichino problemi.

A quanto pare, il WideWorldImportersDW il database ha oggetti con lo stesso object_id che vengono utilizzati in Music Banca dati. L'unico problema è che sono oggetti completamente diversi, con nomi diversi. Quindi i risultati nelle ultime due colonne sono falsi. Questi sono i nomi degli oggetti sbagliati, sul database sbagliato. La mia query tra database ha incrociato i fili e ha restituito gli oggetti sbagliati!

Questo è particolarmente pericoloso, perché se non stavo prestando attenzione, questi risultati potrebbero sembrare OK. Dopotutto, non ho ricevuto alcun errore.

Se questi ID oggetto non esistessero in questo database, probabilmente avrei ottenuto un valore NULL (che potrebbe rendere più semplice rilevare che qualcosa non va nei risultati).

In ogni caso, il risultato è semplicemente sbagliato .

Esempio 3 – Query su più database con risultati CORRETTI

Per correggere l'esempio precedente (senza modificare il database corrente), dobbiamo fornire l'ID del database da cui vogliamo il nome dell'oggetto.

In questo modo:

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

Risultato:

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

Ancora una volta, tanto per essere chiari, il database corrente è WideWorldImportersDW , ma gli oggetti si trovano su un database diverso chiamato Music , che ha un ID database di 5.

Esempio 4 – Come ottenere l'ID database

È molto probabile che tu non sappia quale sia l'ID del database in cima alla tua testa. Probabilmente conoscerai il nome del database, ma non il suo ID.

Fortunatamente puoi usare il DB_ID() funzione per restituire l'ID del database, in base al suo nome.

Pertanto, possiamo modificare l'esempio precedente come segue:

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

Risultato:

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