AzureのWindows VMにSQL Server 2025 Developerを入れて、T-SQLからLLMを呼ぶ
Azure VM上のWindows ServerにSQL Server 2025 Developerをインストールし、sp_invoke_external_rest_endpointでAzure OpenAIのChat Completions APIを呼び出す。
SQL Serverのライセンス費用は無料。ただし、この記事のVM構成はAzure無料VM枠の対象外で、VM・ディスク・ネットワーク・LLMにはそれぞれ課金条件がある。
本稿は公式ドキュメントを基にした手順。記載したAzure環境での一連の実機検証は未実施。画面名、利用可能なVMサイズ、料金は契約とリージョンによって異なる。
1. 構成と無料枠の注意点
| 項目 | 使用するもの |
|---|---|
| OS | Windows Server 2025 Datacenter、x64、GUIあり |
| VMサイズ | Standard_B2as_v2:2 vCPU、8 GiB |
| データベース | SQL Server 2025 Enterprise Developer |
| クライアント | 手元のWindows PCにSSMS |
| LLM | Azure OpenAIにデプロイしたChat Completions対応モデル |
| 認証 | APIキーをDATABASE SCOPED CREDENTIALに格納 |
Developerは開発・テスト用。本番利用には使えない。Enterprise DeveloperとStandard Developerがあるが、この記事ではEnterprise Developerを選ぶ。
「無料VMにDeveloperを入れる」場合の問題
Azureの無料サービスには月750時間・12か月の対象VMがある。ただし、案内されているB1s、B2ats_v2、B2ts_v2はメモリ1 GiB、B2pts_v2はArmベース。無料対象サイズの表記は公式ページ間でも異なるため、自分のサブスクリプションの「無料サービス」で確認する。
Windows版SQL Serverの推奨メモリは4 GB以上。1 GiBのVMにWindowsとSQL Serverを同居させる構成は、勉強会のデモ用として避けたい。
この記事では8 GiBのB2as_v2を使う。B2ats_v2とB2as_v2は別サイズで、B2as_v2は無料対象ではない。 作成前にAzure料金計算ツールと作成画面で金額を確認する。BシリーズはCPUクレジット方式なので、長時間の高負荷処理には向かない。
参考:
2. Windows VMを作成する
- Azure Portalで「仮想マシン」→「作成」を選ぶ。
- 実習専用のリソースグループを作る。例:
rg-sql2025-demo。 - VM名を指定する。例:
vm-sql2025-demo。 - リージョンは利用可能なサイズと料金を確認して選ぶ。
- イメージにWindows Server 2025 Datacenterのx64・GUIありのイメージを選ぶ。Server Coreは本稿の対象外。
- サイズに
Standard_B2as_v2を選ぶ。表示されない場合は別リージョンか、同等の8 GiB以上のサイズを検討する。 - Windows管理者のユーザー名とパスワードを設定する。
- OSディスクは実習向けにStandard SSDを選び、容量と価格を確認する。追加データディスクは小さなデモでは省略する。
- 作成後、NSGのRDP受信規則(TCP 3389)の接続元を**手元のPCのグローバルIPアドレス
/32**に限定する。Anyで公開したままにしない。 - 不要なBastion、バックアップなどを追加していないか確認する。
- 「管理」で自動シャットダウンを設定する。
- 作成前の見積もりを確認してVMを作成する。
専用リソースグループにすると、実習後にまとめて削除しやすい。Public IPなども無料とは限らないので、VM料金だけで判断しない。
3. RDP接続とSQL Serverのインストール
Azure PortalのVM画面から「接続」→「RDP」で接続する。Windows Updateを適用し、必要に応じて再起動する。
インストール媒体
SQL ServerのダウンロードページからSQL Server 2025 Developerのインストーラーを取得する。
インストーラーで「カスタム」を選び、セットアップを開く。「SQL Serverの新規スタンドアロンインストール、または既存のインストールへの機能の追加」を選ぶ。
| セットアップ項目 | 設定 |
|---|---|
| エディション | Enterprise Developer |
| 機能 | データベースエンジンサービス |
| インスタンス | 既定のインスタンス(MSSQLSERVER) |
| サービス | セットアップの既定値を基本とする |
| 認証 | 混合モード |
| SQL Server管理者 | 「現在のユーザーの追加」 |
| sa | 強いパスワードを指定。通常のデモ接続には使わない |
Analysis Servicesなど、今回使わない機能は追加しない。Azure拡張機能/Azure Arcの登録は今回のAPIキーによるREST呼び出しの前提ではない。
参考:インストールウィザードによるSQL Serverのインストール
4. 手元のSSMSから接続する
SSMSのインストール手順に従い、SSMSを手元のPCにインストールする。
SQL Server側のTCP設定
VM内の「SQL Server構成マネージャー」を開く。
- 「SQL Serverネットワークの構成」→「MSSQLSERVERのプロトコル」を開く。
- 「TCP/IP」を有効にする。
- TCP/IPのプロパティの「IPアドレス」タブで、使用するIPの設定を確認する。
Listen All = YesならIPAllの設定を使う。 -
IPAllの「TCP動的ポート」を空にし、「TCPポート」を1433にする。 - SQL Serverサービスを再起動する。
Windows FirewallにTCP 1433の受信規則を追加する。管理者PowerShellで以下を実行する。IPアドレスは実際の接続元に置き換える。
New-NetFirewallRule `
-DisplayName "SQL Server demo from my PC" `
-Direction Inbound -Action Allow -Protocol TCP `
-LocalPort 1433 -RemoteAddress "YOUR_CLIENT_PUBLIC_IP"
Azure側のNSGにも、接続元を同じIP /32、接続先ポートをTCP 1433とする受信許可規則を追加する。既定インスタンスと固定ポートを使うため、SQL Server Browser用UDP 1434は開けない。
ホテルなどでネットワークを変えると接続元IPも変わる。RDPとSQLの両方の規則を更新する。
管理用ログインを作る
VM内で一時的にSSMSを使うなどして、Windows認証でローカルのSQL Serverへ接続する。TCP接続確認用の管理ログインを作る場合は以下を実行する。
USE master;
GO
CREATE LOGIN [demo_admin]
WITH PASSWORD = 'REPLACE_WITH_STRONG_ADMIN_PASSWORD',
CHECK_POLICY = ON;
GO
ALTER SERVER ROLE [sysadmin] ADD MEMBER [demo_admin];
GO
demo_adminは環境設定用。LLM呼び出しの実習には後で作る権限を絞ったログインを使う。
手元のSSMSで次を指定する。
| 項目 | 値 |
|---|---|
| サーバー名 | tcp:VMのPublic IP,1433 |
| 認証 | SQL Server認証 |
| ユーザー | demo_admin |
| 暗号化 | Mandatory |
| サーバー証明書を信頼する | 自己署名証明書を使う閉じた実習環境では有効 |
「サーバー証明書を信頼する」は証明書検証を省略する。本番では適切な証明書とDNS名を設定して無効にする。
SELECT @@VERSION AS Version;
SELECT SERVERPROPERTY('Edition') AS Edition;
バージョンが17.x、エディションがDeveloperであることを確認する。
5. REST呼び出しを有効にする
SQL Server 2025では外部REST呼び出しが既定で無効。管理者接続で有効にする。
EXEC sys.sp_configure N'external rest endpoint enabled', 1;
RECONFIGURE WITH OVERRIDE;
GO
SELECT name, value_in_use
FROM sys.configurations
WHERE name = N'external rest endpoint enabled';
value_in_use = 1を確認する。
Azure SQL Databaseでは既定で有効。この
sp_configure手順は不要。
6. Azure OpenAIを用意する
Azure OpenAIリソースと、Chat Completionsに対応するモデルのデプロイを用意し、次の値を控える。
| 値 | 例 |
|---|---|
| リソースのエンドポイント | https://YOUR-RESOURCE.openai.azure.com |
| APIキー | リソースのキー |
| デプロイ名 | YOUR_DEPLOYMENT |
この記事ではv1 APIを使う。URLは/openai/v1/chat/completions、本文のmodelにはデプロイ名を指定する。日付形式のapi-versionは付けない。
Azure OpenAIのネットワーク制限を有効にしている場合は、VMからのアクセスを許可する。手元のPCのIPとVMの送信元IPは別。Private Endpointを使う場合はVNet接続とDNSを別途構成する。
VMから外部HTTPSへの送信も必要。ネットワークで明示的な送信経路が必要な場合はPublic IPやNAT Gatewayなどを構成し、追加料金を確認する。
参考:Azure OpenAI APIのバージョンライフサイクル
7. データベースとCredentialを作る
管理者接続で以下を実行する。
USE master;
GO
CREATE DATABASE [LLMDemo];
GO
USE [LLMDemo];
GO
CREATE MASTER KEY
ENCRYPTION BY PASSWORD = 'REPLACE_WITH_STRONG_MASTER_KEY_PASSWORD';
GO
CREATE DATABASE SCOPED CREDENTIAL
[https://YOUR-RESOURCE.openai.azure.com]
WITH IDENTITY = 'HTTPEndpointHeaders',
SECRET = '{"api-key":"REPLACE_WITH_AZURE_OPENAI_API_KEY"}';
GO
マスターキーのパスワードとAPIキーは別の値。置換済みのSQLをQiitaやGitに載せない。APIキーにシングルクォートが含まれる場合はT-SQL文字列内で''にエスケープする。
Credentialの名前は任意の別名ではない
HTTPEndpointHeadersを使うCredentialの名前は、呼び出し先と対応するURLにする。
- HTTPSスキームとホスト名を呼び出し先に合わせる。
- パスを含める場合は呼び出し先と同じパス、またはその親パスにする。
- クエリ文字列を含めない。
この例ではホストまでを名前にしているため、/openai/v1/chat/completionsの呼び出しに使える。[AzureOpenAIKey]のような任意の名前にはしない。
キーを更新するときは次を実行する。
USE [LLMDemo];
GO
ALTER DATABASE SCOPED CREDENTIAL
[https://YOUR-RESOURCE.openai.azure.com]
WITH IDENTITY = 'HTTPEndpointHeaders',
SECRET = '{"api-key":"REPLACE_WITH_NEW_API_KEY"}';
8. 実習用ログインに権限を付ける
USE master;
GO
CREATE LOGIN [llm_demo]
WITH PASSWORD = 'REPLACE_WITH_STRONG_DEMO_PASSWORD',
CHECK_POLICY = ON,
DEFAULT_DATABASE = [LLMDemo];
GO
USE [LLMDemo];
GO
CREATE USER [llm_demo] FOR LOGIN [llm_demo];
GO
GRANT EXECUTE ANY EXTERNAL ENDPOINT TO [llm_demo];
GRANT REFERENCES ON DATABASE SCOPED CREDENTIAL::
[https://YOUR-RESOURCE.openai.azure.com] TO [llm_demo];
GO
SSMSの接続をllm_demoに切り替え、接続先データベースをLLMDemoにする。管理用ログインのままでは、実習ユーザーの権限不足を確認できない。
9. T-SQLからLLMを呼ぶ
YOUR-RESOURCEとYOUR_DEPLOYMENTを実際の値に置き換える。Credential名も手順7と同じ値にする。
USE [LLMDemo];
GO
DECLARE @url nvarchar(4000) =
N'https://YOUR-RESOURCE.openai.azure.com/openai/v1/chat/completions';
DECLARE @response nvarchar(max);
DECLARE @rc int;
DECLARE @payload nvarchar(max) = N'{
"model": "YOUR_DEPLOYMENT",
"messages": [
{"role": "user", "content": "SQL Serverを一文で説明して"}
],
"stream": false
}';
EXEC @rc = sys.sp_invoke_external_rest_endpoint
@url = @url,
@method = N'POST',
@credential = N'https://YOUR-RESOURCE.openai.azure.com',
@payload = @payload,
@timeout = 60,
@retry_count = 0,
@response = @response OUTPUT;
SELECT @rc AS ReturnCode, @response AS RawResponse;
IF @rc <> 0
THROW 50001, N'HTTP error. Inspect RawResponse.', 1;
SELECT
JSON_VALUE(@response, '$.response.status.http.code') AS HttpCode,
JSON_VALUE(@response, '$.result.choices[0].finish_reason') AS FinishReason;
SELECT Answer
FROM OPENJSON(@response, '$.result.choices[0].message')
WITH (Answer nvarchar(max) '$.content');
確認する値はReturnCode = 0、HttpCode = 200、回答本文。FinishReasonも確認し、途中終了やフィルターによる終了を成功した回答として扱わない。
通常のJSON_VALUEの戻り値はnvarchar(4000)なので、長い回答の抽出にはOPENJSONとnvarchar(max)を使う。
@timeoutは最大230秒。リトライを指定すると、リトライ全体の累積タイムアウトになる。デモでは問題を追いやすいようリトライを0にする。
10. Azure SQL Databaseとの違い
| 項目 | 今回のSQL Server 2025 on VM | Azure SQL Database |
|---|---|---|
| SQLのインストール | 自分で行う | 不要 |
| REST呼び出し | 有効化が必要 | 既定で有効 |
| 接続先の許可リスト | Azure SQLの許可リストは適用されない | 公式の許可リストが適用される |
| ネットワーク管理 | VM、NSG、Windows Firewall、送信経路 | SQLサービス側の設定 |
| DB切り替え | USEで切り替え可能 | 対象DBに直接接続 |
| OS更新とSQL更新 | 自分で管理 | サービス側で管理 |
sp_invoke_external_rest_endpointの「Allowed endpoints」一覧はAzure SQL DatabaseとAzure SQL Managed Instance向け。LLMだけの制限ではない。SQL Server 2025 on VMはFoundry限定ではなく、ネットワーク・認証・API仕様が対応するHTTPS REST APIを呼び出せる。
参考:sp_invoke_external_rest_endpointの仕様
11. 接続できないとき
| 症状 | 確認箇所 |
|---|---|
| RDP接続不可 | VM起動状態、NSGの3389、接続元IP |
| SSMS接続不可 | NSGの1433、Windows Firewall、TCP/IP有効化、SQL再起動 |
| ログイン失敗 | 混合モード、パスワード、既定DB、ユーザー対応 |
| 証明書エラー | 証明書とサーバー名、実習時の証明書信頼設定 |
| REST機能が無効 | external rest endpoint enabledのvalue_in_use |
| 権限不足 | EXECUTE ANY EXTERNAL ENDPOINTとCredentialのREFERENCES |
| Credential関連エラー | URL形式の名前、ホスト・パスの一致、対象DB |
| HTTP 401 | APIキー、対象リソース |
| HTTP 403 | Azure OpenAIのネットワーク制限、認可 |
| HTTP 404 | URL、デプロイ名、APIの対応 |
| HTTP 400 | モデルとChat Completionsの対応、本文のパラメーター |
| HTTP 429 | クォータ、レート制限 |
| タイムアウト | VMの送信経路、DNS、HTTPS接続、モデル応答時間 |
HTTPエラーでは最初にRawResponseを見る。接続自体ができない場合はSQL例外が発生し、HTTPステータスが返らないこともある。
12. 実習後に課金を抑える
次回も使う場合
Azure PortalのVM画面で「停止」を実行し、状態が**「停止済み(割り当て解除)」**になったことを確認する。
Windows内からシャットダウンしただけの「停止済み」状態は、VMのコンピューティング料金が続く場合がある。
割り当て解除後もOSディスク、追加ディスク、Public IPなどは課金対象として残り得る。データを残して完全に0円になるとは限らない。
もう使わない場合
必要なDBバックアップをVM外へ退避した後、実習専用リソースグループを削除する。削除前に対象一覧を確認する。Azure OpenAIなどを同じグループに置いた場合、それも削除される。