はじめに
自分の書いたSQLがベストプラクティスに沿っているかをチェックしたいときにどうしますか?
今回紹介する T-SQL Analyzer は、140以上のルールで SQL Serverの T-SQL のアンチパターンや設計上の問題を検出してくれる無料のコマンドラインツールです。さらに VS Code の MCP サーバー として設定すれば、GitHub Copilot が SQL ファイルを自動で分析してくれるようになります。
この記事では、環境構築から実際の使い方までを解説します。
T-SQL Analyzer とは
Microsoft と SQL Server コミュニティが作成したCLIツールです。 140以上のルール を元に、以下のような問題を検出します。
- パフォーマンスの問題
- 設計上の問題(命名規則違反など)
- アンチパターン
詳細は公式ブログを参照してください。
https://devblogs.microsoft.com/azure-sql/sql-analysis-dotnet-tool/
普通の LLM によるレビューとの違い
「Gemini や Claude に直接 SQL をレビューしてもらうのと何が違うの?」という疑問があると思います。
| 観点 | 普通の LLM レビュー | T-SQL Analyzer + Copilot |
|---|---|---|
| ルールの一貫性 | プロンプトや文脈で結果がブレる | 140以上の固定ルールで常に一貫した結果 |
| 検出の網羅性 | 見落としがある場合もある | 体系的にすべてのルールをチェック |
| 根拠の明確さ | 「一般的に〜」という曖昧な説明 | ルール ID(例:SRD0005)で明確に特定 |
| CI/CD 統合 | 難しい | コマンドラインツールなので容易 |
| オフライン実行 | 不可 | 可能 |
T-SQL Analyzer で体系的に問題を検出 → Copilot がわかりやすく説明・修正提案 という組み合わせが強力です。
環境構築
M1 Macを例に構築手順を記載します。
Step 1: .NET SDK のインストール
T-SQL Analyzer は .NET 8 ツールなので、まず SDK が必要です。
今回は .NET 10をインストールしました。
1.公式サイトから macOS Arm64 版をダウンロード
https://dotnet.microsoft.com/ja-jp/download/dotnet/8.0
2..pkg ファイルを実行してインストール
3.シンボリックリンクを作成
.pkg インストール後も dotnet コマンドが見つからない場合はシンボリックリンク作成で解決します。
sudo ln -s /usr/local/share/dotnet/dotnet /usr/local/bin/
4.動作確認
dotnet --version
# 8.0.xxx 以上であれば OK
Step 2: T-SQL Analyzer のインストール
dotnet tool install --global ErikEJ.DacFX.TSQLAnalyzer.Cli
動作確認
tsqlanalyze --help
以下のように表示されれば成功です:
_____ ____ ___ _ _ _
|_ _| / ___| / _ \ | | / \ _ __ __ _ | | _ _ ____ ___
| | _____ \___ \ | | | | | | / _ \ | '_ \ / _` | | | | | | | |_ / / _ \
| | |_____| ___) | | |_| | | |___ / ___ \ | | | | | (_| | | | | |_| | / / | __/
|_| |____/ \__\_\ |_____| /_/ \_\ |_| |_| \__,_| |_| \__, | /___| \___|
|___/
T-SQL Analyzer CLI 1.0.35
Step 3: VS Code MCP サーバーの設定
ブラウザで以下のリンクを開くと、VS Code が起動して MCP サーバーの設定を促されます:
vscode:mcp/install?%7B%22name%22%3A%22tsqlanalyzer%22%2C%22command%22%3A%22tsqlanalyze%22%2C%22args%22%3A%5B%22-mcp%22%5D%7D
または、手動で ~/Library/Application Support/Code/User/mcp.json を編集してください。
{
"servers": {
"tsqlanalyzer": {
"command": "tsqlanalyze",
"args": [
"-mcp"
],
"type": "stdio"
}
},
"inputs": []
}
設定後、VS Code を再起動してください。
使ってみる
サンプル:問題だらけの SQL
以下のような アンチパターンを踏みまくったSQL を用意しました。
SELECT * FROM Users, Orders
WHERE Users.id = Orders.user_id
AND YEAR(Orders.order_date) = 2024
AND Users.name LIKE '%hoge%'
AND Orders.amount > '5000'
OR Users.status = 1;
コマンドラインで分析
SQL ファイルがあるフォルダで実行
配下のSQLファイルを全て分析してれるはず....
tsqlanalyze
と思いきや、.sqlファイルがあるにも関わらず分析してくれません。
Analyzed 1 files in 3.969 seconds using 'Microsoft.Rules.Data, Smells, SqlServer.Rules'. 0 problems found.
確認したところ、T-SQL Analyzer はCREATE文のみが対象のようです。
適当なビューのCREATE文にします。
IF OBJECT_ID(N'dbo.vw_TestUsersOrders', N'V') IS NOT NULL
DROP VIEW dbo.vw_TestUsersOrders;
GO
CREATE VIEW dbo.vw_TestUsersOrders
AS
SELECT * FROM Users, Orders
WHERE Users.id = Orders.user_id
AND YEAR(Orders.order_date) = 2024
AND Users.name LIKE '%hoge%'
AND Orders.amount > '5000'
OR Users.status = 1;
GO
実際にはGitでSQLを管理する際は、CREATE TABLEやCREATE PROCEDUREなどで管理されることが多いと思うのであまり問題にならないと思います。
GitHub Copilot で分析
これをGithub Copilotと連携してみます。
- VS Code で SQL ファイルを開く
- GitHub Copilot Chat を Agent モード で開く
- 「この SQL ファイルを分析して」と依頼
Copilot が T-SQL Analyzer を呼び出し、以下のような分析結果を返してくれます:
このSQLファイルには以下の問題があります:
主な問題点
SELECT * の使用
- 必要な列のみを明示的に指定すべきです
- パフォーマンスとメンテナンス性の観点から推奨されません
暗黙的なJOIN構文
FROM Users, Orders WHERE...ではなく、明示的なINNER JOINを使用すべきです- 可読性が低く、条件の意図が不明確になります
関数を列に適用(SARGable違反)
YEAR(Orders.order_date) = 2024はインデックスを使用できませんOrders.order_date >= '2024-01-01' AND Orders.order_date < '2025-01-01'のように書き換えるべきです前方一致・中間一致のLIKE検索
Users.name LIKE '%hoge%'は両端にワイルドカードがあるため、インデックスを使用できません型の不一致
Orders.amount > '5000'で数値と文字列を比較しています- 暗黙的な型変換が発生し、パフォーマンスに影響します
AND/OR演算子の優先順位の問題
OR演算子が最後にあり、意図しない結果を返す可能性があります- 括弧で明示的にグループ化すべきです
以下のれすぽんすから、MCPサーバーを利用していることがわかります。
また、生のSQLを渡した場合でも、CREATE PROCEDURE文にラップしてレビューしてレビューしてくれました。気が利きますね。


