2
1

More than 1 year has passed since last update.

nodeの便利なsqlビルダー、squelの使い方まとめ

Last updated at Posted at 2020-02-07

※2020年に作った記事なのでご注意ください。

##環境
node:v8.11.3

##squelとは
メソッドチェーンやって、sqlを組み立てられる便利なnodeモジュール。
sqlを直書きしていると、他の人が見て分かりにくいものになってしまうので、sqlビルダーを使います。

僕、フレームワークとか使う前までは直書きしていて、
当時は、文字列連結でandを作っていたので何回もやり直した記憶がある。。。

nogizaka-suko.js
const sql = 
"INSERT INTO test_table (id , name) VALUES (" +  id +","+ "'"+name+"'" +")" ;

このような地獄の文字列連結をforループの中でしていた時期が私にもあった。何度エラー出たことか。。。

larabelみたいな便利なフレームワークにはクエリビルダとかあったりするけど、今回はnodeなので、nodeのモジュールの力を借りる。

準備

●まず、インストール。
npmから、squelをインストールするだけ。
これは動作に必要なモジュールなので、--saveつける(何もつけないのと同じ)

●使い方
以下に書いたが、メソッドチェーンでfromやintoなどを直感的に指定できる。

selectを使った例

where()の中に、「squel.expr().and().and()」のように、拡張というか、追加で条件が書ける。
and()がいけるということは、もちろんor()もいける。
※ちなみに、.where().where()と繋げた場合はandになる。
なので、orもandもあるようなsqlなら書き方を合わせてexpr().and()を使うのもアリ

あと、order byなら「order()」
group byなら「group()」
を繋がるだけよい。
outer_left_join()とかははっきりとした名前なのになんでorderとgroupのときだけ省略されてんだって思ったけど、joinに関しては最後のほうにjoinという名前がつくので、まあ仕方ない。
join()だけでinner joinになる。

複数の条件の中で一部の条件に対して括弧をつけたいときは、再度where()を繋がればいい。
多少違和感を感じるかもしれないが、where()ごとに括弧で囲ったようなsqlが作れてラクなので結果的には使いやすい。

nogizaka-suko.js
const squel = require('squel');

//selectを使った例。
let sql = squel.select()
.field("title")
.field("deadline")
.from("calendar")
.order("calendar_id",false) // falseをつけると、desc。指定しなかったら、asc
.toString();
console.log(sql);//SELECT title, deadline FROM calendar ORDER BY calendar_id DESC

//case文
sql = squel.select()
.from("calendar")
.where(squel.case()
.when("name = ?" , "Aichi").then("正義のヒーローやんけ")
.when("name = ?" , "Hoge").then("なんだか怪しいなぁ"))
.toString();
console.log(sql);//SELECT calendar_id, hogehoge_title FROM calendar `cal` LEFT OUTER JOIN eventMaster `e` ON (cal.article_id=e.article_id) WHERE (cal.deed_flag<>1 AND (isnull(cal.article_id)) OR e.target_id<>2)

//joinを使った例
 sql = squel.select()
.from("calendar","cal")
.field("calendar_id")
.field("hogehoge_title")
.left_outer_join("eventMaster","e","cal.article_id=e.article_id")// as句がいらない場合は第二引数を「""」にする。第二引数を省略してはいけない。
.where(squel.expr().and("cal.deed_flag<>1").and("(isnull(cal.article_id))").or("e.target_id<>2"))
.toString();
console.log(sql);//SELECT calendar_id, hogehoge_title FROM calendar `cal` LEFT OUTER JOIN eventMaster `e` ON (cal.article_id=e.article_id) WHERE (cal.deed_flag<>1 AND (isnull(cal.article_id)) OR e.target_id<>2)

updateを使った例

set()を繋がるこどに、複数の値を更新できる。

nogizaka-suko.js
const sql = squel.update()
.table("hogeTable")
.set("name","aichi")
.where("name = taro")
.toString();
console.log(sql);//UPDATE hogeTable SET name = 'aichi' WHERE (name = taro)

insertを使った例

set()を繋げていって、複数の値を指定できる。

nogizaka-suko.js
//●insert
const sql = squel.insert()
.into("userMaster")
.set("name","aichi")
.set("age",23)
.toString();
console.log(sql);// insert into userMaster (name,age) values ("aichi" , 23)

deleteを使った例

これはまあ直感的。idとかは変数になると思うので、
バッククォートで埋め込むことになる。

nogizaka-suko.js
//●delete
const sql = squel.delete()
.from("otakuMaster")
.where("id = 1")
.toString();
console.log(sql);//DELETE FROM otakuMaster WHERE (id = 1)

クォーテーションで囲みたくない場合

例えばOracleのCURRENT_TIMESTAMPを指定したい場合、これをダブルクォーテーションで囲むと変な感じになるので、setの第三引数で指定できる

nogizaka-suko.js
  const sql = squel
    .insert()
    .into('hogeTable')
    .set('DATA_CREATE_DATE', 'CURRENT_TIMESTAMP', {
      dontQuote: true,
    })
.toString();
console.log(sql);//INSERT INTO hogeTable (DATA_CREATE_DATE) VALUES (CURRENT_TIMESTAMP)


## 連想配列を使って一気に指定
一つの組み合わせなら、setFields()に連想配列単体を入れればよい

```javascript:nogizaka-suko.js
//●フィールドを連想配列で指定
const sql = squel.insert()
.into("hogeTable")
.setFields({'name' : '愛知','age' : 23})
.toString();
console.log(sql);//INSERT INTO hogeTable (name, age) VALUES ('愛知', 23)

insertしたいデータの数が固定ではない場合のsql生成

他の処理結果からsql文を生成する場合、直接文字列連結なんかせず、データの連想配列をsetFieldsRows()に入れるだけで、sqlを生成してくれる。
insert文のvaluesの後が続いていく感じになるので、一回のinsert文で複数のレコードが入ることになります。
今回は、例として2つの連想配列データで試します。

実際は、for文でデータを回して1つの配列に対して連想配列データを入れていくことになります。

nogizaka-suko.js
const hogeArray1 = {
	'name' : 'Aichi',
	'age' : 23,
}
const hogeArray2 = {
	'name' : '山本彩',
	'age' : 26,
}

const allHogeArray = [hogeArray1,hogeArray2];

let sqlInsert = squel.insert()
.into("livingNationalTreasureMaster")
.setFieldsRows(allHogeArray)
.toString();
console.log(sqlInsert);//INSERT INTO livingNationalTreasureMaster (name, age) VALUES ('Aichi', 23), ('山本彩', 26)

感想

直書きしていた時代からしたら、感動もんですね。
たまに公式のREADMEに書かれていない構文があるが、
同じようにスネークケースで書いてみると実はちゃんと用意されていて使えたりします。

2
1
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
2
1