🎉

【Flutter】SQLiteのクエリパラメータの使い方と安全なデータベース操作

2025/02/03に公開

はじめに

データベース操作で最も重要なのは、安全性です。SQL インジェクション攻撃を防ぐため、適切なパラメータバインディングの使用方法を説明します。

基本的なパラメータバインディング

SQLite では?を使ってパラメータをバインドします。

// 良い例:パラメータバインディングを使用
// データベースに新しいレコードを挿入する際、値を?でプレースホルダーとして指定
int recordId = await db.rawInsert(
  'INSERT INTO my_table(name, year) VALUES (?, ?)',
  ['my_name', 2019]
);

// 悪い例:文字列結合を使用
// SQLインジェクションの危険性があるため、この方法は避ける
int recordId = await db.rawInsert(
  "INSERT INTO my_table(name, year) VALUES ('my_name', 2019)"
);

IN 句でのパラメータバインディング

複数の値を含む IN 句を使用する場合の正しい方法を説明します。

IN 句とは?

IN 句は、複数の条件を指定して検索を行う場合に使用するクエリです。

例)

// 通常のWHERE句での書き方(OR を使用)
SELECT * FROM users
WHERE name = 'Taro' OR name = 'Jiro' OR name = 'Hanako';

// IN句を使用した場合(より簡潔に書ける)
SELECT * FROM users
WHERE name IN ('Taro', 'Jiro', 'Hanako');
// データベースから複数の条件に一致するレコードを取得
var list = await db.rawQuery(
  'SELECT * FROM my_table WHERE name IN (?, ?, ?)',
  ['cat', 'dog', 'fish']
);

// 動的に条件の数が変わる場合は以下のように対応
List<String> inArgs = ['cat', 'dog', 'fish'];
var list = await db.query(
  'my_table',
  where: 'name IN (${List.filled(inArgs.length, '?').join(',')})',
  whereArgs: inArgs
);

パラメータの位置指定

同じ値を複数回使用する場合は、位置パラメータを活用できます。

// ?1, ?2 のように数字で位置を指定
var result = await db.rawQuery(
  'SELECT ?1 as item1, ?2 as item2, ?1 + ?2 as sum',
  [3, 4]
);
// 結果: [{'item1': '3', 'item2': '4', 'sum': 7}]

NULL の扱い方

NULL の検索には特別な構文を使用します。

// 良い例:IS NULLを使用
var list = await db.query(
  'my_table',
  columns: ['name'],
  where: 'type IS NULL'
);

// 悪い例:=を使用
// この方法では正しく動作しない
var list = await db.query(
  'my_table',
  columns: ['name'],
  where: 'type = ?',
  whereArgs: [null]
);

LIKE 句の使用例

テキスト検索でよく使用される LIKE 句の例を紹介します。

// 'Ta'で始まる名前を検索
var list = await db.query(
  'my_table',
  columns: ['name'],
  where: 'name LIKE ?',
  whereArgs: ['Ta%']
);

// 'free'を含む名前を検索
var list = await db.query(
  'my_table',
  columns: ['name'],
  where: 'name LIKE ?',
  whereArgs: ['%free%']
);

まとめ

  1. SQL インジェクション対策として、必ずパラメータバインディングを使用する
  2. IN 句を使用する場合は、動的にプレースホルダーを生成する
  3. NULL 値の検索にはIS NULLを使用する
  4. LIKE 句での検索では%を適切に使用する

これらの方法を使用することで、安全で効率的なデータベース操作が可能になります。

参照

https://github.com/tekartik/sqflite/blob/master/sqflite/doc/sql.md#parameters

Discussion