Copilotがクエリも修正してくれました。
修正後の SQL
SELECT
u.id,
u.name,
u.status,
o.id AS order_id,
o.order_date,
o.amount
FROM dbo.Users AS u
JOIN dbo.Orders AS o
ON u.id = o.user_id
WHERE
o.order_date >= '2024-01-01'
AND o.order_date < '2025-01-01'
AND u.name LIKE '%hoge%' -- SRP0002的には前方%を避けるのが望ましい
AND o.amount > 5000 -- 文字列ではなく数値で比較
AND (
u.status = 1 -- ORの優先順位は括弧で明示
);
検出される問題の一覧
T-SQL Analyzer は 140以上のルールを持っています。主なカテゴリは以下の通りです。
| カテゴリ | 例 |
|---|---|
| パフォーマンス | Non-SARGable クエリ、SELECT *、暗黙的な型変換 |
| 設計 | 命名規則違反、主キーの欠如 |
| セキュリティ | SQL インジェクションのリスク |
| 可読性 | 古い JOIN 構文、括弧の不足 |
全ルール一覧
https://github.com/ErikEJ/SqlServer.Rules/blob/master/docs/readme.md
高度な使い方
特定ルールを無視
ルールIDを指定して、特定ルールを除外できるようです。
例えば以下のルールは致し方ない場合もあるので除外してみましょう。
LIKEの前方ワイルドカード: '%hoge%'は非SARGable(SRP0002)。
MCPサーバーとして動かす場合は、mcp.jsonを以下のように修正します
{
"servers": {
"tsqlanalyzer": {
"command": "tsqlanalyze",
"args": [
"-mcp",
"-r",
"Rules:-SqlServer.Rules.SRP0002;"
],
"type": "stdio"
}
},
"inputs": []
}
しかし、上記のように-rオプションを追加したところMCPサーバーが起動エラーになってしまいました。
また、CLIから除外ルールを指定して実行してもうまく除外されませんでした。(SR0005が指摘に含まれてしまう)
このあたりはこれからのアップデートに期待したいです。
% tsqlanalyze -i ./test.sql -r "Rules:-SqlServer.Rules.SRD0005"
_____ ____ ___ _ _ _
|_ _| / ___| / _ \ | | / \ _ __ __ _ | | _ _ ____ ___
| | _____ \___ \ | | | | | | / _ \ | '_ \ / _` | | | | | | | |_ / / _ \
| | |_____| ___) | | |_| | | |___ / ___ \ | | | | | (_| | | | | |_| | / / | __/
|_| |____/ \__\_\ |_____| /_/ \_\ |_| |_| \__,_| |_| \__, | /___| \___|
|___/
T-SQL Analyzer CLI 1.0.35
https://github.com/ErikEJ/SqlServer.Rules
warning: ./test.sql(9,17): Smells.SML002 : Best practice is to use two part naming. (https://github.com/ErikEJ/SqlServer.Rules/blob/master/docs/CodeSmells/SML002.md)
warning: ./test.sql(9,24): Smells.SML002 : Best practice is to use two part naming. (https://github.com/ErikEJ/SqlServer.Rules/blob/master/docs/CodeSmells/SML002.md)
warning: ./test.sql(9,10): Smells.SML005 : Avoid use of 'Select *'. (https://github.com/ErikEJ/SqlServer.Rules/blob/master/docs/CodeSmells/SML005.md)
warning: ./test.sql(9,10): Microsoft.Rules.Data.SR0001 : SELECT * ステートメントによって生成される結果セットの形状は、基になるテーブルやビューの構造が変更されると変わります。
(https://learn.microsoft.com/sql/tools/sql-database-projects/concepts/sql-code-analysis/t-sql-design-issues#sr0001-avoid-select--in-stored-procedures-views-and-table-valued-functions)
warning: ./test.sql(12,25): Microsoft.Rules.Data.SR0005 : LIKE 述語では "%" で始まるパターンの使用は避けてください
(https://learn.microsoft.com/sql/tools/sql-database-projects/concepts/sql-code-analysis/t-sql-performance-issues#sr0005-avoid-using-patterns-that-start-with--in-like-predicates)
warning: ./test.sql(9,24): Microsoft.Rules.Data.SR0010 : 旧スタイルの JOIN 構文が使用されています。
(https://learn.microsoft.com/sql/tools/sql-database-projects/concepts/sql-code-analysis/t-sql-design-issues#sr0010-avoid-using-deprecated-syntax-when-you-join-tables-or-views)
warning: ./test.sql(9,10): SqlServer.Rules.SRD0006 : Avoid using SELECT *. (https://github.com/ErikEJ/SqlServer.Rules/blob/master/docs/Design/SRD0006.md)
warning: ./test.sql(9,17): SqlServer.Rules.SRD0038 : Consider aliasing all table sources in the query. (https://github.com/ErikEJ/SqlServer.Rules/blob/master/docs/Design/SRD0038.md)
warning: ./test.sql(9,24): SqlServer.Rules.SRD0038 : Consider aliasing all table sources in the query. (https://github.com/ErikEJ/SqlServer.Rules/blob/master/docs/Design/SRD0038.md)
warning: ./test.sql(9,17): SqlServer.Rules.SRD0039 : Use fully qualified object names in SELECT, UPDATE, DELETE, MERGE and EXECUTE statements. [schema].[name].
(https://github.com/ErikEJ/SqlServer.Rules/blob/master/docs/Design/SRD0039.md)
warning: ./test.sql(9,24): SqlServer.Rules.SRD0039 : Use fully qualified object names in SELECT, UPDATE, DELETE, MERGE and EXECUTE statements. [schema].[name].
(https://github.com/ErikEJ/SqlServer.Rules/blob/master/docs/Design/SRD0039.md)
warning: ./test.sql(4,1): SqlServer.Rules.SRD0068 : Query statements should finish with a semicolon - ';'. (https://github.com/ErikEJ/SqlServer.Rules/blob/master/docs/Design/SRD0068.md)
warning: ./test.sql(12,9): SqlServer.Rules.SRP0002 : Try to avoid using patterns that start with '%' when using the LIKE keyword if possible. (Sargable)
(https://github.com/ErikEJ/SqlServer.Rules/blob/master/docs/Performance/SRP0002.md)
warning: ./test.sql(11,9): SqlServer.Rules.SRP0009 : Avoid wrapping columns within a function in the WHERE clause. (Sargable) (https://github.com/ErikEJ/SqlServer.Rules/blob/master/docs/Performance/SRP0009.md)
Analyzed 1 files in 1.396 seconds using 'Microsoft.Rules.Data, Smells, SqlServer.Rules'. 14 problems found.
SQL のフォーマット
フォーマットにも使えそうです。
tsqlanalyze -i ./query.sql -f
before
SELECT * FROM Users, Orders
WHERE Users.id = Orders.user_id
AND YEAR(Orders.order_date) = 2024
AND Users.name LIKE '%hoge%'
AND Orders.amount > '5000'
OR Users.status = 1;
after
SELECT *
FROM Users, Orders
WHERE Users.id = Orders.user_id
AND YEAR(Orders.order_date) = 2024
AND Users.name LIKE '%hoge%'
AND Orders.amount > '5000'
OR Users.status = 1;
細かく設定できそうなので、決まった形式にフォーマットを統一したい場合に便利かもしれません。
https://github.com/madskristensen/SqlFormatter?tab=readme-ov-file#editorconfig-support
CI/CD への組み込み
コマンドラインツールなので、dotnetが動く環境であればどこでも動きます。
以下のようにGitHub Actions などに簡単に組み込めそうです。
- name: Analyze SQL
run: |
dotnet tool install --global ErikEJ.DacFX.TSQLAnalyzer.Cli
tsqlanalyze -i ./sql/ --output xml > analysis-result.xml
まとめ
T-SQL Analyzer + VS Code MCP サーバーの組み合わせにより以下が実現できそうです。
- 一貫したルール で SQL をチェック
- GitHub Copilot がわかりやすく説明・修正提案
- CI/CD に組み込んで自動チェック
SQL Server を使っている方は、ぜひ導入してみてください。
