Haskell runtime error : UnsuccessfulReturnCode "odbc_SQLExecDirectW" (-1)

Haskell runtime error : UnsuccessfulReturnCode "odbc_SQLExecDirectW" (-1)

目前我正在编写一个运行几个 SQLServer 查询的小程序。为了使查询类型保存,我创建了一个模块“SQLQuery”,它可以让您以保存的方式设计查询。

要执行查询,它们必须是 Query 类型,因此我做了以下操作...

toSql $ 
T.pack (show (SELECT [Column "name"] (FROM (Table "kundenDBs")) (WHERE [AND (condition "activeProdData" Eq "'true'")]) NothingGB (ORDERBY [Column "name"] ASC)))

我的 Main.hs 代码是...

{-# LANGUAGE OverloadedStrings #-}

import           Database.ODBC.SQLServer
import           Data.ByteString
import qualified Data.Text as T
import           SQLQuery  (AND (..), Column (..), Direction (..), FROM (..),
                            GROUPBY (..), ORDERBY (..), Operand (..),
                            Operator (..), SELECT (..), Table (..), WHERE (..),
                            condition)

main :: IO ()
main = do
  conn <- connectToDB
  selectGipscommDB conn
  clients <- queryClients conn
  selectClientDB conn
  orders <- queryOrders conn
  print clients
  print orders

  -- Produces valid sql string (tested!)
  print $ show (SELECT [Column "name"] (FROM (Table "kundenDBs")) (WHERE [AND (condition "activeProdData" Eq "'true'")]) NothingGB (ORDERBY [Column "name"] ASC))

  close conn

connectToDB :: IO Connection
connectToDB =
    connect
      "DRIVER={ODBC Driver 13 for SQL Server};SERVER=xxx;Uid=yyy;Pwd=zzz"

selectGipscommDB :: Connection -> IO ()
selectGipscommDB =
    flip exec gipscommDB

gipscommDB :: Query
gipscommDB =
    "USE abc"

type Client = ByteString

queryClients :: Connection -> IO [Client]
queryClients =
    flip query clientsSql

clientsSql :: Query
clientsSql =
    toSql $ T.pack (show (SELECT [Column "name"] (FROM (Table "kundenDBs")) (WHERE [AND (condition "activeProdData" Eq "'true'")]) NothingGB (ORDERBY [Column "name"] ASC)))
    -- "SELECT name FROM kundenDBs WHERE activeProdData = 'true' ORDER BY name"

type Product = ByteString
type Order = ByteString

queryOrders :: Connection -> IO [(Product, Order)]
queryOrders = flip query ordersSql

ordersSql :: Query
ordersSql =
    "SELECT artikelnummer, auftrag FROM ProdData_ WHERE artikelnummer <> '' AND auftrag <> '' GROUP BY auftrag, artikelnummer ORDER BY artikelnummer"

selectClientDB :: Connection -> IO ()
selectClientDB =
    flip exec clientDB

clientDB :: Query
clientDB =
    "USE xyz"

我的 SQLQuery 模块代码是...

{-# LANGUAGE OverloadedStrings #-}

module SQLQuery where

import           Data.List               (intercalate)
import           Data.Maybe              (fromMaybe)
import           Data.String             (IsString (fromString))
import qualified Data.Text               as T
import           Database.ODBC.SQLServer


-- SELECT
--
data SELECT
    = SELECT [Column] FROM WHERE GROUPBY ORDERBY

instance Show SELECT where
    show (SELECT cols from where' groupBy orderBy) =
        "SELECT " ++ join ", " cols ++ " " ++ show from  ++ " " ++ show where' ++ " " ++ show groupBy ++ " " ++ show orderBy


-- FROM
--
newtype FROM = FROM Table

instance Show FROM where
    show (FROM tbl) = "FROM " ++ show tbl


-- WHERE
--
data WHERE
    = WHERE [AND]
    | NothingW

instance Show WHERE where
    show (WHERE ands) = "WHERE " ++ join " AND " ands
    show NothingW     = ""


-- AND
--
newtype AND = AND Condition

instance Show AND where
    show (AND cond) = show cond


--GROUPBY
--
data GROUPBY
    = GROUPBY [Column]
    | NothingGB

instance Show GROUPBY where
    show (GROUPBY cols) = "GROUP BY " ++ join ", " cols
    show NothingGB      = ""


-- ORDERBY
--
newtype ORDERBY = ORDERBY [Column]

instance Show ORDERBY where
    show (ORDERBY cols) = "ORDER BY " ++ join ", " cols


-- Table
--
newtype Table = Table String

instance Show Table where
    show (Table tbl) = tbl


-- Column
--
data Column = Column String Direction

instance Show Column where
    show (Column col dir) = col ++ " " ++ show dir


-- Condition
--
data Condition
    = Condition Operand Operator Operand

instance Show Condition where
    show (Condition operand1 operator operand2) = show operand1 <> show operator <> show operand2

condition :: String -> Operator -> String -> Condition
condition operand1 operator operand2 =
    Condition (Operand operand1) operator (Operand operand2)


-- Operand
--
newtype Operand = Operand String

instance Show Operand where
    show (Operand operand) = operand


-- Operator
--
data Operator
    = Eq
    | Ueq
    | Gt
    | Lt

instance Show Operator where
    show Eq  = " = "
    show Ueq = " <> "
    show Gt  = " > "
    show Lt  = " < "


-- Direction
--
data Direction
    = ASC
    | DESC

instance Show Direction where
    show ASC  = "ASC"
    show DESC = "DESC"


-- Functions
--
join :: Show a => String -> [a] -> String
join str = intercalate str . map show

哪个类型检查但在运行时导致错误...

UpdateProdData-exe.EXE: UnsuccessfulReturnCode "odbc_SQLExecDirectW" (-1) "[Microsoft][ODBC 
Driver 13 for SQL Server][SQL Server]In EXECUTE <procname>, procname can only be a literal or 
variable of type char, varchar, nchar, or nvarchar.[Microsoft][ODBC Driver 13 for SQL Server][SQL Server]In EXECUTE <procname>, procname can only be a literal or variable of type char, 
varchar, nchar, or nvarchar."

嗯,我不知道如何解决这个问题,如果有人能帮助我,我将不胜感激。 :)

Haskell ODBC 库旨在进行字符串转义。似乎正在发生的是 toSql "String" 将字符串的内容包装为转义的 SQL 字符串,而不是未转义的查询。

如果您使用 fromString myQuery 而不是 toSQL $ T.pack myQuery,它应该可以工作。