2019年2月8日金曜日

node.jsでSQL-Serverを使いたい! (ちょっとプログラミング編)

準備編からの続きです

ASUS E203MAでnode.jsを動かしたいのですが、その際にSQL-Serverを使いたく、そのためのAPIとして「Tedious」を選びました。

今回はいよいよブログラミング編です。

テスト的なプログラミングではあるものの、そうは言っても、やっぱり何か使えるものを作りたいなぁと。

そこで、以下のようなテストプログラムを作ることにしました。

■ナレッジベース検索を作る!

(1)Excelシートに貯めているナレッジベースがあります。

(2)node.jsから検索キーワードを入力します。

(3)Tedious経由でSQL-Serverに接続し、ナレッジベースから情報を取得します。

(4)取得したナレッジベースの内容をコンソールに表示します。


↑Excel 2019(Office 365)で作り続けているナレッジベースがあります。

これに対して、SQL-Server経由でアクセスし、指定したキーワード検索を行い、当該情報がヒットしたらコンソールにその内容を表示する・・・という動きにします。

プログラム名はSQL1.jsとでもします(テキトー)。



//----------------------------------
//画面の罫線を定義
//----------------------------------
const cLINE1 = new String("=").repeat(100);
const cLINE2 = new String("・").repeat(100);

//----------------------------------
//パラメータから検索条件の作成
//----------------------------------
function CreateSqlWhere() {
    let sWhere = "";
    //process.argv.lengthはパラメータ数。node.exeそのものが0なので注意。
    //@@@@@@@@@@[LOOP-START]@@@@@@@@@@
    for(let i=2;i<process.argv.length;i++){
        console.log("process.argv.length="+process.argv.length);
        console.log("i="+i);
        sWhere += "{0} Collate Japanese_CI_AS ";
        sWhere += "Like '%" + process.argv[i] + "%' ";
        if(i < process.argv.length-1){
            sWhere += " AND ";
        }
    }
    //@@@@@@@@@@[LOOP-END  ]@@@@@@@@@@

    return sWhere;
}

//----------------------------------
//接続オブジェクト定義
//----------------------------------
//接続設定(SQL-Server 2017Express 名前付きインスタンス)
//名前付きインスタンスはポート指定してはいけない
let SqlConObject = require('tedious').Connection;
let config = {
    server  :'E203MA',
    authentication:{
        type     : 'default',
        options  : {
            userName : 'ログインID',
            password : 'パスワード'
        }
    },
    options :{
        instanceName:'EXPRESS2017',
        encrypt :false,
        database:'MAINDB'
    } 
};

//----------------------------------
//接続開始
//----------------------------------
let SqlCon = new SqlConObject(config);
SqlCon.on('connect', function(err) {
    if ( err ) {
        console.log('接続エラー(' + err + ')');
        process.exit();//終了
    }
    proc001();
});

//----------------------------------
//接続成功後のメイン処理
//----------------------------------
let iCount = 0;
let SqlReqObject = require('tedious').Request;
function proc001() {
    // Query Request
    let sWhere = CreateSqlWhere();

    let SqlStr = "SELECT T.* ";
        SqlStr+= "FROM OPENROWSET(";
        SqlStr+= "    'Microsoft.ACE.OLEDB.16.0'";
        SqlStr+= "   ,'Excel 12.0;DataBase=D:¥¥OneDrive¥¥HOME¥¥MAIN_DATA¥¥知識¥¥ナレッジベース.xlsx'";
        SqlStr+= "   ,'SELECT * FROM [学習$]') AS T ";
        SqlStr+= "WHERE [ジャンル] IS NOT NULL "
        SqlStr+="   AND " + sWhere;
        
        SqlStr = SqlStr.replace(/¥{0¥}/g, "[項目]+' '+[内容]");

    let SqlReq = new SqlReqObject(SqlStr, function(err, rows) {
        if ( err ) {
            console.log('リクエストエラー(' + err + '');
            process.exit(); //終了
        }
        SqlCon.close(); //接続終了
    });

    //実行結果イベント(1レコード毎)
    SqlReq.on('row', function(SqlRows) {
        //@@@@@@@@@@[LOOP-START]@@@@@@@@@@
        SqlRows.forEach(function(SqlRow){
            console.log(cLINE2);
            console.log(SqlRow.value);
            
        })
        //@@@@@@@@@@[LOOP-START]@@@@@@@@@@
        console.log(cLINE1);
        iCount++;

    });

    SqlReq.on('requestCompleted',function(){
        console.log("( " + iCount + " )件ありました!");
    });
    //クエリーの実行
    SqlCon.execSql(SqlReq);
}



↑接続のための情報をjson形式で記述するのですが、userNameとpasswordをそのまま「プロパティ:値」で記述したら、「その書き方は古いので新しい書き方にしとけ」という警告が毎回出るようになっていました。

公式サイトを参考にして、authenticationという階層を作り、さらにその中にoptionsという階層を作ってその中に記述し、ようやく警告が取れました。

それと、名前付きインスタンスの時は、serverだけだとだめです。

instanceNameプロパティの方で¥記号以下のインスタンス名を書くようにしないと、ポート1433の既定のインスタンス目掛けて接続に行ってしまうので注意が必要です。

エラーならまだしも、下手に同名のテーブルが偶然ヒットしたりすると、しばらく気が付かないで違うサーバーに接続したまま使用してしまうという獄炎地獄になるので気を付けてください。


実行はPowerShellのコンソールから行います。

以下のように、node.exe△実行ファイル名(SQL1.js)・・・の後ろに検索キーワードを付けます。


node.js C:\Temp\SQL1.js 検索キーワード1 ・・・ 検索キーワードn

↑実行結果が出ました。

昔懐かしいようなコンソール画面ですが、地味に地味にちょっと使えて割と嬉しい。

しかし、JavaScriptって、今って色々書けるように進化してますね。

ローカルのプログラミング(またはサーバーサイドプログラミング)がJavaScriptで可能になっているので、これはあまりにも途轍もなくでかい。

特に、処理の部分で一切ブラウザの仕様に悩まされる事なく書けるのは気持ち良いですね。