使用Visual Studio Express 2013在c++中解决SQL Server连接问题
Troubleshooting SQL Server connection in C++ using Visual Studio Express 2013
我一直在尝试得到一个简单的程序,可以在SQL Server数据库上执行一些简单的操作,但不能得到任何教程实际运行。我试图弄清楚问题是与代码还是与我的ODBC设置。任何帮助/见解都是非常感谢的。
EDIT/UPDATE: ADDITIONAL DETAIL &下列代码
现在的主程序是基于本教程。我不得不做一些改变,使VS Express 2013能够编译代码:
- SQLCHAR *的所有实例必须更改为SQLWCHAR *。
- 必须使用wcout来输出错误信息
- 教程中使用的'GOTO: FINISHED'会产生对象可能未初始化的错误。我在'FINISHED'之后添加了一个'UNFIN'块,并将那些生成的错误更改为GOTO UNFIN,以使编译器高兴
- 添加了一些调试标记,以确保我正确地遵循程序
- 更改了连接字符串以匹配服务器,用户名和数据库的密码,我试图连接到。注意:目标数据库使用SQLServer2008
Messsage: [Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified
nSQLSTATE: IM002
它可能是像我需要在我的机器上切换的ODBC设置或我在项目设置中错过的依赖项一样简单的东西吗?
下面是代码。(请注意,对于正在测试的其他功能,还有额外的头文件。说其他功能在我目前的测试程序中被注释掉,并从下面的复制粘贴中删除,以减少混淆)
#include "stdafx.h"
#include <stdio.h>
#include <string>
#include <sstream>//Used to int to string, and string to int operations
#include <stdlib.h>
#include <fstream>//Used for file opening, appending and writing operations
#include <iostream>
#include <Windows.h>//Used for sleep command, and window "clearwindow" function
#include <sqlext.h> // Used for writing to SQL database
#include <sqltypes.h>
#include <sql.h>
using namespace std;
void show_error(unsigned int handletype, const SQLHANDLE& handle){
SQLWCHAR sqlstate[1024];
SQLWCHAR message[1024];
cout << "In show_error" << endl;
if (SQL_SUCCESS == SQLGetDiagRec(handletype, handle, 1, sqlstate, NULL, message, 1024, NULL)){
cout << "Message: ";
wcout << message;
cout << endl << "nSQLSTATE: ";
wcout << sqlstate;
cout << endl;
}
}
bool write_to_database(/*string dbconnection, string fields, string values*/){
SQLHANDLE sqlenvhandle;
SQLHANDLE sqlconnectionhandle;
SQLHANDLE sqlstatementhandle;
SQLRETURN retcode;
if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &sqlenvhandle))
goto UNFIN;
if (SQL_SUCCESS != SQLSetEnvAttr(sqlenvhandle, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0))
goto UNFIN;
if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_DBC, sqlenvhandle, &sqlconnectionhandle))
goto UNFIN;
SQLWCHAR retconstring[1024];
cout << "Made it this far at least" << endl;
switch (SQLDriverConnect(sqlconnectionhandle,
NULL,
(SQLWCHAR*)"DRIVER={SQL Server};SERVER=sqlserver.myhost.com, 1433;DATABASE=MyDatabase;UID=xxxxx;PWD=xxxxx",
SQL_NTS,
retconstring,
1024,
NULL,
SQL_DRIVER_NOPROMPT)){
case SQL_SUCCESS_WITH_INFO:
show_error(SQL_HANDLE_DBC, sqlconnectionhandle);
break;
case SQL_INVALID_HANDLE:
case SQL_ERROR:
cout << "Now we're in SQL_ERROR" << endl;
show_error(SQL_HANDLE_DBC, sqlconnectionhandle);
goto FINISHED;
default:
break;
}
if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_STMT, sqlconnectionhandle, &sqlstatementhandle))
goto FINISHED;
if (SQL_SUCCESS != SQLExecDirect(sqlstatementhandle, (SQLWCHAR*)"select * from testtable", SQL_NTS)){
show_error(SQL_HANDLE_STMT, sqlstatementhandle);
goto FINISHED;
}
else{
char name[64];
char address[64];
int id;
while (SQLFetch(sqlstatementhandle) == SQL_SUCCESS){
SQLGetData(sqlstatementhandle, 1, SQL_C_ULONG, &id, 0, NULL);
SQLGetData(sqlstatementhandle, 2, SQL_C_CHAR, name, 64, NULL);
SQLGetData(sqlstatementhandle, 3, SQL_C_CHAR, address, 64, NULL);
cout << id << " " << name << " " << address << endl;
}
}
FINISHED:
SQLFreeHandle(SQL_HANDLE_STMT, sqlstatementhandle);
SQLDisconnect(sqlconnectionhandle);
SQLFreeHandle(SQL_HANDLE_DBC, sqlconnectionhandle);
SQLFreeHandle(SQL_HANDLE_ENV, sqlenvhandle);
goto ALLOVER;
UNFIN:
cout << "Everything is unfinished" << endl;
ALLOVER:
return true;
}
int _tmain(int argc, _TCHAR* argv[])
{
write_to_database();
return 0;
}
编辑/更新:
继续尝试找出错误在哪里。使用基于EasySoft教程的代码来获得可用的DSN列表感觉有点像进步。下面是更新后的程序和结果:
// SQLTest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <string>
#include <iostream>
#include <Windows.h>//Used for sleep command, and window "clearwindow" function
#include <sql.h>
#include <sqltypes.h>
#include <sqlext.h> // Used for writing to SQL database
using namespace std;
static void extract_error(char *fn, SQLHANDLE handle, SQLSMALLINT handletype){
SQLWCHAR sqlstate[1024];
SQLWCHAR message[1024];
if (SQL_SUCCESS == SQLGetDiagRec(handletype, handle, 1, sqlstate, NULL, message, 1024, NULL)){
cout << "Message: ";
wcout << message;
cout << " nSQLSTATE: ";
wcout << sqlstate;
cout << endl;
}
}
static void do_sql(){
SQLHENV env;
SQLWCHAR dsn[256];
SQLWCHAR desc[256];
SQLSMALLINT dsn_ret;
SQLSMALLINT desc_ret;
SQLUSMALLINT direction;
SQLRETURN ret;
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
direction = SQL_FETCH_FIRST;
cout << "SQL DATA SOURCES:" << endl;
while (SQL_SUCCEEDED(ret = SQLDataSources(env, direction,
dsn, sizeof(dsn), &dsn_ret,
desc, sizeof(desc), &desc_ret))) {
direction = SQL_FETCH_NEXT;
wcout << dsn << " | " << desc << endl;
if (ret == SQL_SUCCESS_WITH_INFO) printf("tdata truncationn");
}
SQLHDBC dbc;
SQLHSTMT stmt;
SQLWCHAR outstr[1024];
SQLSMALLINT outstrlen;
/* Allocate an environment handle */
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
/* We want ODBC 3 support */
SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
/* Allocate a connection handle */
SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
/* Connect to the DSN mydsn */
string connstr = "DSN=EnglobalConn";
cout << endl << endl << "ATTEMPTING TO CONNECT TO DATA SOURCE USING:" << endl <<connstr << endl << endl;
ret = SQLDriverConnect(dbc, NULL, (SQLWCHAR*)connstr.c_str(), SQL_NTS,
outstr, sizeof(outstr), &outstrlen,
SQL_DRIVER_NOPROMPT);
if (SQL_SUCCEEDED(ret)) {
printf("Connectedn");
printf("Returned connection string was:nt%sn", outstr);
if (ret == SQL_SUCCESS_WITH_INFO) {
printf("Driver reported the following diagnosticsn");
extract_error("SQLDriverConnect", dbc, SQL_HANDLE_DBC);
}
SQLDisconnect(dbc); /* disconnect from driver */
}
else {
fprintf(stderr, "Failed to connectn");
extract_error("SQLDriverConnect", dbc, SQL_HANDLE_DBC);
}
/* free up allocated handles */
SQLFreeHandle(SQL_HANDLE_DBC, dbc);
SQLFreeHandle(SQL_HANDLE_ENV, env);
}
int _tmain(int argc, _TCHAR* argv[])
{
do_sql();
return 0;
}
程序给出如下输出。' englobaln '和'Englobal2'的错误相同
<>之前SQL数据源:dBASE文件| Microsoft Access dBASE驱动程序(*dbf, *. dbf)ndx, *中)Excel文件| Microsoft Excel Driver (*.xls, *.xlsx, *.xlsx)xlsm * .xlsb)MS Access Database | Microsoft Access Driver (*.)mdb, * .accdb)Englobal2 | SQL Serverenglobalcony | SQL Server试图使用以下命令连接到数据源:DSN = EnglobalConn连接失败消息:[microsoft][ODBC Driver Manager]数据源名称未找到,未指定默认驱动程序nSQLSTATE: IM002之前我在谷歌上找到的一条建议是,64位Windows安装有2个ODBC集,一个在System32中,一个在SysWOW64中。我已经运行了两个并将dsn设置为相同:在C:WindowsSysWOW64 odbcad32.exe:用户数据源:Englobal2 - SQL ServerSystem DSN: englobalcony - SQL Server
C:WindowsSystem32 odbcad32.exe:用户数据源:Englobal2 - SQL ServerSystem DSN: englobalcony - SQL Server
嗨,我一直在努力解决完全相同的问题,完全相同的失败:)
(SQLWCHAR *)"DRIVER={SQL Server}; Server =sqlserver.myhost.com, 1433;DATABASE=MyDatabase;UID=xxxxx;PWD=xxxxx",
应该是
(SQLWCHAR*)_T("DRIVER={SQL Server}; Server =sqlserver.myhost.com, 1433;DATABASE=MyDatabase;UID=xxxxx;PWD=xxxxx"),
或
(SQLWCHAR*)TEXT("DRIVER={SQL Server}; Server =sqlserver.myhost.com, 1433;DATABASE=MyDatabase;UID=xxxxx;PWD=xxxxx"),
万岁!找到一个有效的解决方案:
使用库http://otl.sourceforge.net/(设计用于Oracle,但也可以连接到SQL Server):
#include "stdafx.h"
#include <iostream>
using namespace std;
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define OTL_ODBC // Compile OTL 4.0/ODBC
// The following #define is required with MyODBC 3.51.11 and higher
#define OTL_ODBC_SELECT_STM_EXECUTE_BEFORE_DESCRIBE
// #define OTL_ODBC_UNIX // uncomment this line if UnixODBC is used
#include "otlv4.h" // include the OTL 4.0 header file
otl_connect db; // connect object
void insert()
// insert rows into table
{
otl_stream o(1, // buffer size should be == 1 always on INSERT
"insert into test_tab values "
"(:f1<int>, : f2<char[31]>), "
"(:f12<int>, : f22<char[31]>), "
"(:f13<int>, : f23<char[31]>), "
"(:f14<int>, : f24<char[31]>), "
"(:f15<int>, : f25<char[31]>) ",
// INSERT statement. Multiple sets of values can be used
// to work around the lack of the bulk interface
db // connect object
);
// If the number of rows to be inserted is not known in advance,
// another stream with the same INSERT can be opened
otl_stream o2(1, // buffer size should be == 1 always on INSERT
"insert into test_tab values "
"(:f1<int>, : f2<char[31]>)",
db // connect object
);
char tmp[32];
int i;
for (i = 1; i <= 100; ++i){
sprintf_s(tmp, "Name%d", i);
o << i << tmp;
}
for (i = 101; i <= 103; ++i){
sprintf_s(tmp, "Name%d", i);
o2 << i << tmp;
}
}
void update(const int af1)
// insert rows into table
{
otl_stream o(1, // buffer size should be == 1 always on UPDATE
"UPDATE test_tab "
" SET f2 = :f2<char[31]> "
" WHERE f1 = : f1<int>",
// UPDATE statement
db // connect object
);
o << "Name changed" << af1;
o << otl_null() << af1 + 1; // set f2 to NULL
}
void select(const int af1)
{
otl_stream i(50, // buffer size may be > 1
"select :f1<int>, :f2<char[31]> from test_tab "
/*"where f1 >= :f11<int> "*/,
// SELECT statement
db // connect object
);
// create select stream
cout << "Here" <<endl;
int f1;
char f2[31];
i << af1 << af1; // :f11 = af1, :f12 = af1
while (!i.eof()){ // while not end-of-data
i >> f1;
cout << "f1 = " << f1 << ", f2 = ";
i >> f2;
if (i.is_null())
cout << "NULL";
else
cout << f2;
cout << endl;
}
}
int main()
{
otl_connect::otl_initialize(); // initialize ODBC environment
try{
//db.rlogon("root / XX @mysql3532");
db.rlogon("driver={SQL Server};UID=XXXXX;PWD=XXXXXX; server=sqlserver.myserver.com"); // connect to ODBC
// db.rlogon("scott/tiger@mysql35"); // connect to ODBC, alternative format
// of connect string
otl_cursor::direct_exec
(
db,
"drop table test_table",
otl_exception::disabled // disable OTL exceptions
); // drop table
otl_cursor::direct_exec
(
db,
"create table test_table(f1 int, f2 varchar(30))"
//"create table test_tab(f1 int, f2 varchar(30)) type=innoDB" (causes MYSQL error)
); // create table
//insert(); // insert records into the table
//update(10); // update records in the table
//select(8); // select records from the table
otl_cursor::direct_exec(db, "INSERT INTO test_table (f1, f2) VALUES (600,'Test')");
otl_cursor::direct_exec(db, "INSERT INTO test_table (f1, f2) VALUES (-3,'Lest')");
otl_cursor::direct_exec(db, "INSERT INTO test_table (f1, f2) VALUES (4,'Rest')");
otl_cursor::direct_exec(db, "INSERT INTO test_table (f1, f2) VALUES (10,'Best')");
otl_cursor::direct_exec(db, "INSERT INTO test_table (f1, f2) VALUES (19,'Quest')");
//select(20);
}
catch (otl_exception& p){ // intercept OTL exceptions
cerr << "MSG: " << p.msg << endl; // print out error message
cerr << "STM_TEXT: " << p.stm_text << endl; // print out SQL that caused the error
cerr << "SQLSTATE: " << p.sqlstate << endl; // print out SQLSTATE message
cerr << "VAR_INFO: " << p.var_info << endl; // print out the variable that caused the error
}
db.logoff(); // disconnect from ODBC
return 0;
}
- 运行同一解决方案的另一个项目的项目
- Project Euler问题4的错误解决方案
- Ardunio UNO解决了多个重叠的定时器循环
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 两个文件使用彼此的功能-如何解决
- 计算每个节点的树高,帮助我解释这个代码解决方案
- 如何解决"invalid conversion from 'char' to 'const char*'"
- 在java中解决这段代码时面临循环中的问题
- C++:Application.cpp中抛出了未解析的外部符号(解决方案在问题的末尾,供未来的读者参考)
- 难以理解某些人解决IOI问题的源代码
- visual c++,如何获取解决方案目录中的代码
- 如何解决错误:SCIP C++中的 SCIP 阶段无效 <10>
- 节俭并发:未解决的外部问题
- IpOpt拒绝解决不受约束的问题
- 如何使用c++在VS 2019上运行SQL查询
- 如何解决这个超硬恒星的创造问题
- 循环无限运行C++解决骑士之旅问题
- System.InvalidCastException - SQL to C++ - safe_cast<float>
- 有没有办法在远程设备上打开和编辑visual Studio 2017解决方案
- 使用Visual Studio Express 2013在c++中解决SQL Server连接问题