ルール
SQL クエリでの SELECT * の使用を 避ける
本番 コードでの SELECT *は、 アプリケーションを
スキーマ 変更に対して 脆弱にし、 データ 依存関係を 不明瞭にします。
対応言語: 45+はじめに
使用 SELECT * 本番クエリでは、アプリケーションが使用しない列を含む、テーブルからすべての列を取得します。データベーススキーマが進化し、新しい列(パスワードやPIIなどの機密データを含む)が追加されると、使用するクエリは SELECT * コード変更なしで自動的にそれらを取得し始めます。これはセキュリティ脆弱性を生み出し、アプリケーションロジックの前提を崩します。
なぜ重要なのか
パフォーマンスへの影響: 不要なカラムの取得は、クエリ実行時間、ネットワーク転送サイズ、およびメモリ消費量を増加させます。50カラムあるテーブルで5カラムしか必要としない場合、必要以上の10倍のデータを転送していることになり、応答時間を低下させ、インフラコストを増加させます。
セキュリティへの影響: テーブルに追加された新しいカラム(監査フィールド、内部フラグ、機密性の高いユーザーデータ)は、~を通じて自動的に公開されます SELECT * クエリ。APIがパスワードハッシュ、SSN、またはそのエンドポイント向けではなかった内部ビジネスデータを漏洩し始める可能性があります。
コードの保守性: いつ SELECT * スキーマ変更後にクエリが破損し、コンパイル時ではなく実行時に障害が発生します。新しいNULL非許容列や名前変更されたフィールドは、本番環境でエラーを引き起こします。明示的な列リストは依存関係を明確にし、スキーマが非互換に変更された場合にビルドを中断させます。
コード例
❌ 非準拠:
async function getUserProfile(userId) {
const query = 'SELECT * FROM users WHERE id = ?';
const [user] = await db.execute(query, [userId]);
return {
name: user.name,
email: user.email,
createdAt: user.created_at
};
}
誤っている理由: これは、password_hash、ssn、internal_notes、deleted_atなどの機密性の高い可能性のあるフィールドを含むすべての列を取得します。スキーマが成長するにつれて、このクエリは遅くなり、より多くのデータを公開しますが、アプリケーションは3つのフィールドしか使用していません。
✅ 準拠済み:
async function getUserProfile(userId) {
const query = `
SELECT name, email, created_at
FROM users
WHERE id = ?
`;
const [user] = await db.execute(query, [userId]);
return {
name: user.name,
email: user.email,
createdAt: user.created_at
};
}
まとめ
SQLクエリでは、常に明示的なカラムリストを指定してください。これにより、データ漏洩を防ぎ、パフォーマンスを向上させ、コードとスキーマ間の依存関係を明確にします。カラム名を入力するというわずかな初期コストで、セキュリティとパフォーマンスに関するあらゆる種類の問題を未然に防ぐことができます。

