我有一个列表:[["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
。感谢。
答案 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)
此代码存在两个问题:
缺乏正确的导入(用于转换的Database.HDBC.SqlValue)
单行的商店类型不能与许多行的商店相同。
改进代码:
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"]]