Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySQL连接抛出;提供给mysql的未知准备语句处理程序(0)“U stmt”precheck”;错误_Mysql_Swift - Fatal编程技术网

MySQL连接抛出;提供给mysql的未知准备语句处理程序(0)“U stmt”precheck”;错误

MySQL连接抛出;提供给mysql的未知准备语句处理程序(0)“U stmt”precheck”;错误,mysql,swift,Mysql,Swift,我创建了一个macOS应用程序来学习和测试本地MySQL连接 我通过自制安装了MySQL 我可以从应用程序连接到本地主机 我试图使用不存在的数据库名MySQL连接服务器,MySQL抛出未知数据库“测试” 使用现有数据库名称时,会出现以下错误: Unknown prepared statement handler (0) given to mysql_stmt_precheck 我的连接代码: import PerfectHTTP import PerfectHTTPServer import

我创建了一个macOS应用程序来学习和测试本地MySQL连接

我通过自制安装了MySQL

我可以从应用程序连接到本地主机

我试图使用不存在的数据库名MySQL连接服务器,MySQL抛出未知数据库“测试”

使用现有数据库名称时,会出现以下错误:

Unknown prepared statement handler (0) given to mysql_stmt_precheck
我的连接代码:

import PerfectHTTP
import PerfectHTTPServer
import PerfectMySQL
import Foundation

public class DB {

    let host = "127.0.0.1"
    let user = "root"
    let password = "12345678"
    let database = "pets"
   
    func databaseConnect(host: String, user: String, password: String, db: String) -> MySQL {
        
        let mysql = MySQL() // Create an instance of MySQL to work with
        
        let connected = mysql.connect(host: host, user: user, password: password, db: db)
        
        guard connected else {
            // verify that we have connected successfully
            print(mysql.errorMessage())
            return mysql
        }
        
        return mysql
    }
    
    public func insertGame(title: String, description: String, createdDate: String){
    
        // Connect to our database
        var db = databaseConnect(host: host, user: user, password: password, db: database)
        
        defer {
            db.close() //This defer block makes sure we terminate the connection once finished, regardless of the result
        }
        
        // Create the statement we wish to execute
        let statement = MySQLStmt(db)
        let insert = "INSERT INTO game(id, title, description, release_date) VALUES (\(statement.insertId()), '\(title)', '\(description)', '\(createdDate)');"
        _ = statement.prepare(statement: insert)
        
        // Run the query
        let querySuccess = statement.execute()
        
        // Check that our query was successfuly, otherwise return out
        guard querySuccess else {
            print(db.errorMessage())
            return
        }
        
        print("Insert successful!");
    }
    
}

您不应该在
INSERT
语句本身中使用
insertId
(它只是在调用)。该函数获取以前执行的
INSERT
语句的id,由于没有以前的语句,它将失败

您只需从
INSERT
语句中省略
AUTO_INCREMENT
列,让MySQL自己设置自动递增值。这显然假设您将其定义为一个自动递增列,例如

现在,如果在
INSERT
之后,如果您需要自动递增键使用的值,那么您可以调用
insertId
。例如:

func databaseConnect(host: String, user: String, password: String, db: String) -> MySQL? {
    let mysql = MySQL() // Create an instance of MySQL to work with

    let connected = mysql.connect(host: host, user: user, password: password, db: db)

    // verify that we have connected successfully
    guard connected else {
        print(mysql.errorCode(), mysql.errorMessage())
        return nil
    }

    return mysql
}

@discardableResult
public func insertGame(title: String, description: String, createdDate: String) -> UInt? {
    // Connect to our database
    guard let db = databaseConnect(host: host, user: user, password: password, db: database) else {
        return nil
    }

    // Create the statement we wish to execute
    let statement = MySQLStmt(db)
    let insert = "INSERT INTO game (title, description, release_date) VALUES (?, ?, ?);"
    guard statement.prepare(statement: insert) else {
        print(db.errorMessage())
        return nil
    }

    // bind values to the ? in the prepared SQL
    statement.bindParam(title)
    statement.bindParam(description)
    statement.bindParam(createdDate)

    // Check that our query was successfuly, otherwise return out
    guard statement.execute() else {
        print(db.errorMessage())
        return nil
    }

    // if you really need the ID, this is where you'd call `insertId`, perhaps returning it in case the caller would need it
    let id = statement.insertId()
    return id
}

上述代码片段中还包含一些其他不相关的问题:

  • 我建议不要使用字符串插值来构建SQL。如果标题是“Finnegan's Wake”,名称中的撇号将搞乱SQL,过早终止该字符串值,该怎么办。理想情况下,您可以像上面那样将值绑定到占位符,或者至少使用一些转义逻辑。问题中的SQL容易受到SQL注入攻击和/或需要转义字符串的语法错误的影响

  • 我不会建议使用
    \=语句。准备(…)
    模式。返回值的全部意义在于告诉您它是否成功。如果
    prepare
    失败,您将检查错误消息并退出该功能

  • 我建议只有在与服务器连接成功时才能继续。在您的报告中,您报告了第二条“MySQL服务器已离开”消息。这仅仅是因为当连接失败时,您正试图与MySQL进行交互,并且您正在继续