OBJECT_NAME()
を使用する必要がある場合 SQL Serverの別のデータベースからオブジェクトの名前を取得する機能を使用している場合、その機能がわからないと問題が発生する可能性があります。
あなたはおそらくOBJECT_NAME()
object_id
を受け入れます 名前を取得するオブジェクトをSQLServerに指示する引数。
ご存知かもしれませんが、この関数はオプションのdatabase_id
も受け入れるということです。 object_id
をSQLServerに通知する引数 に属します。
デフォルトでは、SQLServerはobject_id
を想定しています 現在のデータベースのコンテキストにあります。この場合、object_id
を参照するクエリ 別のデータベースでは、NULLまたは(さらに悪いことに)誤った結果が返されます。
例1-(現在のデータベースからの)ローカルクエリ
まず、現在のデータベースからオブジェクト名を返すローカルクエリを次に示します。
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';>
結果:
Changed database context to 'Music'. +--------------------+----------------------+--------------------------+ | Foreign Key | Parent Object Name | Referenced Object Name | |--------------------+----------------------+--------------------------| | FK_Artists_Country | Artists | Country | +--------------------+----------------------+--------------------------+ (1 row affected)
これらの結果は正しいです。
これはクロスデータベースクエリではありません。これは、現在のデータベースからオブジェクトの名前を取得するときにこの関数がどのように使用されるかを示すための単なる例です。
例2–間違った結果を伴うクロスデータベースクエリ!
さて、これが間違った結果を生成するクロスデータベースクエリです。
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';>
結果:
Changed database context to 'WideWorldImportersDW'. +--------------------+----------------------+-----------------------------+ | Foreign Key | Parent Object Name | Referenced Object Name | |--------------------+----------------------+-----------------------------| | FK_Artists_Country | CityKey | PK_Dimension_Payment_Method | +--------------------+----------------------+-----------------------------+ (1 row affected)
別のデータベースに切り替えてから、同じクエリを再度実行するだけでした。
私のFROM
句は、データベースの名前を指定するために3つの部分からなる名前を使用します(Music
)。これにより、正しい外部キーを見つけることができます。ただし、これだけでは問題の発生を防ぐことはできません。
結局のところ、WideWorldImportersDW
データベースに同じobject_id
のオブジェクトがあります Music
で使用されている データベース。唯一の問題は、それらが完全に異なるオブジェクトであり、名前が異なることです。したがって、最後の2列の結果は偽物です。これらは、間違ったデータベース上の間違ったオブジェクトの名前です。私のクロスデータベースクエリは、ワイヤを交差させて間違ったオブジェクトを返しました!
これは特に危険です。注意を払っていない場合、これらの結果は問題ないように見える可能性があるためです。結局のところ、エラーは発生しませんでした。
これらのオブジェクトIDがこのデータベースに存在しなかった場合は、おそらくNULL値を取得している可能性があります(これにより、結果に問題があることを簡単に検出できる可能性があります)。
いずれにせよ、結果は単に間違っている 。
例3–正しい結果を使用したクロスデータベースクエリ
前の例を(現在のデータベースを変更せずに)修正するには、オブジェクトの名前を取得するデータベースのIDを指定する必要があります。
このように:
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';
結果:
Changed database context to 'WideWorldImportersDW'. +--------------------+----------------------+--------------------------+ | Foreign Key | Parent Object Name | Referenced Object Name | |--------------------+----------------------+--------------------------| | FK_Artists_Country | Artists | Country | +--------------------+----------------------+--------------------------+ (1 row affected)
繰り返しになりますが、明確にするために、現在のデータベースはWideWorldImportersDW
です。 、ただし、オブジェクトはMusic
と呼ばれる別のデータベースにあります 、データベースIDは5です。
例4–データベースIDを取得する方法
データベースのIDが頭から離れていることがわからない可能性が非常に高くなります。データベースの名前はわかっているかもしれませんが、IDはわかりません。
幸い、DB_ID()
を使用できます 名前に基づいてデータベースのIDを返す関数。
したがって、前の例を次のように変更できます。
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';
結果:
Changed database context to 'WideWorldImportersDW'. +--------------------+----------------------+--------------------------+ | Foreign Key | Parent Object Name | Referenced Object Name | |--------------------+----------------------+--------------------------| | FK_Artists_Country | Artists | Country | +--------------------+----------------------+--------------------------+ (1 row affected)