node.js + express 最小構成でAzure上のSQL Database(SQL Server)に接続する

あまりAzureのSQL Databaseに接続する記事が見当たらなかったので書いてみます。最小限なので、環境変数とか使ってません。本来は使うべきなのでそちらの記事もそのうち書きます。

Azure SQL Databaseで試す方は、Azure管理画面でファイアウォールに自身のIPを忘れずに追加してください。もちろんローカルに存在するSQLServerでも問題なく接続できます。

準備

まずは必要なモジュールのインストール。

npm install tedious

インストールが終わったら、既にあるindex.jsにコードを追加しましょう。まずは関連するモジュールの初期化とコンフィグの作成。

var Connection = require('tedious').Connection;
var Request = require('tedious').Request;
// SQLServerの接続定義を記載する。
var config = {
  server: 'サーバ名.database.windows.net',    // IPアドレスもしくはサーバー名
  authentication: {
    type: 'default',
    options: {
      userName: '接続ユーザ名',
      password: '接続パスワード',
      useUTC: true //必要に応じて。未入力ならfalseになる。
    }
  },
  options: {
    encrypt: true, //必要に応じて。
    database: 'データベース名'
  }
};

細かい解説は省きますが、encryptはSQLDatabaseならtrue、ローカルSQLServerならfalseで接続出来ました。もし接続出来ない時は変更してみてください。

次にgetメソッドを追加します。

router.get('/test', function (req, res, next) {
  var connection = new Connection(config);
  connection.on('connect', function (err) {
    if (err) {
      return res.status(500).send('sql connection error');
    }
    else {
      execute();
    }
  });

  function execute() {
    var errorflg = false;
    var content = [];
    request = new Request("SELECT * FROM テーブル名", function (err) {
      if (err) {
        errorflg = true;
        return res.status(500).send('sql query error');
      }
    });

    request.on('row', function (columns) {
      var result = {};
      columns.forEach(function (column) {
        result[column.metadata.colName] = column.value === null ? '' : column.value;
      });
      content.push(result);
      result = {};
    });

    request.on('requestCompleted', function () {
      connection.close();
    });

    connection.on('end', function () {
      if(!errorflg)
        return res.status(200).json(content);
    });
    connection.execSql(request);
  };
});

まず、connectionとrequestどちらもon(‘~~’~~~)で動作を記述している点に注目です。どれらもイベントハンドラにfunctionを登録するイメージで記述していきます。これを理解していないと、SQL文の結果が帰ってきていないのにレスポンスを返してしまったりします。

connectionの’connect’が成功した場合、リクエストを投げるfunctionへ進みます。
requestは結果を1行ずつ’row’で処理する必要があります。処理が終わるとrequestの’requestCompleted’が実行され、その後connectionの’end’が発火し一連の流れが終わります。

また、これらの動作を定義してからconnection.execSql()を実行しないと、思った動作にならないので注意してください。

最後に

今回は手っ取り早く実装することが目的だったのでやっちゃってますが、データベースへの接続情報をコードにベタ書きするのはタブーです。必ず環境変数にある情報を読み取ってくる様に実装しましょう。