7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Node.js] MySQLのIN句をプレースホルダーで表す

Posted at

#概要

Node.jsでMySQLを扱うにあたり、
IN句のリスト部分をプレースホルダーで表すには、どのようにすれば良いかを以下に記していきます。

#本題の前に...
(本題しか興味ない人は、すっ飛ばしてください)
##Node.jsでMySQLを扱うためにインストール

npm i -S mysql promise-mysql

##Node.jsでMySQLプレースホルダーを扱うときの基本

例えば、プレースホルダーなしで書こうとすると以下のようになります。(良くない例です)

【NG例】プレースホルダーなし
const userid = 1 ;
const sql = `SELECT * FROM users WHERE userid = ${userid} ;`

このままだと、SQLインジェクションの格好の餌食となってしまうため、
プレースホルダーを使って書き直します。

【OK例】プレースホルダーあり
const userid = 1;
const sql = `SELECT * FROM users WHERE userid = ? ;`
const res = await conn.query(sql, userid);
//この場合、
//SELECT * FROM users WHERE userid = 1;
//というクエリを投げたことになる

変数が2つ以上になる場合は、

【OK例】変数が2つ以上の場合
const userid = 1;
const classname = 'G';
const sql = `SELECT * FROM users WHERE userid = ? AND classname = ? ;`
const res = await conn.query(sql, [userid, classname] );
//この場合、
//SELECT * FROM users WHERE userid = 1 AND classname = 'G';
//というクエリを投げたことになる

のように、配列に変数を格納することで表すことができます。

#本題「IN句のリストをプレースホルダで表したい」
以下のように書くことで、IN句もプレースホルダーを用いて表すことができます。

IN句でプレースホルダーを使う
const sql = `SELECT * FROM users WHERE userid NOT IN (?) ;`
const excludedId = [1, 3, 4];
const res = await conn.query(sql, [excludedId] );

これで、userid = 1, 3, 4 以外の行を抽出することができました。

##ちょっとだけ解説
複数の変数がある場合、その変数の個数分「?」を用意する必要があると上述しました。
今回の場合、

リストを?で表す
const excludedId = [1, 3, 4];
const sql = `SELECT * FROM users WHERE userid NOT IN (?,?,?) ;`

のように書かれていてほしいわけです。
しかしながら、状況によって
?の個数が3つから4つ、5つと変動していくことも考えられ、上記のように書くのは現実的ではありません。

そこで、
「1,3,4をそれぞれ変数として見る」のではなく、
「[1,3,4]という配列を、1つの変数として捉える」ことで解決できます。
リストに渡したい配列さえあれば、その配列を引数に渡すだけで
簡単にクエリを作ることが出来ました。

##注意点

ちなみに、以下のやり方ではエラーが出ます。

【NG例】IN句でプレースホルダーを使う
const sql = `SELECT * FROM users WHERE userid NOT IN (?) ;`
const excludedId = [1, 3, 4];
const res = await conn.query(sql, excludedId);

複数の変数が出てくる場合は
[userid, classname]のように配列に変数を格納して、渡しますよね。

しかし今回の場合、[1,3,4]という配列を一つの変数として扱いたいので、
const res = await conn.query(sql, excludedId );
のように配列を渡してしまうと、
その中の要素である、1,3,4という3つの数値が、変数として見られてしまいます。

そのため必ず、配列を配列で括って書くようにしましょう。

#余談「Node.jsでクエリを確認するためには」
プレースホルダーで書いていると、
実際、自分の思ったところに正しい変数が入っているか不安になることもあると思います。
そこで、以下のような書き方をすると
実際に投げられているクエリを確認することができ、大変便利です。

クエリ確認

const excludedId = [1, 3, 4];
const sql = mysql.format(`select * from users where userid NOT IN (?) ;`, [excludeId] );
console.log(sql); //select * from users where userid NOT IN (1,3,4) ;

#終わりに
IN句のリストをプレースホルダーで表している例があまりなかったので
先輩の助けを借り、今回記事にしてみました。
参考になれば幸いです。

#参考

7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?