Haskellでデータベース操作

(2009.5.11 新規作成。)

(2013.4更新.)

ライブラリ

(2013.4更新.)

HaskellからRDBMSを操作するライブラリには, 次のものがあります。

hsqlとHDBCは、直接SQLを書くもので、似ています。見たところ、hsqlは placeholder の書き方が分からなかったため、HDBCのほうがよさそうです。

HaskellDB と Persistent は, Haskell の文法で書くので, Haskellソースのコンパイル時にSQLの誤りを検出できます。ただし, SQLのすべてを記述できるわけではありません。

haskelldb: SQL unwrapper for Haskell
SQLを使わず、Haskellの文法で書く. SELECT, INSERT, UPDATE, DELETE に対応。
hsql: Simple library for database access from Haskell
文字列でSQLを与える
HDBC · hdbc/hdbc Wiki · GitHub -- Haskell Database Connectivity
文字列でSQLを与える。DBIに似た感じ。

Persistent

Webアプリフレームワーク Yesod で使われている O/Rマッパ. 2017年1月現在の最新版は, バージョン 2.6.

別ページで解説します; 型安全な Persistent を使う

HDBC

データベースに接続し、テーブルを作って行を挿入するサンプルを書いてみます。コンパイルは次のようにします。

$ ghc -package HDBC-sqlite3 db.hs
Haskell
[RAW]
  1. import Database.HDBC
  2. import Database.HDBC.Sqlite3
  3. main = do
  4. -- データベースへの接続はRDBMS依存.
  5. conn <- connectSqlite3 "test.db"
  6. run conn "CREATE TABLE foo (a int primary key, b varchar(100));" []
  7. -- 引数はそれぞれtoSqlを付ける。
  8. run conn "INSERT INTO foo VALUES (?, ?)" [toSql (1::Int), toSql "hoge"]
  9. -- 自動コミットではない
  10. commit conn

SQL文に埋め込む値は, それぞれtoSqlを付けます。

Haskellではリストの要素は同じ型でなければなりませんが、SQLの引数として埋め込む値はそれぞれ違う型ですし、SQLにはナル値があったりもします。

toSqlは次の型を持ち、SqlValue型に揃えます。

Haskell
[RAW]
  1. Database.HDBC.toSql ::
  2. (Data.Convertible.Base.Convertible a Database.HDBC.SqlValue.SqlValue) =>
  3. a -> Database.HDBC.SqlValue.SqlValue

型を実行時にしか見ないスクリプト言語に比べるとちょっと面倒ではあります。

HaskellDB

(2013.4更新)

Haskellでは演算子を自由に定義できることを活かして、HaskellのコードをSQLにマップするライブラリです。

Haskellソースのコンパイル時に, SQLのエラーも検出できます。

root になって, 次のようにしてインストールします;

# cabal install --global haskelldb

(2017.1) しかし、書き方が SQL とギャップがあるのと、演算子を拡張 (定義) しまくりで、あまり自然ではない。というかやり過ぎ。ActiveRecord のように、条件式は文字列でいいじゃないか。

今なら persistent + esqueleto か。

(2017.1 ここまで)

接続

RDBMS への接続。

クエリ (SELECT)

挿入 (INSERT)

削除 (DELETE)

更新 (UPDATE)

クエリ式

演算子 意味
(.==.)
(.<>.)
(.<.)
(.<=.) (.>.) (.>=.) (.&&.) (.||.) (.*.) 乗算 (./.) (.+.) (.-.) (.%.) (.++.) 文字列の連結 _not
like SQL LIKEキーワード. "%"はワイルドカード, "_"は1文字 _in _length isNull notNull _sum _max _min