Node.jsによる MySQLの操作・同期処理 / SQL文字列の変数展開

JavaScript

Node.jsによる MySQLの操作

同期処理 / SQL文字列の変数展開

macOS 10.15.7 / MySQL Server 5.7.16
はじめに
MySQLモジュールの queryメソッドは非同期処理である。処理の制御は SQLコマンドを実行する queryメソッドの終了を待たずに次のステートメントに移る。
テーブル
クエリーの結果を受けて行う処理は、queryメソッドのコールバック関数の中に記述しなくてはならない。ひとつの単純な処理ならいいが、例えば、前の処理の結果をもとに複数の SQL文を実行するといった場合、処理のネストが深くなる。また、コールバック関数の中でデータを編集するために外部で定義した変数への参照が増えるとコードの視認性が落ちることになる。
できることなら queryメソッドの終了を待ち、結果を受け取り、そこから処理を続けたい。そうすればかなりスッキリしたコードになるだろう。Promiseオブジェクトおよび、async & await 文を使用することにより、そのような同期的な処理を実現することができる。
同期処理
関数(db_query)を作成し、SQLステートメント(connection.queryメソッド)を実装する。関数は SQLステートメントが終了するまで待ち、結果は Promiseオブジェクトに格納する。これを戻り値として呼び出し元に返す。
実装のポイントは次の通り。
SQLステートメントを変数で置き換える
下の例では、SELECTステートメントの WHERE句の条件値(idの値)に関数のパラメータ値を指定している。
connection.queryメソッドの第2引数に SQLステートメントに展開する値を配列として設定する。値は、SQLステートメントに記述されたリテラル '?' と置き換わる。要素が複数の場合、左側のリテラルからとなる。
ネストしたSQLステートメント
指定したレコードによりテーブルを検索し、レコードが存在すれば値を更新し、存在しなければ新規に追加する。まずSELECT文の実行する。結果を判定し、UPDATE文あるいいは、INSERT文を実行する。3種類のSQLステートメントのうち二つが実行されることになる。
前記の処理を踏襲して、async関数を3種類作成してもよいが、ここではひとつの async関数の中で全てを行うことにしてみる。実装のポイントは次の通り。
Promiseオブジェクトを受け取らない
SQLステートメントを実行した後の処理を async関数の中で完結させる場合のコード例を示す。例外を補足するために try文で囲む。