MySQL连接抛出;提供给mysql的未知准备语句处理程序(0)“U stmt”precheck”;错误
我创建了一个macOS应用程序来学习和测试本地MySQL连接 我通过自制安装了MySQL 我可以从应用程序连接到本地主机 我试图使用不存在的数据库名MySQL连接服务器,MySQL抛出未知数据库“测试” 使用现有数据库名称时,会出现以下错误: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
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进行交互,并且您正在继续