C++连接MySQL使用Statement无法查询结果及语句效率疑问
C++ MySQL连接:Statement执行INSERT后SELECT无结果及效率对比问题
问题描述
我使用C++的MySQL Connector编写了数据库连接代码,用Statement执行INSERT语句后立刻执行SELECT,却无法获取表内信息,但改用PreparedStatement就能正常运行。想请教两个问题:
- 这种INSERT后直接SELECT的流程是否存在问题?
- 向数据库添加数据时,PreparedStatement和Statement哪种效率更高?
代码示例
#include <iostream> #include <Windows.h> #include "jdbc/mysql_connection.h" #include "jdbc/cppconn/driver.h" #include "jdbc/cppconn/exception.h" #include "jdbc/cppconn/resultset.h" #include "jdbc/cppconn/statement.h" #include "jdbc/cppconn/prepared_statement.h" #ifdef _DEBUG #pragma comment(lib, "debug/mysqlcppconn.lib") #else #pragma comment(lib, "mysqlcppconn.lib") #endif using namespace std; std::string Utf8ToMultiByte(std::string utf8_str); int main() { try { sql::Driver* driver; sql::Connection* connection; sql::Statement* statement; sql::ResultSet* resultset; driver = get_driver_instance(); connection = driver->connect("tcp://127.0.0.1:3306", "root", ""); if (connection == nullptr) { cout << "connect failed" << endl; exit(-1); } connection->setSchema("logindata"); statement = connection->createStatement(); resultset = statement->executeQuery("insert into new_table(number, id, wincount, totalgameplay) values(4, 132, 232349, 123)"); resultset = statement->executeQuery("select * from new_table "); for (;resultset->next();) { cout << resultset->getInt("id") << " : " << Utf8ToMultiByte(resultset->getString("wincount")) << " : " << Utf8ToMultiByte(resultset->getString("totalgameplay")) << endl; } delete resultset; delete statement; delete connection; } catch (sql::SQLException e) { cout << "# ERR: SQLException in " << __FILE__; cout << "(" << __FUNCTION__ << ") on line " << __LINE__ << endl; cout << "# ERR: " << e.what(); cout << " (MySQL error code: " << e.getErrorCode(); cout << ", SQLState: " << e.getSQLState() << " )" << endl; } return 0; } std::string Utf8ToMultiByte(std::string utf8_str) { std::string resultString; char* pszIn = new char[utf8_str.length() + 1]; strncpy_s(pszIn, utf8_str.length() + 1, utf8_str.c_str(), utf8_str.length()); int nLenOfUni = 0, nLenOfANSI = 0; wchar_t* uni_wchar = NULL; char* pszOut = NULL; // 1. utf8 Length if ((nLenOfUni = MultiByteToWideChar(CP_UTF8, 0, pszIn, (int)strlen(pszIn), NULL, 0)) <= 0) return nullptr; uni_wchar = new wchar_t[nLenOfUni + 1]; memset(uni_wchar, 0x00, sizeof(wchar_t)*(nLenOfUni + 1)); // 2. utf8 --> unicode nLenOfUni = MultiByteToWideChar(CP_UTF8, 0, pszIn, (int)strlen(pszIn), uni_wchar, nLenOfUni); // 3. ANSI(multibyte) Length if ((nLenOfANSI = WideCharToMultiByte(CP_ACP, 0, uni_wchar, nLenOfUni, NULL, 0, NULL, NULL)) <= 0) { delete[] uni_wchar; return 0; } pszOut = new char[nLenOfANSI + 1]; memset(pszOut, 0x00, sizeof(char)*(nLenOfANSI + 1)); // 4. unicode --> ANSI(multibyte) nLenOfANSI = WideCharToMultiByte(CP_ACP, 0, uni_wchar, nLenOfUni, pszOut, nLenOfANSI, NULL, NULL); pszOut[nLenOfANSI] = 0; resultString = pszOut; delete[] uni_wchar; delete[] pszOut; return resultString; }
问题解答
1. INSERT后SELECT无结果的原因
你用statement->executeQuery()执行INSERT语句是错误用法。executeQuery()专门用于执行查询类SQL(如SELECT),它会返回查询结果集;而INSERT、UPDATE、DELETE这类数据操作语句,必须用executeUpdate()方法,该方法返回受影响的行数,不会生成结果集。
你的代码中用executeQuery()执行INSERT,会导致Statement内部状态异常,后续的SELECT查询也会被干扰,因此无法获取到结果。而改用PreparedStatement时,你应该是用了正确的executeUpdate()来执行INSERT,所以整个流程能正常运行。
修正方法:将INSERT语句的执行代码替换为:
// 执行INSERT并获取受影响行数 int affectedRows = statement->executeUpdate("insert into new_table(number, id, wincount, totalgameplay) values(4, 132, 232349, 123)"); cout << "成功插入 " << affectedRows << " 条数据" << endl;
2. PreparedStatement与Statement的效率对比
- 重复执行相同结构的SQL时,PreparedStatement效率更高:
PreparedStatement会在数据库端预编译SQL模板,后续执行仅需传入参数,避免了重复解析、优化SQL的开销。而Statement每次执行都会重新编译SQL,重复执行时性能差距明显。 - 单次执行简单SQL时,两者效率差异可忽略:
对于只执行一次的简单语句,编译开销占比极低,两者性能差不多。
此外,PreparedStatement还有额外优势:
- 自动处理参数转义,彻底避免SQL注入风险;
- 参数化写法比字符串拼接更清晰,代码可读性和维护性更好。
因此,日常开发中优先推荐使用PreparedStatement,尤其是涉及参数传递或需要重复执行的场景。
内容的提问来源于stack exchange,提问作者NW K
相关产品推荐
相关产品推荐

