插入数据库Haskell

时间:2013-12-08 01:52:34

标签: haskell

我有一个列表:[["a","b"],["c","d"],["e","f"]],即(row1, row2, row3)我想插入数据。我的代码是

store xs =
 do conn <- connectSqlite3 "ld.db"
    stmt <- prepare conn "INSERT INTO ld (url, des) VALUES (?,?)"
    executeMany stmt [(head (map (\x -> [toSql x]) xs) ++ last (map (\x -> [toSql x]) xs))]
    commit conn

如果单独使用store ["a","b"],它工作正常。但我没有像store [["a","b"],["c","d"],["e","f"]]那样插入。我尝试了几种方法但失败了。我们需要正确使用map。感谢。

2 个答案:

答案 0 :(得分:2)

这将有效 -

let values = [["a", "b"], ["c", "d"], ["e", "f"]]
sequence $ map store values

或者,你可以使用更直观的 -

forM values store

有点像Haskell版本的不完美for循环。可以把它想象成像伪代码的Java / c / javascript:

for(value in values) 
{
  store(value);
}

您必须导入Control.Monad。

这就是说,你可能想要重构这个....你正在为每个插入创建一个连接,这会降低性能(只需拉出connectSqlite3并将函数提交出函数,并将conn作为参数传递) )。


我正在编辑以添加关于类型的一些讨论,以便您可以更好地了解这里发生的事情。

store ["a", "b"]

的类型为IO()....这是主要需要的,所以你已经设置好了。

map store values

的类型为[IO()],需要先将其转换为IO()才能在main中使用。在某种程度上,任何Haskell程序的整个目的是生成一个主要用于修改世界(输入和输出)的IO()。如果你掌握这些列表,它不知道使用哪一个。

sequence

是一个函数,它将IO()的列表和“序列”它们放入一个IO()中,可以由main使用。 (对于高级人员,我知道,它实际上适用于任何monad,但我认为这可能会使问题混淆在一起。)

forM

只是对参数移动的序列的友好重写。

答案 1 :(得分:1)

此代码存在两个问题:

  1. 缺乏正确的导入(用于转换的Database.HDBC.SqlValue)

  2. 单行的商店类型不能与许多行的商店相同。

  3. 改进代码:

    module Main(main) where
    
    import Database.HDBC.Sqlite3
    import Database.HDBC
    import Database.HDBC.Types
    import Database.HDBC.SqlValue
    import Data.Convertible.Base
    
    storeOne :: [String] -> IO ()
    storeOne xs =
      do conn <- connectSqlite3 "ld.db"
         stmt <- prepare conn "INSERT INTO ld (url, des) VALUES (?,?)"
         execute stmt $ map toSql xs
         commit conn
    
    storeMany :: [[String]] -> IO ()
    storeMany xs =
      do conn <- connectSqlite3 "ld.db"
         stmt <- prepare conn "INSERT INTO ld (url, des) VALUES (?,?)"
         executeMany stmt $ map (map toSql) xs
         commit conn
    
    main = do storeOne ["a", "b"]
              storeMany [["a","b"],["c","d"],["e","f"]]