アーカイブ

【SQL Server】コンピュータ名を変更しているとクエリがエラーになる場合がある【リンクサーバー】

SQL Serverに関する小ネタ。ホストするコンピュータ名を変更する場合とリンクサーバーにまつわる話。

目次
  1. SQL Server ではコンピューター名変更時、手動で変更作業が必要
  2. エラーが発生するケース
  3. 理由
  4. 変更方法
    1. 既定のインスタンスの場合
    2. 名前付きインスタンスの場合
    3. 実行例
  5. 参考
  6. おわりに

SQL Server ではコンピューター名変更時、手動で変更作業が必要

あまりないケースかもしれませんが、SQL Serverがインストールされたコンピューターのコンピューター名を変更する場合、みなさんなにか意識されていますでしょうか?

コンピューター名を変更したらいきなりDBにアクセスできなくなる、といったことはなく普通に使えるので、特に意識してない方も多いのではないかと思います。
リモート接続なども変更後のコンピューター名でバッチリできますしね。

しかし実は、SQL Serverのメタデータ内にはコンピューター名の情報を持っていて、OSでコンピュータ名を変更した際に自動では変更されません。手動での変更作業が必要になります。

変更をしていないと、一部処理が正常に動作しなくなってしまい思わぬエラーが出ることも。

エラーが発生するケース

コンピュータ名の変更作業が漏れていることによって、エラーが発生するケースをご紹介。

例えば、以下のようなクエリの発行がエラーとなります。

SELECT * FROM [AFTERNAME\TEST].[testDB].[dbo].[table_a]

前提は以下

  • SQL Server インストール時のコンピューター名が「PREVNAME」
  • OSでコンピューター名を「AFTERNAME」に変更
  • インスタンス「TEST」のデータベース「testDB」内「table_a」テーブルのレコードを全行取得

例のクエリでポイントとなるのが、SQL Serverの「リンクサーバー」という機能を意識してテーブル名の前に「サーバー名\インスタンス」を付加しているところです。

◯実行例

エラー内容

sys.servers でサーバー ‘AFTERNAME\TEST’ が見つかりませんでした。正しいサーバー名を指定したかどうかを確認してください。必要であればストアド プロシージャ sp_addlinkedserver を実行し、サーバーを sys.servers に追加してください。

理由

SQL Serverには「リンクサーバー」という機能があります。

ざっくりいうと、あるSQL Serverにアクセスしている際にリンクサーバーとして設定している他のDBサーバー(インスタンス)のデータに対してもアクセスが可能になる機能です。
※にわかなので、ご容赦を…。詳しくは以下をご参照ください。
リンク サーバー (データベース エンジン) – SQL Server

何がよいのかといいますと、例えば異なるDBサーバー(インスタンス)のテーブル同士を結合したクエリが発行できたりします。
※Aサーバーに接続時に、AサーバーのBテーブルとリンクサーバーに設定したCサーバーのDテーブルを結合してSELECT、みたいな。

そんなリンクサーバー機能ですが、クエリを発行する際に対象テーブルがどのサーバー(インスタンス)のテーブルかを識別するために、テーブル名の前に「サーバー名\インスタンス名」を付加するわけです。

↓異なるサーバー同士のテーブル結合のクエリは、こんな感じになります。

SELECT
 *
FROM
 [AServer\INSTANCE].[DatabaseA].[dbo].[TableA] A
LEFT OUTER JOIN
 [BServer\INSTANCE].[DatabaseB].[dbo].[TableB] B
 ON B.KeyColumn = A.BKey


「サーバー名\インスタンス」の部分ですが、どうやらSQL Serverに保持しているメタデータと照合しているようです。

メタデータは、以下のクエリで確認することができます

SELECT * FROM sys.servers


上記には、リンクサーバーを作成すると設定内容に応じた情報がレコードとして追加されます。

また、任意に作成したリンクサーバーとは別に既定で
ローカルサーバー(自分自身)の情報が存在します(server_id=0 のレコード)
※画像の例は、リンクサーバーを作成していないのでローカルサーバーのレコードのみです。

この情報にはコンピューター名の情報が含まれています。
(「name」列/「data_source」列)

そしてこちらの情報は、コンピュータ名変更時に自動では更新されません。

そのため、クエリを変更後のコンピュータ名で記述しているのに対して、このメタデータが古いと、サーバーが見つからないとのエラーになってしまうというわけですね。

反対に、クエリの記述が実際のOSのコンピューター名と一致していなくても、このメタデータの情報に合致していればクエリは成功しました。(意図的に両者が異なる場合って、あるのかな・・・?)

もちろん、クエリでテーブル名に [サーバー名\インスタンス名] を付加するのは、リンクサーバーへアクセスするときに必要なもので、自サーバー(インスタンス)へアクセスする際は必要ありません。
そのため、このような問題はあまり想定されないレアケースではあるのですが…

SQL Serverと連携するシステム開発で、遭遇することがあるカモ。

変更方法

以下のプロシージャを実行することで、SQLServer内コンピューター名の情報を変更することができます。

反映には、実行後インスタンスの再起動が必要になります。
※サービスを再起動すればOK

既定のインスタンスの場合

EXEC sp_dropserver '<old_name>';
GO
EXEC sp_addserver '<new_name>', local;
GO

名前付きインスタンスの場合

EXEC sp_dropserver '<old_name\instancename>';
GO
EXEC sp_addserver '<new_name\instancename>', local;
GO
プロシージャの実行に失敗する場合
他コンピュータから接続中だとエラーになり実行できない場合があるようです。

その場合はsp_dropremoteloginプロシージャでリモート接続を削除します。
※もちろん、使用者に確認したあとで…

実行例

実行前

○メタデータ

○クエリ

現在のコンピュータ名「AFETRNAME」でクエリを発行しても、メタデータに存在しないのでエラーとなります。

実行後

○メタデータ

コンピュータ名に関する列の値が書き換わっていますね。
※「name」列/「data_source」列

○クエリ

エラーなく実行結果が返るようになりました(サービス再起動後)。

参考

SQL Server のスタンドアロン インスタンスをホストするコンピューターの名前を変更する – SQL Server

sys.servers (Transact-SQL) – SQL Server

リンク サーバー (データベース エンジン) – SQL Server

おわりに

環境依存で起こる問題って、やーね。

(我ながらPrevに対してAfterて…なんだ;)

プロフィール
筆者:UMAイカ

IT企業に勤務しています。
当ブログは商品レビューや生活の知恵、プログラミング、PCTipsなどについてお役立ち情報を発信します。趣味などの雑記も少し。
【マイブーム】:ウイスキー/自炊
【最近のひとこと】:転職したい・・・

- SNS -
アーカイブ