はじめに:読みづらいSQLに苦労していませんか?
開発やデータ分析の現場で、こんな経験はありませんか?
SELECT u.id,u.name,u.email,o.order_id,o.total FROM users u INNER JOIN orders o ON u.id=o.user_id WHERE u.status='active' AND o.created_at>='2026-01-01' ORDER BY o.created_at DESC;改行もインデントもない1行のSQLクエリ。ログから抽出したSQL、他人が書いた圧縮されたクエリ、古いシステムから取り出したクエリ…。
こういったSQLを読み解く時、手作業で整形するのは本当に面倒です:
- 手動でキーワードごとに改行
- インデントを調整
- カンマの位置を揃える
- 大文字・小文字を統一
エディタで1つずつ編集するのは時間の無駄です。
もし、VSCodeで選択したSQLを1キー操作で整形し、新規ファイルに出力できたら便利だと思いませんか?
さらに、複数のSQL方言(MySQL、PostgreSQL、Oracle等)に対応し、キーワードの大文字/小文字やインデント幅を選択できたら?
今回、sql-formatterライブラリを活用したSQL整形ツールをVSCodeのTypeScriptマクロとして実装しました。
同じようにVSCodeで少しでも効率化したい開発者の方に、ぜひ参考にしていただきたい内容です。
この記事で分かること
- SQL整形ツールの機能と使い方
sql-formatterライブラリの活用方法- 対応するSQL方言(8種類)
- オプション選択(キーワードケース、インデント幅)
- TypeScript実装の詳細コード
- エラーハンドリングとユーザビリティ
- 実務での活用例
なぜSQL整形ツールが必要なのか?
開発現場でのSQL整形の課題
課題1:ログから抽出したSQLが読めない
SELECT*FROM users WHERE status='active'AND created_at>='2026-01-01'ORDER BY id DESC LIMIT 10;→ 本番環境のログから取り出したクエリは、改行もインデントもなく圧縮されている
課題2:SQL方言の違いに対応できない
- MySQL独自の構文(LIMIT、バッククォート)
- PostgreSQL独自の構文(::型キャスト、RETURNING)
- Oracle独自の構文(DUAL、ROWNUM、PL/SQL)
- SQL Server独自の構文(TOP、[]識別子)
→ 汎用的な整形ツールでは方言の違いを正しく扱えない
課題3:コーディング規約の統一
- プロジェクトA:キーワードは大文字(SELECT、FROM)
- プロジェクトB:キーワードは小文字(select、from)
- プロジェクトC:インデントは2スペース
- プロジェクトD:インデントは4スペース
→ 手作業での統一は非効率
既存のSQL整形ツールの問題点
オンライン整形ツール:
- ブラウザで別サイトを開く手間
- セキュリティの懸念(機密SQLを外部に送信)
- ネットワーク接続が必要
DBクライアントツール:
- 特定のDBにしか対応していない
- エディタ上で完結しない
- ツールの立ち上げに時間がかかる
VSCode拡張機能:
- 設定が複雑
- カスタマイズ性が低い
- 出力先が固定
このマクロで実現できること
| 項目 | オンラインツール | DBクライアント | このマクロ |
|---|---|---|---|
| 方言対応 | ⚠️ 限定的 | ⚠️ 特定DBのみ | ✅ 8種類対応 |
| セキュリティ | ❌ 外部送信 | ⚠️ ツール依存 | ✅ ローカル完結 |
| 操作性 | ❌ ブラウザ切替 | ❌ ツール切替 | ✅ 1キー操作 |
| カスタマイズ | ❌ 不可 | ⚠️ 限定的 | ✅ 柔軟に設定 |
| 出力先 | ❌ 手動コピペ | ⚠️ 同一ファイル | ✅ 新規ファイル |
実装した機能の概要
できること
選択されたSQLを整形して新規ファイルに出力
ステップ1:整形したいSQLを選択(または何も選択せずファイル全体)
ステップ2:コマンド実行
ステップ3:オプション選択ダイアログ
- SQL方言(MySQL、PostgreSQL、Oracle等)
- キーワードの大文字/小文字
- インデント幅(2スペース、4スペース、タブ)
ステップ4:整形されたSQLが右側に新規ファイルで表示
ステップ5:保存ダイアログでファイル名を指定して保存対応SQL方言(8種類)
1. Standard SQL(標準SQL)
-- デフォルト、最も汎用的
SELECT * FROM users WHERE id = 1;2. MySQL / MariaDB
-- バッククォート、LIMIT構文
SELECT `id`, `name` FROM `users` LIMIT 10;3. PostgreSQL
-- 型キャスト、RETURNING構文
SELECT id::INTEGER, name FROM users RETURNING *;4. T-SQL (Microsoft SQL Server)
-- TOP構文、[]識別子
SELECT TOP 10 [id], [name] FROM [users];5. PL/SQL (Oracle Database)
-- DUAL、ROWNUM、PL/SQLブロック
SELECT * FROM dual;
SELECT * FROM users WHERE ROWNUM <= 10;6. Amazon Redshift
-- Redshift固有の構文
SELECT * FROM users LIMIT 10;7. IBM DB2
-- DB2固有の構文
SELECT * FROM users FETCH FIRST 10 ROWS ONLY;8. MariaDB
-- MariaDB固有の構文(MySQLベース)
SELECT * FROM users LIMIT 10;オプション選択機能
1. SQL方言の選択
┌─────────────────────────────────────┐
│ SQL方言を選択してください │
├─────────────────────────────────────┤
│ ○ Standard SQL (標準SQL) │
│ ○ MySQL / MariaDB │
│ ○ PostgreSQL │
│ ○ T-SQL (SQL Server) │
│ ○ PL/SQL (Oracle) │
│ ○ Amazon Redshift │
│ ○ IBM DB2 │
└─────────────────────────────────────┘2. キーワードの大文字/小文字
┌─────────────────────────────────────┐
│ キーワードの大文字/小文字を選択 │
├─────────────────────────────────────┤
│ ○ 大文字 (SELECT, FROM, WHERE) │
│ ○ 小文字 (select, from, where) │
│ ○ 元のまま保持 │
└─────────────────────────────────────┘3. インデント幅
┌─────────────────────────────────────┐
│ インデント幅を選択 │
├─────────────────────────────────────┤
│ ○ 2スペース (推奨) │
│ ○ 4スペース │
│ ○ タブ │
└─────────────────────────────────────┘整形例
整形前:
SELECT u.id,u.name,u.email,o.order_id,o.total,o.created_at FROM users u INNER JOIN orders o ON u.id=o.user_id WHERE u.status='active' AND o.total>=1000 AND o.created_at>='2026-01-01' ORDER BY o.created_at DESC,o.total DESC LIMIT 100;整形後(大文字・2スペース):
SELECT
u.id,
u.name,
u.email,
o.order_id,
o.total,
o.created_at
FROM
users u
INNER JOIN orders o ON u.id = o.user_id
WHERE
u.status = 'active'
AND o.total >= 1000
AND o.created_at >= '2026-01-01'
ORDER BY
o.created_at DESC,
o.total DESC
LIMIT
100;整形後(小文字・4スペース):
select
u.id,
u.name,
u.email,
o.order_id,
o.total,
o.created_at
from
users u
inner join orders o on u.id = o.user_id
where
u.status = 'active'
and o.total >= 1000
and o.created_at >= '2026-01-01'
order by
o.created_at desc,
o.total desc
limit
100;具体的な使用場面とメリット
場面1:本番環境のログからSQLを抽出して分析
シーン:パフォーマンス問題の調査
application.log
---
[2026-02-15 10:30:45] Slow Query: SELECT u.id,u.name,p.product_id,p.name,p.price FROM users u JOIN purchases pu ON u.id=pu.user_id JOIN products p ON pu.product_id=p.id WHERE u.created_at>='2026-01-01' ORDER BY pu.created_at DESC;手順:
- SQLの部分を選択
- コマンド実行
- 方言選択(MySQL)
- 大文字・2スペース
- 整形されたSQLを確認してインデックス追加の検討
メリット:
- 圧縮されたログからSQLを即座に読みやすく変換
- 結合条件やWHERE句を視覚的に確認
- パフォーマンスチューニングの第一歩
場面2:他人が書いた複雑なクエリをレビュー
シーン:コードレビュー
-- レビュー対象のSQL(圧縮されている)
select u.id,u.name,u.email,count(o.order_id) as order_count,sum(o.total) as total_sales from users u left join orders o on u.id=o.user_id where u.status='active' group by u.id,u.name,u.email having count(o.order_id)>0 order by total_sales desc;手順:
- SQLを選択
- コマンド実行
- 方言選択(Standard SQL)
- 大文字・2スペース
- 整形されたSQLでロジックを確認
メリット:
- GROUP BYとHAVINGの条件を明確化
- 結合条件の妥当性を視覚的に確認
- レビューコメントを的確に指摘
場面3:マイグレーションスクリプトの整形
シーン:データベース移行作業
-- 古いシステムから取り出したDDL(フォーマットが崩れている)
create table users(id int primary key,name varchar(100) not null,email varchar(255) unique not null,status varchar(20) default 'active',created_at timestamp default current_timestamp);手順:
- DDLを選択
- コマンド実行
- 方言選択(PostgreSQL)
- 大文字・2スペース
- 整形されたDDLを確認してマイグレーションファイルに記載
メリット:
- カラム定義を視覚的に確認
- NOT NULL、DEFAULT、UNIQUEの制約を明確化
- チームメンバーとの共有が容易
場面4:プロジェクトのコーディング規約統一
シーン:新メンバーが参加してコーディング規約がバラバラ
-- メンバーAの書き方(小文字・インデントなし)
select * from users where status='active';
-- メンバーBの書き方(大文字・4スペース)
SELECT
*
FROM
users
WHERE
status = 'active';手順:
- すべてのSQLファイルを順次整形
- 方言選択(MySQL)
- 統一ルール:大文字・2スペース
- プロジェクト全体のSQL規約を統一
メリット:
- コードレビューの負担軽減
- 可読性の向上
- 新メンバーのオンボーディングを円滑化
場面5:Oracle PL/SQLのスラッシュ区切りに対応
シーン:Oracle開発環境でのPL/SQLブロック
BEGIN
INSERT INTO users (id, name) VALUES (1, 'Test');
COMMIT;
END; /問題:
sql-formatterはデフォルトで/を行末にくっつけてしまう- Oracle SQL*Plusでは
/が独立した行にないとエラー
このマクロの対応:
postProcessSlashSeparator()関数で/を独立した行に移動- Oracle開発者にとって使いやすい形式で出力
BEGIN
INSERT INTO users (id, name) VALUES (1, 'Test');
COMMIT;
END;
/場面6:複数SQLの一括整形
シーン:複数のクエリが含まれるファイル
SELECT * FROM users WHERE id=1; SELECT * FROM orders WHERE user_id=1; SELECT * FROM products WHERE category='electronics';手順:
- ファイル全体を対象(何も選択しない状態でコマンド実行)
- 方言選択(Standard SQL)
- 大文字・2スペース
- 整形された複数のSQLを確認
出力:
SELECT
*
FROM
users
WHERE
id = 1;
SELECT
*
FROM
orders
WHERE
user_id = 1;
SELECT
*
FROM
products
WHERE
category = 'electronics';メリット:
- クエリ間に2行の空行を自動挿入(
linesBetweenQueries: 2) - 複数クエリの視認性向上
TypeScript実装の詳細
実際のコードを紹介します。formatSql.tsファイルに実装しました。
import * as vscode from 'vscode';
import * as path from 'path';
import { format } from 'sql-formatter'; // sql-formatterライブラリをインポート
/**
* SQL整形ツール(sql-formatterライブラリ使用)
* 選択されたSQLを整形して新規ファイルに出力
*/
export async function formatSql() {
const editor = vscode.window.activeTextEditor;
if (!editor) {
vscode.window.showWarningMessage('アクティブなエディタがありません');
return;
}
const selection = editor.selection;
const document = editor.document;
// 選択範囲がある場合は選択範囲、なければファイル全体を対象
let sqlText: string;
if (!selection.isEmpty) {
sqlText = document.getText(selection);
} else {
sqlText = document.getText();
}
if (!sqlText || sqlText.trim().length === 0) {
vscode.window.showWarningMessage('整形対象のSQLがありません');
return;
}
// オプション選択ダイアログを表示
const options = await showFormatOptionsDialog();
if (!options) {
return; // ユーザーがキャンセルした場合
}
try {
// SQL整形を実行
const formattedSql = formatSqlText(sqlText, options);
// 新規ファイルに出力
await createResultFile(formattedSql);
vscode.window.showInformationMessage('SQL整形が完了しました');
} catch (error: any) {
// パースエラーの場合は詳細なメッセージを表示
if (error.message && error.message.includes('Parse error')) {
const message =
'SQL整形に失敗しました。\n\n' +
'原因:SQLとして認識できない文字が含まれています。\n' +
'(例:△、●、■などの記号、不正なSQL構文)\n\n' +
'対処法:\n' +
'1. SQL以外のテキストやコメントを削除してください\n' +
'2. 特殊文字(△など)を削除してください\n' +
'3. SQL構文が正しいか確認してください\n\n' +
`エラー詳細: ${error.message}`;
vscode.window.showErrorMessage(message, { modal: true });
} else {
vscode.window.showErrorMessage(`SQL整形エラー: ${error.message || error}`);
}
console.error('SQL formatting error:', error);
}
}
/**
* フォーマットオプション
*/
interface FormatOptions {
language: 'sql' | 'mysql' | 'postgresql' | 'tsql' | 'plsql' | 'mariadb' | 'db2' | 'redshift';
keywordCase: 'upper' | 'lower' | 'preserve';
tabWidth: number;
useTabs: boolean;
}
/**
* フォーマットオプション選択ダイアログ
*/
async function showFormatOptionsDialog(): Promise {
// 1. SQL方言の選択
const dialectItems = [
{ label: 'Standard SQL', value: 'sql' as const, description: '標準SQL(デフォルト)' },
{ label: 'MySQL / MariaDB', value: 'mysql' as const, description: 'MySQL/MariaDB方言' },
{ label: 'PostgreSQL', value: 'postgresql' as const, description: 'PostgreSQL方言' },
{ label: 'T-SQL (SQL Server)', value: 'tsql' as const, description: 'Microsoft SQL Server' },
{ label: 'PL/SQL (Oracle)', value: 'plsql' as const, description: 'Oracle Database' },
{ label: 'Amazon Redshift', value: 'redshift' as const, description: 'Amazon Redshift' },
{ label: 'IBM DB2', value: 'db2' as const, description: 'IBM DB2' }
];
const selectedDialect = await vscode.window.showQuickPick(dialectItems, {
placeHolder: 'SQL方言を選択してください',
ignoreFocusOut: true // ダイアログ外クリックでキャンセルされないようにする
});
if (!selectedDialect) {
return null; // キャンセル
}
// 2. キーワードの大文字/小文字
const caseItems = [
{ label: '大文字 (SELECT, FROM, WHERE)', value: 'upper' as const, description: 'キーワードを大文字に' },
{ label: '小文字 (select, from, where)', value: 'lower' as const, description: 'キーワードを小文字に' },
{ label: '元のまま保持', value: 'preserve' as const, description: '元の大文字/小文字を保持' }
];
const selectedCase = await vscode.window.showQuickPick(caseItems, {
placeHolder: 'キーワードの大文字/小文字を選択してください',
ignoreFocusOut: true
});
if (!selectedCase) {
return null; // キャンセル
}
// 3. インデント幅
const indentItems = [
{ label: '2スペース', tabWidth: 2, useTabs: false, description: '推奨' },
{ label: '4スペース', tabWidth: 4, useTabs: false },
{ label: 'タブ', tabWidth: 4, useTabs: true }
];
const selectedIndent = await vscode.window.showQuickPick(indentItems, {
placeHolder: 'インデント幅を選択してください',
ignoreFocusOut: true
});
if (!selectedIndent) {
return null; // キャンセル
}
return {
language: selectedDialect.value,
keywordCase: selectedCase.value,
tabWidth: selectedIndent.tabWidth,
useTabs: selectedIndent.useTabs
};
}
/**
* SQLテキストを整形
*/
function formatSqlText(sql: string, options: FormatOptions): string {
const formattedSql = format(sql, {
language: options.language, // SQL方言を指定
keywordCase: options.keywordCase, // キーワードの大文字/小文字
tabWidth: options.tabWidth, // インデント幅
useTabs: options.useTabs, // タブ使用有無
linesBetweenQueries: 2 // クエリ間の空行数(複数SQLの場合)
});
// Oracle PL/SQL の / を独立した行にする後処理
// 例: "dual /" → "dual\n/"
return postProcessSlashSeparator(formattedSql);
}
/**
* Oracle PL/SQL のスラッシュ区切りを独立した行にする後処理
*/
function postProcessSlashSeparator(sql: string): string {
// 行末のスラッシュの前に改行を挿入
// パターン: 任意の文字列 + スペース + / + 改行 → 文字列 + 改行 + / + 改行
return sql.replace(/\s+\/\s*$/gm, '\n/');
}
/**
* 結果を新規ファイルに出力
*/
async function createResultFile(formattedSql: string): Promise {
// 新規ドキュメントを作成(言語モードをSQLに設定)
const doc = await vscode.workspace.openTextDocument({
content: formattedSql,
language: 'sql'
});
// 右側に並べて表示
await vscode.window.showTextDocument(doc, {
viewColumn: vscode.ViewColumn.Beside,
preview: false
});
// ファイル名を自動生成
const suggestedName = generateFileName(new Date());
// 保存ダイアログを表示
const uri = await vscode.window.showSaveDialog({
defaultUri: vscode.Uri.file(suggestedName),
filters: {
'SQL files': ['sql'],
'Text files': ['txt'],
'All files': ['*']
}
});
if (uri) {
// ファイルを作成
const edit = new vscode.WorkspaceEdit();
edit.createFile(uri, { overwrite: true });
await vscode.workspace.applyEdit(edit);
// 内容を書き込み
await vscode.workspace.fs.writeFile(
uri,
Buffer.from(formattedSql, 'utf8')
);
vscode.window.showInformationMessage(
`整形済みSQLを保存しました: ${path.basename(uri.fsPath)}`
);
}
}
/**
* 出力ファイル名を生成
*/
function generateFileName(date: Date): string {
const timestamp = formatDateTimeForFile(date);
return `formatted_sql_${timestamp}.sql`;
}
/**
* 日時フォーマット(ファイル名用)
*/
function formatDateTimeForFile(date: Date): string {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return `${year}${month}${day}_${hours}${minutes}${seconds}`;
} コードのポイント解説
1. sql-formatterライブラリの活用
import { format } from 'sql-formatter'; // npmパッケージをインポート
const formattedSql = format(sql, {
language: 'mysql', // SQL方言を指定
keywordCase: 'upper', // キーワードを大文字に
tabWidth: 2, // インデント幅
useTabs: false, // スペースを使用
linesBetweenQueries: 2 // 複数クエリ間の空行数
});ポイント:
sql-formatterは複数のSQL方言に対応した軽量ライブラリ- オプションで細かくカスタマイズ可能
- パースエラー時には詳細なエラーメッセージを返す
2. オプション選択ダイアログの3段階構成
// 1. SQL方言を選択
const selectedDialect = await vscode.window.showQuickPick(dialectItems, {
placeHolder: 'SQL方言を選択してください',
ignoreFocusOut: true // ダイアログ外クリックでキャンセルされない
});
// 2. キーワードケースを選択
const selectedCase = await vscode.window.showQuickPick(caseItems, {
placeHolder: 'キーワードの大文字/小文字を選択してください',
ignoreFocusOut: true
});
// 3. インデント幅を選択
const selectedIndent = await vscode.window.showQuickPick(indentItems, {
placeHolder: 'インデント幅を選択してください',
ignoreFocusOut: true
});ポイント:
ignoreFocusOut: trueでダイアログ外クリックでもキャンセルされない- 3段階に分けることでユーザーの選択を明確化
- 各ステップで
nullチェックして早期リターン
3. Oracle PL/SQLのスラッシュ区切り対応
/**
* Oracle PL/SQL のスラッシュ区切りを独立した行にする後処理
*/
function postProcessSlashSeparator(sql: string): string {
// 行末のスラッシュの前に改行を挿入
// パターン: 任意の文字列 + スペース + / + 改行 → 文字列 + 改行 + / + 改行
return sql.replace(/\s+\/\s*$/gm, '\n/');
}ポイント:
- 正規表現
/\s+\/\s*$/gmで行末の/を検出 gmフラグで複数行にわたって処理- Oracle開発者にとって必須の後処理
4. エラーハンドリングの充実
try {
const formattedSql = formatSqlText(sqlText, options);
await createResultFile(formattedSql);
vscode.window.showInformationMessage('SQL整形が完了しました');
} catch (error: any) {
// パースエラーの場合は詳細なメッセージを表示
if (error.message && error.message.includes('Parse error')) {
const message =
'SQL整形に失敗しました。\n\n' +
'原因:SQLとして認識できない文字が含まれています。\n' +
'(例:△、●、■などの記号、不正なSQL構文)\n\n' +
'対処法:\n' +
'1. SQL以外のテキストやコメントを削除してください\n' +
'2. 特殊文字(△など)を削除してください\n' +
'3. SQL構文が正しいか確認してください\n\n' +
`エラー詳細: ${error.message}`;
vscode.window.showErrorMessage(message, { modal: true });
} else {
vscode.window.showErrorMessage(`SQL整形エラー: ${error.message || error}`);
}
console.error('SQL formatting error:', error);
}ポイント:
Parse errorを検出して専用のエラーメッセージを表示- ユーザーに原因と対処法を明示
modal: trueでエラーダイアログを強調表示
5. 新規ファイル出力とファイル名自動生成
/**
* 出力ファイル名を生成
*/
function generateFileName(date: Date): string {
const timestamp = formatDateTimeForFile(date);
return `formatted_sql_${timestamp}.sql`; // formatted_sql_20260215_103045.sql
}
/**
* 日時フォーマット(ファイル名用)
*/
function formatDateTimeForFile(date: Date): string {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return `${year}${month}${day}_${hours}${minutes}${seconds}`; // 20260215_103045
}ポイント:
- タイムスタンプ付きファイル名で重複を防止
- 年月日_時分秒の形式で整理しやすい
- 保存ダイアログで自動的にファイル名が提案される
6. 右側に並べて表示
// 右側に並べて表示
await vscode.window.showTextDocument(doc, {
viewColumn: vscode.ViewColumn.Beside, // 右側に表示
preview: false // プレビューモードを無効化
});ポイント:
vscode.ViewColumn.Besideで元のファイルと並べて表示- 元のSQLと整形後のSQLを同時に確認可能
preview: falseで確実にエディタとして開く
使い方
1. 拡張機能のインストール
git clone https://github.com/xxxxx-sys/my-macros.git
cd my-macros
# 依存関係インストール
npm install --legacy-peer-deps
# sql-formatterライブラリをインストール
npm install sql-formatter
# パッケージ化
npm run compile
npx vsce package
# インストール
code --install-extension my-macros-0.0.7.vsix2. 基本的な使い方
作業メモ.txt
---
SELECT u.id,u.name,o.order_id FROM users u JOIN orders o ON u.id=o.user_id WHERE u.status='active';手順:
- 整形したいSQLを選択(または何も選択せずファイル全体を対象)
- コマンドパレットを開く(
Ctrl+Shift+P) - "Format SQL" と入力して実行
- オプションダイアログで選択:
- SQL方言:MySQL
- キーワード:大文字
- インデント:2スペース
- 整形されたSQLが右側に表示される
- 保存ダイアログで保存
3. 実践例
シーン1: ログから抽出したSQLを整形
application.log
---
[2026-02-15 10:30:45] Slow Query: SELECT * FROM users WHERE status='active' AND created_at>='2026-01-01';手順:
- SQL部分を選択
- コマンド実行
- 方言選択(MySQL)
- 整形されたSQLを確認
シーン2: 複数のクエリを一括整形
SELECT * FROM users; SELECT * FROM orders; SELECT * FROM products;手順:
- 何も選択せずコマンド実行
- 方言選択(Standard SQL)
- 整形された3つのSQLが空行区切りで出力
package.jsonの設定
{
"contributes": {
"commands": [
{
"command": "myMacros.formatSql",
"title": "Format SQL",
"category": "My Macros"
}
],
"keybindings": [
{
"command": "myMacros.formatSql",
"key": "ctrl+shift+f",
"when": "editorTextFocus"
}
]
},
"dependencies": {
"sql-formatter": "^15.0.0"
}
}extension.tsでの登録
import { formatSql } from './macros/formatSql';
export function activate(context: vscode.ExtensionContext) {
const commands = [
vscode.commands.registerCommand(
'myMacros.formatSql',
formatSql
),
// ... 他のコマンド
];
commands.forEach(command => context.subscriptions.push(command));
}メリット・デメリット
メリット
✅ 圧倒的な効率化
- 1キー操作でSQL整形が完了
- オンラインツールやDBクライアントの立ち上げ不要
- VSCode上で完結
✅ 複数のSQL方言に対応
- MySQL、PostgreSQL、Oracle、SQL Server等に対応
- プロジェクトごとに適切な方言を選択可能
✅ 柔軟なカスタマイズ
- キーワードの大文字/小文字を選択
- インデント幅を選択(2スペース、4スペース、タブ)
- プロジェクトのコーディング規約に合わせて調整可能
✅ 安全性
- ローカル環境で完結(セキュリティ面で安心)
- 元のファイルは変更せず新規ファイルに出力
- エラー時の詳細メッセージで原因を把握
✅ 実務に即した機能
- Oracle PL/SQLのスラッシュ区切りに対応
- 複数クエリ間に空行を自動挿入
- タイムスタンプ付きファイル名で管理しやすい
デメリット
❌ sql-formatterの制限
- 完全に正しいSQL構文でないと整形できない
- 特殊な記号(△、●など)が含まれるとパースエラー
- 方言固有の構文で未対応のものもある
❌ 巨大なSQLファイルはパフォーマンス低下
- 数万行のSQLファイルは処理に時間がかかる可能性
- メモリ使用量が増加する場合あり
❌ 出力先が新規ファイル固定
- 元のファイルを直接置き換える機能はない
- 必ず新規ファイルに出力される
トラブルシューティング
Q: SQL整形に失敗する
A: SQLとして認識できない文字が含まれている
NG: SELECT * FROM users; -- △注意点
OK: SELECT * FROM users; -- 注意点解決策:
- SQL以外のテキストや特殊文字を削除
- コメント内の記号を確認
Q: 方言を間違えて選択した
A: 再度実行して正しい方言を選択
誤: Standard SQLで整形したがMySQLのバッククォートが消えた
正: MySQLで整形してバッククォートを保持解決策:
- MySQLの場合は "MySQL / MariaDB" を選択
- PostgreSQLの場合は "PostgreSQL" を選択
Q: 整形後のファイルを保存したくない
A: 保存ダイアログでキャンセル
解決策:
- 整形結果を確認したら保存ダイアログでキャンセル
- 一時的に確認するだけならそのままタブを閉じる
Q: オプション選択が面倒
A: デフォルト設定を変更したい場合はコードを修正
// デフォルト設定を変更する例
const options = {
language: 'mysql', // 常にMySQLに固定
keywordCase: 'upper', // 常に大文字に固定
tabWidth: 2,
useTabs: false
};解決策:
- よく使う設定をデフォルトにしたい場合はコードを修正
まとめ:SQL整形を1キー操作で実現する快適さ
VSCodeでsql-formatterライブラリを活用したSQL整形ツールを実装しました。
このマクロの強み:
- 1キー操作でSQL整形が完了
- 複数のSQL方言に対応(MySQL、PostgreSQL、Oracle等)
- キーワードケースとインデント幅を選択可能
- ローカル環境で完結(セキュリティ面で安心)
- Oracle PL/SQLのスラッシュ区切りに対応
- 充実したエラーハンドリング
こんな人におすすめ:
- ログから抽出したSQLを頻繁に分析する
- 複数のDBを扱うプロジェクトに参加している
- コーディング規約の統一を効率化したい
- マウス操作を減らしたい
- VSCodeで開発環境を完結させたい
特に、本番環境のログから圧縮されたSQLを抽出して分析する場面では、このマクロが大きな威力を発揮します。
手作業で1つずつ改行とインデントを調整していた作業が、たった1回のキー操作で完了します。
「読みづらいSQLに苦労している」という方は、ぜひVSCodeでのSQL整形にお役立てください!
関連記事
- VSCodeで正規表現マッチを一括抽出するTypeScriptマクロ

- VSCodeで「選択行による一括置換」を実現するTypeScriptマクロ

- VSCodeで「任意行までの一括選択・コピー」を実現するTypeScriptマクロ

- VSCode TypeScriptマクロ開発ガイド【サクラエディタから移行した開発環境構築】

タグ: #VSCode #TypeScript #マクロ #SQL #データベース #生産性向上 #sql-formatter
コメント