アーカイブ

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

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

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 -
アーカイブ