haskell操作数据库

对于现代应用软件系统以及网站,没有数据库的参与是很难想像的。Haskell中操作数据库的类库并不多,但是基本上包含了:

  • ODBC
  • MySQL
  • Oracle
  • PostgresSQL
  • SQLite/3

基本上够用了。
Haskell Database Libraries

我们这里用 Haskell Toolkit项目中的 HSQL 来做例子,其他的几个像 HaskellDB, CoddFish 等,有些过于 Haskellish 了,暂时先放过。

下载安装,就是标准的 Cabal 的安装过程: 到解压目录中:
runghc Setup.lhs configure
runghc Setup.lhs build
sudo runghc Setup.lhs install

以前在 configure 那步,看到有很多包没有发现,还以为无法安装,就去装那些“依赖”包,浪费了很多时间,后来才发现根本不需要。

装好之后,examples 目录下有一个例子, 把它的datasource 改成自己的,就可以测试了,需要改动的地方:


module Main where

import Control.Exception
import Database.HSQL.MySQL    -- MySQL 的库
import Queries

datasource = "YOUR_MYSQL_HOST"    -- 本地的话就是 localhost
database   = "DB_name"                      -- 要操作的库名
user_id    = "user"                                -- 用户名
password   = "pass"                             -- 密码



main = handleSql print $ do
        --  mysql 的 connect 需要上面列出的四个参数
        bracket (connect datasource database user_id password) disconnect $ \c ->
                inTransaction c $ \c -> do
                        createTables c
                        insertRecords c
                        retrieveRecords c
                        rs <- retrieveRecords c

                        putStrLn " Records inserted in table Test are: "
                        putStrLn "*************************************"
                        mapM print rs
                        putStrLn "*************************************"
                        putStrLn ""

                        putStrLn " The tables in your database are:    "
                        putStrLn "*************************************"
                        mi <- getMetaInfo c
                        mapM print mi
                        putStrLn "*************************************"
                        putStrLn ""

                        dropTables c



Queries.hs 中演示了基本的操作:表创建、表删除、插入记录、查询记录、获取表元信息:

module Queries where

import Database.HSQL

createTables :: Connection -> IO ()
createTables c = execute c "create table Test(id integer not null, name varchar(
255) not null)"

dropTables :: Connection -> IO ()
dropTables c = execute c "drop table Test"

insertRecords :: Connection -> IO ()
insertRecords c = do
        execute c "insert into Test(id,name) values (1,'Test1')"
        execute c "insert into Test(id,name) values (2,'Test2')"
        execute c "insert into Test(id,name) values (3,'Test3')"
        execute c "insert into Test(id,name) values (4,'Test4')"

retrieveRecords :: Connection -> IO [(Int,String)]
retrieveRecords c = do
        query c "select id, name from Test" >>= collectRows getRow
        where
                getRow :: Statement -> IO (Int,String)
                getRow stmt = do
                        id   <- getFieldValue stmt "id"
                        name <- getFieldValue stmt "name"
                        return (id,name)

getMetaInfo :: Connection -> IO [(String,[FieldDef])]
getMetaInfo c = do
        ts <- tables c
        mapM (\t -> describe c t >>= \cs -> return (t,cs)) ts