SQL で値をバインドするとき、よく見るかける例ではプレースホルダーを ? にしていますが、名前付きパラメーターで記述した方が可読性も良く、その後のメンテナンスも楽です。
環境
- SQLite Version 3.32.3
- Node.js Version 16.3.0
- sqlite3 Version 5.0.2
名前付きパラメーターを使ったとき
SQL の記述で、パラメーターで渡したい値に $ で始まる変数名を使い、その名前で値をバインドします。
const sqlite3 = require('sqlite3').verbose();
const db = new sqlite3.Database(':memory:');
const sql = `
INSERT INTO users(id, name, email, address)
VALUES($id, $name, $email, $address)
ON CONFLICT(id)
DO UPDATE SET
  name = $name,
  email = $email,
  address = $address
;`;
db.serialize(function () {
  const stmt = db.prepare(sql);
  const params = {
    $id: 'kuma',
    $name: 'kuma emon',
    $email: 'master@kuma-emon.com',
    $address: 'kuma 1-2-3',
  };
  stmt.run(params);
  stmt.finalize();
});
db.close();$ と : と @ を使うことができますが、公式は $ を勧めています。
Named parameters can be prefixed with
https://github.com/mapbox/node-sqlite3/wiki/API#databaserunsql-param–callback:name,@nameand$name. We recommend using$namesince JavaScript allows using the dollar sign as a variable name without having to escape it.
名前付きパラメーターを使わなかったとき
プレースホルダーを ? で記述したときは、次のようになります。
const sqlite3 = require('sqlite3').verbose();
const db = new sqlite3.Database(':memory:');
const sql = `
INSERT INTO users(id, name, email, address)
VALUES(?, ?, ?, ?)
ON CONFLICT(id)
DO UPDATE SET
  name = ?,
  email = ?,
  address = ?
;`;
db.serialize(function () {
  const stmt = db.prepare(sql);
  const params = [
    'kuma',
    'kuma emon',
    'master@kuma-emon.com',
    'kuma 1-2-3',
    'kuma emon',
    'master@kuma-emon.com',
    'kuma 1-2-3',
  ];
  stmt.run(params);
  stmt.finalize();
});
db.close();名前付きパラメーターの良さが分かる
SQL文と渡すパラメーターを比較すると、名前付きパラメーターの良さが分かります。
  // 名前付きパラメーター
  // INSERT INTO users(id, name, email, address)
  // VALUES($id, $name, $email, $address)
  // ON CONFLICT(id)
  // DO UPDATE SET
  //   name = $name,
  //   email = $email,
  //   address = $address;
  const params = {
    $id: 'kuma',
    $name: 'kuma emon',
    $email: 'master@kuma-emon.com',
    $address: 'kuma 1-2-3',
  };
  // 名前付きパラメーターでない
  // INSERT INTO users(id, name, email, address)
  // VALUES(?, ?, ?, ?)
  // ON CONFLICT(id)
  // DO UPDATE SET
  //   name = ?,
  //   email = ?,
  //   address = ?;
  const params = [
    'kuma',
    'kuma emon',
    'master@kuma-emon.com',
    'kuma 1-2-3',
    'kuma emon',
    'master@kuma-emon.com',
    'kuma 1-2-3',
  ];名前付きパラメーターを使わなかった場合、プレースホルダーの順に値を渡すようになり、
- 順番通りに値を渡す必要がある
 → パラメーターが増減するような変更が SQL にあったときに注意が必要
- 同じ変数も、現れる順番に渡す必要がある
 → INSERT と UPDATE で同じ変数なのに、それぞれで指定が必要
というように名前付きパラメーターの方が、可読性とメンテナンスの面で優れています。
 
 


コメント