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
,@name
and$name
. We recommend using$name
since 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 で同じ変数なのに、それぞれで指定が必要
というように名前付きパラメーターの方が、可読性とメンテナンスの面で優れています。
コメント