I have a list like: [["a","b"],["c","d"],["e","f"]]
, ie (row1, row2, row3)
I want to insert data. My code is
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
It is working fine if I use individually store ["a","b"]
. But I have failed to insert like store [["a","b"],["c","d"],["e","f"]]
. I tried in several ways but failed. We need proper use of map
. Thanks.
This will work-
let values = [["a", "b"], ["c", "d"], ["e", "f"]]
sequence $ map store values
Alternatively, you could use the more intuitive-
forM values store
which works sort of like a Haskell version of an imperitive for loop. Think of it like the Java/c/javascript like pseudocode:
for(value in values)
{
store(value);
}
You will have to import Control.Monad.
This being said, you might want to refactor this.... You are creating a connection for each insert, which can degrade performance (just pull the connectSqlite3 and commit lines out of the function, and pass conn in as a parameter).
I am editing to add a bit of discussion on types, so that you can better understand what is going on here.
store ["a", "b"]
is of type IO().... This is what main wants, so you are set.
map store values
is of type [IO()], which needs to be converted to IO() before it can be used in main. To some extent, the whole purpose of any Haskell program is to generate a single IO() that main can use to modify the world (input and output). If you hand main a list of these, it doesn't know which one to use.
sequence
is a function that takes a list of IO()'s and "sequences" them into one single IO(), which can be used by main. (For the advanced folks, I know, it actually works for any monad, but I think that might confuse matters at this point).
forM
is just a friendly rewriting of sequence with parameters moved around.
There are two problems with this code:
Lack of proper imports (Database.HDBC.SqlValue for conversion)
Type of store for a single row cannot be the same as store for many rows.
Improved code:
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"]]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.