我正在尝试通过 Visual C++ 2008 Express Edition 上的 MySQL ODBC 5.1 驱动程序使用 C++ 连接到 MySQL 服务器。
我正在按照 MSDN 中的这些说明进行操作:
唯一的区别是我必须将所有 SQLCHAR 转换为 SQLWCHAR,以匹配函数参数,希望这不会影响连接字符串。
每次连接时,我都会得到 SQL_ERROR 作为返回值。
所以我假设连接字符串或连接语句有问题。
我试过了
DNS=测试连接; UID=用户; PSW=密码
和
服务器=本地主机;驱动程序={MySQL ODBC 5.1 驱动程序};端口=3306; UID=用户; PSW=密码;数据库=dbo;
和其他类似的连接字符串。
名为 TestConnection 的 DNS 与后一个连接字符串具有相同的信息。
架构是 dbo,有一个名为 testfire 的表,其中包含以下列规范:
TEST_ID( INT(11), PRIMARY, AUTO INCREMENT)
TEST_STRING( VARCHAR(50) )
TEST_INTEGER( INT(11) )
TEST_FLOAT( FLOAT )
TEST_DATE( DATETIME )
有 3 行:
ID STRING INT FLOAT DATE
------------------------------------------------------
| 1 | Test 1 | 1 | 0.1 | 2001-01-01 00:00:00 |
| 2 | Test 2 | 2 | 0.2 | 2002-01-01 00:00:00 |
| 3 | Test 3 | 3 | 0.3 | 2003-01-01 00:00:00 |
------------------------------------------------------
我尝试使用 Excel 连接检索数据,主要是为了查看驱动程序是否正常工作。 Excel 成功地检索了数据,没有问题,因此名为 TestConnection 的 DNS 有效,凭据也是有效的。
MYSQLWCHAR * 弄乱了连接字符串? 哦,编译器没有给出任何错误或警告,代码编译和运行没有任何问题。
所以,这是测试代码,它返回“查询执行错误”:
#include <iostream>
#include <windows.h>
#include <sql.h>
#include <sqltypes.h>
#include <sqlext.h>
using namespace std;
int main(){
SQLHENV henv;
SQLHDBC hdbc;
SQLHSTMT hstmt;
SQLRETURN retcode;
HWND desktopHandle = GetDesktopWindow();
SQLWCHAR OutConnStr[255];
SQLSMALLINT OutConnStrLen;
SQLWCHAR szDNS[2048] ={0};
// Allocate environment handle
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
// Set the ODBC version environment attribute
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
// Allocate connection handle
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
// Set login timeout to 5 seconds
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
// Connect to data source
retcode = SQLDriverConnect(
hdbc,
desktopHandle,
(SQLWCHAR*)"driver=MySQL Server",
_countof("driver=MySQL Server"),
OutConnStr,
255,
&OutConnStrLen,
SQL_DRIVER_PROMPT );
// Allocate statement handle
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
// Process data
retcode = SQLExecDirect(hstmt, (SQLWCHAR*)"SELECT TEST_STRING, TEST_INTEGER, TEST_FLOAT FROM dbo.testfire", SQL_NTS);
if (retcode == SQL_SUCCESS) {
SQLINTEGER sTestInt, cbTestStr, cbTestInt, cbTestFloat;
SQLFLOAT dTestFloat;
SQLCHAR szTestStr[200];
while (TRUE) {
cout<<"Inside loop";
retcode = SQLFetch(hstmt);
if (retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO) {
cout<<"An error occurred";
}
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO){
SQLGetData(hstmt, 1, SQL_C_CHAR, szTestStr, 200, &cbTestStr);
SQLGetData(hstmt, 2, SQL_C_ULONG, &sTestInt, 0, &cbTestInt);
SQLGetData(hstmt, 3, SQL_C_FLOAT, &dTestFloat, 0,&cbTestFloat);
/* Print the row of data */
cout<<szTestStr<<endl;
cout<<sTestInt<<endl;
cout<<dTestFloat<<endl;
} else {
break;
}
}
}else{
cout<<"Query execution error."<<endl;
SQLWCHAR SqlState[6], Msg[SQL_MAX_MESSAGE_LENGTH];
SQLINTEGER NativeError;
SQLSMALLINT i, MsgLen;
SQLRETURN rc2;
// Get the status records.
i = 1;
while ((rc2 = SQLGetDiagRec(SQL_HANDLE_STMT, hstmt, i, SqlState, &NativeError,
Msg, sizeof(Msg), &MsgLen)) != SQL_NO_DATA) {
cout<<SqlState<<endl;
cout<<NativeError<<endl;
cout<<Msg<<endl;
cout<<MsgLen<<endl;
i++;
}
}
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
}
SQLDisconnect(hdbc);
}else{
cout<<"Connection error."<<endl;
}
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
}
}
SQLFreeHandle(SQL_HANDLE_ENV, henv);
}
system("pause");
return 0;
}
更新
使用 Mat 提供的文档中的 SQLDriverConnect 的正确参数更新代码(和发布)后(请参阅下面的评论),连接正常。如何在不提示输入 DNS 名称的情况下做同样的事情?将窗口句柄设为 null 并...?
现在它在 SQLExecDirect(hstmt, (SQLWCHAR*)"SELECT TEST_STRING, TEST_INTEGER, TEST_FLOAT FROM dbo.testfire", SQL_NTS) 处失败了,但是查询是正确的,所以,问题是什么?
返回的确切错误信息是:
Sql State: 42000
Native Error: 1064
Message:
Message Length: 211
42000: Syntax error or access violation
*StatementText contained an SQL statement that was not preparable or contained a syntax error.
The user did not have permission to execute the SQL statement contained in *StatementText.
所以……那是什么意思? 没有权限怎么办? 这怎么会产生语法错误,它显然是一个有效的查询?
最佳答案
在 Mat 的帮助下,我能够找出问题所在,但由于他没有以答案的形式给出,我必须回答它以便与那些人共享谁有同样的问题,也标记为已回答。
所以,我的问题是无法连接到数据库。正如 Mat 所建议的,我应该使用扩展的错误信息,称为 SQLGetDiagRec 并根据文档修复参数。我花了一些时间了解 SQLGetDiagRec 函数是如何工作的,但是一旦我设法将 wchar_t 转换为 char * 我就能够看到它产生的错误。
连接尝试给了我错误Data source not found and no default driver specified。这给了我一个线索,表明我写了不正确的连接字符串,或者文本字符串以某种方式被误解或损坏。
做一些事情 searching on the net让我意识到字符串被误解了,为了修复它,我必须把它变成一个文字字符串。果然,在字符串前面放一个 L 就解决了!
retcode = SQLDriverConnect(hdbc, 0,
(SQLWCHAR*)L"DSN=TestConnection;SERVER=localhost;UID=user;PWD=password;DRIVER=MySQL Server;",
_countof(L"DSN=TestConnection;SERVER=localhost;UID=user;PWD=password;DRIVER=MySQL Server;"),
OutConnStr, 255, &OutConnStrLen, SQL_DRIVER_COMPLETE);
与此同时,我学会了如何摆脱提示,这在纠正最初的问题后很容易弄清楚。为窗口句柄指定 null,将驱动程序完成设置为 SQL_DRIVER_COMPLETE 并确保在连接字符串中添加所有需要的信息。
因此,我在使用 SQLExecDirect 进行查询时遇到的下一个问题是给出了一个错误,指出 Syntax error or access violation。问题显然与连接字符串相同。果然够了
retcode = SQLExecDirect(hstmt, (SQLWCHAR*)L"SELECT TEST_STRING, TEST_INTEGER, TEST_FLOAT FROM dbo.testfire", SQL_NTS);
像魅力一样工作。
这是完整的、功能齐全的代码:
#include <iostream>
#include <windows.h>
#include <sql.h>
#include <sqltypes.h>
#include <sqlext.h>
#include <string>
using namespace std;
int main(){
SQLHENV henv;
SQLHDBC hdbc;
SQLHSTMT hstmt;
SQLRETURN retcode;
SQLWCHAR OutConnStr[255];
SQLSMALLINT OutConnStrLen;
// Allocate environment handle
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
// Set the ODBC version environment attribute
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
// Allocate connection handle
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
// Set login timeout to 5 seconds
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
// Connect to data source
retcode = SQLDriverConnect(
hdbc,
0,
(SQLWCHAR*)L"DSN=TestConnection;SERVER=localhost;UID=root;PWD=never140;DRIVER=MySQL Server;",
_countof(L"DSN=TestConnection;SERVER=localhost;UID=root;PWD=never140;DRIVER=MySQL Server;"),
OutConnStr,
255,
&OutConnStrLen,
SQL_DRIVER_COMPLETE );
// Allocate statement handle
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
// Process data
retcode = SQLExecDirect(hstmt, (SQLWCHAR*)L"SELECT TEST_STRING, TEST_INTEGER, TEST_FLOAT FROM dbo.testfire", SQL_NTS);
if (retcode == SQL_SUCCESS) {
SQLINTEGER sTestInt, cbTestStr, cbTestInt, cbTestFloat, iCount = 1;
SQLFLOAT dTestFloat;
SQLCHAR szTestStr[200];
while (TRUE) {
retcode = SQLFetch(hstmt);
if (retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO) {
cout<<"An error occurred";
}
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO){
SQLGetData(hstmt, 1, SQL_C_CHAR, szTestStr, 200, &cbTestStr);
SQLGetData(hstmt, 2, SQL_C_ULONG, &sTestInt, 0, &cbTestInt);
SQLGetData(hstmt, 3, SQL_C_DOUBLE, &dTestFloat, 0,&cbTestFloat);
/* Print the row of data */
cout<<"Row "<<iCount<<":"<<endl;
cout<<szTestStr<<endl;
cout<<sTestInt<<endl;
cout<<dTestFloat<<endl;
iCount++;
} else {
break;
}
}
}else{
cout<<"Query execution error."<<endl;
}
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
SQLDisconnect(hdbc);
}else{
cout<<"Connection error"<<endl;
}
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
}
}
SQLFreeHandle(SQL_HANDLE_ENV, henv);
}
system("pause");
return 0;
}
只是去展示,即使是最微小的事情也会让一切失败。
谢谢 Mat 的帮助。
关于c++ - 使用 C++ 连接到 MySQL 服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7860480/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h