使用C++连接SQL Server创建新表时出现报错如何解决
SQL Server 建表失败问题
以下是用于创建SQL Server连接并尝试新建数据表的函数:
我已尝试所有能想到的解决方法,目前毫无头绪。与服务器的连接可正常建立,但始终提示“could not create a new table”。我已查阅Stack Overflow上该主题的相关帖子,仍未找到解决方案。
程序返回的报错如下:
以下是主函数及运行截图,可证明简单查询语句可正常运行:
原有代码:
void DB::runQuery(string SQLQuery) { SQLCHAR retConString[1024]; // Conection string switch (SQLDriverConnect(SQLConnectionHandle, NULL, (SQLCHAR*)"DRIVER={SQL Server}; SERVER=localhost, 1433; DATABASE=myDB; UID=myID; PWD=1234;", SQL_NTS, retConString, 1024, NULL, SQL_DRIVER_NOPROMPT)) { // Establishes connections to a driver and a data source case SQL_SUCCESS: break; case SQL_SUCCESS_WITH_INFO: break; case SQL_NO_DATA_FOUND: showSQLError(SQL_HANDLE_DBC, SQLConnectionHandle); retCode = -1; break; case SQL_INVALID_HANDLE: showSQLError(SQL_HANDLE_DBC, SQLConnectionHandle); retCode = -1; break; case SQL_ERROR: showSQLError(SQL_HANDLE_DBC, SQLConnectionHandle); retCode = -1; break; default: break; } if (retCode == -1) print("An error occurred"); if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_STMT, SQLConnectionHandle, &SQLStatementHandle)) // Allocates the statement print("could not allocate the statement"); if (SQL_SUCCESS != SQLExecDirect(SQLStatementHandle, (SQLCHAR*)SQLQuery.c_str(), SQL_NTS)) { // Executes a preparable statement showSQLError(SQL_HANDLE_STMT, SQLStatementHandle); print("could not execute the statement"); } else { char name[256]; int age; while (SQLFetch(SQLStatementHandle) == SQL_SUCCESS) { // Fetches the next rowset of data from the result SQLGetData(SQLStatementHandle, 1, SQL_C_DEFAULT, &name, sizeof(name), NULL); SQLGetData(SQLStatementHandle, 2, SQL_C_DEFAULT, &age, sizeof(age), NULL); // Retrieves data for a single column in the result set cout << name << " " << age << endl; } } }
修复方案
你的代码核心问题是逻辑适配不全,仅适配了有结果集返回的查询类SQL,没有适配CREATE TABLE这类无结果集的DDL语句,导致执行建表语句时触发后续的结果集读取错误,被误判为执行失败。
具体问题及修改点
- 移除每次执行语句时的重复建连逻辑,把数据库连接初始化抽离到单独的初始化函数,仅在程序启动时执行一次即可,避免连接资源泄漏。
- 新增参数标记当前执行的SQL是否需要返回结果集,只有SELECT类查询才走结果集读取逻辑,建表、插入、更新这类语句直接跳过即可。
- 每次执行完语句后释放Statement句柄,避免资源耗尽导致后续执行失败。
- 额外排查两个非代码问题:确认连接使用的myID账号有myDB数据库的CREATE TABLE权限;确认你执行的建表SQL本身没有语法错误,不存在表名重复、字段类型不合法等问题。
修改后代码
// 连接初始化仅执行一次即可,不要放在runQuery里重复调用 void DB::initConnection() { SQLCHAR retConString[1024]; switch (SQLDriverConnect(SQLConnectionHandle, NULL, (SQLCHAR*)"DRIVER={SQL Server}; SERVER=localhost, 1433; DATABASE=myDB; UID=myID; PWD=1234;", SQL_NTS, retConString, 1024, NULL, SQL_DRIVER_NOPROMPT)) { case SQL_SUCCESS: case SQL_SUCCESS_WITH_INFO: retCode = 0; break; case SQL_NO_DATA_FOUND: case SQL_INVALID_HANDLE: case SQL_ERROR: showSQLError(SQL_HANDLE_DBC, SQLConnectionHandle); retCode = -1; break; default: retCode = -1; break; } if (retCode == -1) print("An error occurred in connection"); } void DB::runQuery(string SQLQuery, bool hasResultSet) { if (retCode == -1) { print("Connection is invalid"); return; } SQLHSTMT stmt; if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_STMT, SQLConnectionHandle, &stmt)) { print("could not allocate the statement"); return; } if (SQL_SUCCESS != SQLExecDirect(stmt, (SQLCHAR*)SQLQuery.c_str(), SQL_NTS)) { showSQLError(SQL_HANDLE_STMT, stmt); print("could not execute the statement"); SQLFreeHandle(SQL_HANDLE_STMT, stmt); return; } if (hasResultSet) { char name[256]; int age; while (SQLFetch(stmt) == SQL_SUCCESS) { SQLGetData(stmt, 1, SQL_C_DEFAULT, &name, sizeof(name), NULL); SQLGetData(stmt, 2, SQL_C_DEFAULT, &age, sizeof(age), NULL); cout << name << " " << age << endl; } } SQLFreeHandle(SQL_HANDLE_STMT, stmt); }
调用时执行建表语句传入hasResultSet = false,执行SELECT语句传入hasResultSet = true即可。
内容的提问来源于stack exchange,提问作者רועי סלע
相关产品推荐
相关产品推荐

