SQL Server Connection c++ - c++

I'm having trouble connecting to my local SQL Server Express DB. I'm fairly new to c++ and wanted to try messing around with "simple" server connections to mess around with dbs. But I have two main errors I keep getting and haven't figured out I believe everything in the backend is setup correctly (ie. server users/logins & accessibility) heres the code I have atm:
#include "pch.h"
#include <iostream>
#include <windows.h>
#include <sqlext.h>
#include <sqltypes.h>
#include <sql.h>
using namespace std;
void showSQLError(SQLCHAR desc[1024], unsigned int handleType, const SQLHANDLE& handle)
{
SQLCHAR SQLState[1024];
SQLCHAR message[1024];
if (SQL_SUCCESS == SQLGetDiagRec(handleType, handle, 1, SQLState, NULL, message, 1024, NULL))
// Returns the current values of multiple fields of a diagnostic record that contains error, warning, and status information
cout << "At Point:" << desc << endl;
cout << "SQL driver message: " << message << "\nSQL state: " << SQLState << "." << endl;
}
int main()
{
cout << "Hello world" << endl;
SQLHANDLE SQLEnvHandle = NULL;
SQLHANDLE SQLConnectionHandle = NULL;
SQLHANDLE SQLStatementHandle = NULL;
SQLRETURN retCode = 0;
//desc
SQLCHAR noData[1024] = "SQL_NO_DATA\n";
SQLCHAR invalidHandle[1024] = "SQL_INVALID_HANDLE\n";
SQLCHAR error[1024] = "SQL_ERROR\n";
SQLCHAR success[1024] = "Connection succesful";
char SQLQuery[] = "SELECT * FROM roster";
do {
if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &SQLEnvHandle))
// Allocates the environment
break;
if (SQL_SUCCESS != SQLSetEnvAttr(SQLEnvHandle, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0))
// Sets attributes that govern aspects of environments
break;
if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_DBC, SQLEnvHandle, &SQLConnectionHandle))
// Allocates the connection
break;
if (SQL_SUCCESS != SQLSetConnectAttr(SQLConnectionHandle, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0))
// Sets attributes that govern aspects of connections
break;
SQLCHAR retConString[1024]; // Conection string
switch (SQLDriverConnect(SQLConnectionHandle, NULL, (SQLCHAR*)"DRIVER={SQL Server Native Client 11.0}; SERVER=MYPC\SQLEXPRESS, 1433; DATABASE=MYdb; UID=myID; PWD=myPWD ", 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(noData , SQL_HANDLE_DBC, SQLConnectionHandle);
retCode = -1;
break;
case SQL_INVALID_HANDLE:
showSQLError(invalidHandle, SQL_HANDLE_DBC, SQLConnectionHandle);
retCode = -1;
break;
case SQL_ERROR:
showSQLError(error, SQL_HANDLE_DBC, SQLConnectionHandle);
retCode = -1;
break;
default:
break;
}
if (retCode == -1)
break;
if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_STMT, SQLConnectionHandle, &SQLStatementHandle))
// Allocates the statement
break;
if (SQL_SUCCESS != SQLExecDirect(SQLStatementHandle, (SQLCHAR*)SQLQuery, SQL_NTS)) {
// Executes a preparable statement
showSQLError(success, SQL_HANDLE_STMT, SQLStatementHandle);
break;
}
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;
}
}
} while (FALSE);
SQLFreeHandle(SQL_HANDLE_STMT, SQLStatementHandle);
SQLDisconnect(SQLConnectionHandle);
SQLFreeHandle(SQL_HANDLE_DBC, SQLConnectionHandle);
SQLFreeHandle(SQL_HANDLE_ENV, SQLEnvHandle);
// Frees the resources and disconnects
getchar();
}
so my initial error with the above code is:
At Point:SQL_ERROR
SQL driver message: [Microsoft][SQL Server Native Client 11.0]TCP Provider: No such host is known.
SQL state: 08001.
And if I change my connection string to:
SQLDriverConnect(SQLConnectionHandle, NULL, (SQLCHAR*)"DRIVER={SQL Server
Native Client 11.0}; SERVER=MYPC\\SQLEXPRESS, 1433; DATABASE=MYdb;
UID=myID; PWD=myPWD ", SQL_NTS, retConString, 1024, NULL, SQL_DRIVER_NOPROMPT))
NOTE: The added '\' in the SERVER string
I get:
At Point:SQL_ERROR
SQL driver message: [Microsoft][SQL Server Native Client 11.0]TCP Provider: No connection could be made because the target machine actively refused it.
SQL state: 08001.
I beleive the \ is correct but unclear as to why it would be refused. I have setup all the permissions and accounts for the server correctly (assumingly) unless my approach is just straight up incorrect. Where/ would my local server be refusing my connection attempt?

I have never seen an instance name like "MYPC\SQLEXPRESS, 14.0". It should almost certainly be just "MYPC\SQLEXPRESS", and if it actually is "MYPC\SQLEXPRESS, 14.0" it needs to be contained in {} the way the driver name is.
I suggest you use the "sqlcmd -L" command (install it from https://www.microsoft.com/en-us/download/details.aspx?id=53591 if you don't already have it) and use one of the instance names that returns.
The benefit of sqlcmd over other instance listing methods I'm aware of is that sqlcmd uses ODBC and thus you will get a name that the SQL Server ODBC driver is ready to use.

Related

visual studio - SQLDriverConnect is failing (returning SQL_ERROR)

I am trying to connect to a database I created in SQL Server Management Studio from Visual Studio 2017 in C++, but the function SQLDriverConnect is not connecting, it's failing and returning SQL_ERROR for some reason.
this is the code I am using: (I took it from the internet, and I saw it in many other websites)
#include <iostream>
#include <windows.h>
#include <sqlext.h>
#include <sqltypes.h>
#include <sql.h>
using namespace std;
void showSQLError(unsigned int handleType, const SQLHANDLE& handle)
{
SQLCHAR SQLState[1024];
SQLCHAR message[1024];
if (SQL_SUCCESS == SQLGetDiagRec(handleType, handle, 1, SQLState, NULL, message, 1024, NULL))
cout << "SQL driver message: " << message << "\nSQL state: " << SQLState << "." << endl;
}
int main()
{
SQLHANDLE SQLEnvHandle = NULL;
SQLHANDLE SQLConnectionHandle = NULL;
SQLHANDLE SQLStatementHandle = NULL;
SQLRETURN retCode = 0;
do {
if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &SQLEnvHandle))
break;
if (SQL_SUCCESS != SQLSetEnvAttr(SQLEnvHandle, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0))
break;
if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_DBC, SQLEnvHandle, &SQLConnectionHandle))
break;
if (SQL_SUCCESS != SQLSetConnectAttr(SQLConnectionHandle, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0))
break;
SQLCHAR retConString[1024];
switch (SQLDriverConnect(SQLConnectionHandle, NULL, (SQLCHAR*)"DRIVER={SQL Server}; SERVER=DESKTOP-MYSERVER\\SQLEXPRESS, 1433; DATABASE=mydatabase; UID=sa; PWD=mypassword;", SQL_NTS, retConString, 1024, NULL, SQL_DRIVER_NOPROMPT)) {
case SQL_SUCCESS:
std::cout << "YES" << std::endl;
break;
case SQL_SUCCESS_WITH_INFO:
std::cout << "YES" << std::endl;
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:
cout << "Here" << endl; // it is failing here <<<<<<
showSQLError(SQL_HANDLE_DBC, SQLConnectionHandle);
retCode = -1;
break;
default:
break;
}
if (retCode == -1)
break;
if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_STMT, SQLConnectionHandle, &SQLStatementHandle))
break;
//Some sql query execution after connecting to the database.
} while (FALSE);
SQLFreeHandle(SQL_HANDLE_STMT, SQLStatementHandle);
SQLDisconnect(SQLConnectionHandle);
SQLFreeHandle(SQL_HANDLE_DBC, SQLConnectionHandle);
SQLFreeHandle(SQL_HANDLE_ENV, SQLEnvHandle);
getchar();
}
I have tried all possible solutions suggested on the internet, such as running VS as administrator, putting Trusted_Connection=yes; instead of UID/PWD, putting localhost in SERVER or some suggested that I should enable TCP/IP and Named Pipes in SQL Server Configuration and SQL Server Browser in Services.
But none of those have worked, I have added my database with sa username to ODBC DSN User and DSN System, also no luck.
This is what I'm getting in the console:
Am I missing something? What is going on?
Thanks in advance
Anyone facing the problem, I fixed it by adding the port 1433 in SQL Server Configuration > TCP/IP > Properties > IP Addresses tab (at the end).
Also Enabling TCP/IP.

Error when trying to connect & run query: Message 0085E084 SQLSTATE 0085E88C

I have been trying to connect to Azure SQL and query from it.
I get this error message:
Here is the complete code that I have used:
#include "stdafx.h"
#include <iostream>
#include <windows.h>
#include <sqltypes.h>
#include <sql.h>
#include <sqlext.h>
using namespace std;
void show_error(unsigned int handletype, const SQLHANDLE& handle)
{
SQLWCHAR sqlstate[1024];
SQLWCHAR message[1024];
if (SQL_SUCCESS == SQLGetDiagRec(handletype, handle, 1, sqlstate, NULL, message, 1024, NULL))
cout << "Message: " << message << "\nSQLSTATE: " << sqlstate << endl;
}
int main()
{
SQLHANDLE sqlenvhandle;
SQLHANDLE sqlconnectionhandle;
SQLHANDLE sqlstatementhandle;
SQLRETURN retcode;
do
{
if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &sqlenvhandle))
break;
if (SQL_SUCCESS != SQLSetEnvAttr(sqlenvhandle, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0))
break;
if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_DBC, sqlenvhandle, &sqlconnectionhandle))
break;
SQLWCHAR retconstring[1024];
/*switch (SQLDriverConnect(sqlconnectionhandle, NULL,
L"Driver={ODBC Driver 10 for SQL Server};Server=tcp:xyz.database.windows.net;Database=ProjectLIT;UID=auser;PWD=zzzzz;Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30;",
SQL_NTS, retconstring, 1024, NULL, SQL_DRIVER_NOPROMPT)*/
switch (SQLDriverConnect(sqlconnectionhandle, NULL,
L"DRIVER={SQL Server};SERVER=xyz.database.windows.net,1433;DATABASE=ProjectLIT;UID=auser;PWD=zzzzz;",
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:
show_error(SQL_HANDLE_DBC, sqlconnectionhandle);
retcode = -1;
break;
default:
break;
}
if (retcode == -1)
break;
if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_STMT, sqlconnectionhandle, &sqlstatementhandle))
break;
//if (SQL_SUCCESS != SQLExecDirect(sqlstatementhandle, L"SELECT * FROM Emploees_Res", SQL_NTS))
if (SQL_SUCCESS != SQLExecDirect(sqlstatementhandle, L"SELECT [Internal Email ID] FROM [Emploees_Res] WHERE [Office Acc]=63", SQL_NTS))
{
show_error(SQL_HANDLE_STMT, sqlstatementhandle);
break;
}
else
{
char name[64];
while (SQLFetch(sqlstatementhandle) == SQL_SUCCESS)
{
SQLGetData(sqlstatementhandle, 1, SQL_C_CHAR, name, 64, NULL);
cout << name;
}
}
} while (FALSE);
SQLFreeHandle(SQL_HANDLE_ENV, sqlenvhandle);
}
I thought the error might be in connection string.
Can anyone please advise where the correction is needed? Thanks in advance.
Many thanks to all,
Finally got the solution, as said by quentin used L wide string Literals
Below is the exact Connection string
switch (SQLDriverConnect(sqlconnectionhandle, NULL,
L"DRIVER={SQL Server};Server=tcp:xyz.database.windows.net,1433;DATABASE=ProjectLIT;UID=auser;PWD=zzzzzz;Encrypt=yes;TrustServerCertificate=no;Connection Timeout=30;",
SQL_NTS, retconstring, 1024, NULL, SQL_DRIVER_NOPROMPT))

SQL connection from Visual C++ Windows Form project

I'm very new to C++. just created a C++ Windows Forms project using Visual Studio Community 2015. And used the below main function to obtain a SQL connection.
#include "stdafx.h"
#include <iostream>
#include <windows.h>
#include <sqlext.h>
#include <sqltypes.h>
#include <sql.h>
using namespace std;
int main()
{
#define SQL_RESULT_LEN 240
#define SQL_RETURN_CODE_LEN 1000
//define handles and variables
SQLHANDLE sqlConnHandle;
SQLHANDLE sqlStmtHandle;
SQLHANDLE sqlEnvHandle;
SQLWCHAR retconstring[SQL_RETURN_CODE_LEN];
//initializations
sqlConnHandle = NULL;
sqlStmtHandle = NULL;
//allocations
if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &sqlEnvHandle))
goto COMPLETED;
if (SQL_SUCCESS != SQLSetEnvAttr(sqlEnvHandle, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0))
goto COMPLETED;
if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_DBC, sqlEnvHandle, &sqlConnHandle))
goto COMPLETED;
//output
cout << "Attempting connection to SQL Server...";
cout << "\n";
//connect to SQL Server
switch (SQLDriverConnect(sqlConnHandle,
NULL,
(SQLWCHAR*)L"Server=P2005\SQLEXPRESS2014;Database=CPPDB;User Id=myuid;Password=mypswd;",
SQL_NTS,
retconstring,
1024,
NULL,
SQL_DRIVER_NOPROMPT)) {
case SQL_SUCCESS:
cout << "Successfully connected to SQL Server";
cout << "\n";
break;
case SQL_SUCCESS_WITH_INFO:
cout << "Successfully connected to SQL Server";
cout << "\n";
break;
case SQL_INVALID_HANDLE:
cout << "Could not connect to SQL Server";
cout << "\n";
goto COMPLETED;
case SQL_ERROR:
cout << "Could not connect to SQL Server";
cout << "\n";
goto COMPLETED;
default:
break;
}
//if there is a problem connecting then exit application
if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_STMT, sqlConnHandle, &sqlStmtHandle))
goto COMPLETED;
//output
cout << "\n";
cout << "Executing T-SQL query...";
cout << "\n";
//if there is a problem executing the query then exit application
//else display query result
if (SQL_SUCCESS != SQLExecDirect(sqlStmtHandle, (SQLWCHAR*)L"SELECT ##VERSION", SQL_NTS)) {
cout << "Error querying SQL Server";
cout << "\n";
goto COMPLETED;
}
else {
//declare output variable and pointer
SQLCHAR sqlVersion[SQL_RESULT_LEN];
SQLINTEGER ptrSqlVersion;
while (SQLFetch(sqlStmtHandle) == SQL_SUCCESS) {
SQLGetData(sqlStmtHandle, 1, SQL_CHAR, sqlVersion, SQL_RESULT_LEN, &ptrSqlVersion);
//display query result
cout << "\nQuery Result:\n\n";
cout << sqlVersion << endl;
}
}
//close connection and free resources
COMPLETED:
SQLFreeHandle(SQL_HANDLE_STMT, sqlStmtHandle);
SQLDisconnect(sqlConnHandle);
SQLFreeHandle(SQL_HANDLE_DBC, sqlConnHandle);
SQLFreeHandle(SQL_HANDLE_ENV, sqlEnvHandle);
//pause the console window - exit when key is pressed
cout << "\nPress any key to exit...";
getchar();
return 0;
}
When I build and run the above code, It always gives "Could not connect to SQL Server".
SQL connection string is given below as,
"Server=P2005\SQLEXPRESS2014;Database=CPPDB;User Id=myuid;Password=mypswd;"
I got the above connection string format from this link.
And I'm using Microsoft SQL Server 2014 via SQL Management Studio.
Note : It always triggers the SQL_ERROR case in switch.
I'm trying to trace the error. But I didn't get any luck.
Why this occurs?
Any help would be appreciated.
Thanks.
This is a suggestion.
Try Visual C++ MFC Template.
Include belows.
//For CDatabase class
#include "odbcinst.h"
#include "afxdb.h"
//
Do below stuff anywhere you want.
CDatabase database;
CString SqlString;
CString strID, strName, strAge;
CString sDriver = L"ODBC Driver 11 for SQL Server";
CString sDsn;
int iRec = 0;
// Build ODBC connection string
sDsn.Format(L"ODBC;DRIVER={%s};DSN='';DBQ=%s;DATABASE=MYDBNAME", sDriver, NULL);
TRY{
// Open the database
database.Open(NULL,false,false,sDsn);
SqlString = "INSERT INTO MY_TABLE (id,name,age) VALUES (1,'Sanjaya',25)";
database.ExecuteSQL(SqlString);
// Close the database
database.Close();
}CATCH(CDBException, e) {
// If a database exception occured, show error msg
AfxMessageBox(L"Database error: " + e->m_strError);
}
END_CATCH;
You should create ODBC Datasource, and it should specify as "ODBC Driver 11 for SQL Server".
I'm using VS Community 2015 and SQL Server 2014.
just add a backslash in your instance name
P2005\SQLEXPRESS2014
P2005\\SQLEXPRESS2014

ODBC connection not open

I recently sent some working code from my laptop to my desktop. Even though they are both using the same tech (Visual studio community 15 and SQL Server 14) I am unable to connect to my database on the desktop.
I've got an identical ODBC driver on both (and have tried various combinations on my desktop). Whilst controlling the connection from the ODBC to SQL Server it seems fine, but when I run my application from the debugger I receive this error:
Message: [Microsoft][ODBC Driver Manager] Connection Not Open
SQLSTATE: 08003 Failed to connect
This is the code:
#include "stdafx.h"
#include <iostream>
#include <windows.h>
#include <sqltypes.h>
#include <sql.h>
#include <sqlext.h>
using namespace std;
void show_error(unsigned int handletype, const SQLHANDLE& handle)
{
SQLWCHAR sqlstate[1024];
SQLWCHAR message[1024];
if (SQL_SUCCESS == SQLGetDiagRec(handletype, handle, 1, sqlstate, NULL, message, 1024, NULL))
wcout << "Message: " << message << "\nSQLSTATE: " << sqlstate << endl;
}
int main() {
SQLHENV env;
SQLHDBC dbc;
SQLHSTMT stmt;
SQLRETURN ret;
SQLSMALLINT columns;
int row = 0;
/* 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 */
SQLDriverConnectW(dbc, NULL, L"DRIVER={SQL Server};ERA-PC-STUART\\JBK_DB;DATABASE=master;UID=geo;PWD=kalle123;", SQL_NTS, NULL, 0, NULL, SQL_DRIVER_COMPLETE);
/* Check for success */
if (SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt))
{
show_error(SQL_HANDLE_DBC, dbc);
std::cout << "Failed to connect";
}
if (SQL_SUCCESS != SQLExecDirectW(stmt, L"select salary from dbo.salary_table", SQL_NTS)) {
show_error(SQL_HANDLE_STMT, stmt);
}
else {
int id;
cout << "ID:" << endl;
while (SQLFetch(stmt) == SQL_SUCCESS) {
SQLGetData(stmt, 1, SQL_C_ULONG, &id, 0, NULL);
cout << id << endl;
}
}
return 0;
}
As mentioned the code runs flawlessly on my laptop, but for some reason it won't work on the desktop - even though the ODBC connects.
This might be probably due to windows version problem. Your laptop might be running on 64-bit os and your desktop might be running on 32 bit os. Create a new DSN on your desktop using 32-bit odbc data source administrator and try again.There is nothing wrong with the code
For people that might have this issue in the future; ensure that the TCP/IP is enabled in your SQL Server Configuration Manager.
In my case the above was disabled and the "Server=" was missing in the connection string.

Troubleshooting SQL Server connection in C++ using Visual Studio Express 2013

I've been trying to get a simple program together that can perform some simple operations on a SQL Server database, but can't get any of the tutorials to actually run. I'm trying to figure out if the problem is with the code or with my ODBC settings. Any help/insight is greatly appreciated.
EDIT/UPDATE: ADDITIONAL DETAIL & CODE BELOW
The main program right now is based on this tutorial. I had to make a few changes so that VS Express 2013 would compile the code:
All instances of SQLCHAR * had to be changed to SQLWCHAR *.Had to use wcout to output the error messagesThe 'GOTO: FINISHED' used in the tutorial generated errors that the objects might be uninitialized. I added an 'UNFIN' block after 'FINISHED' and changed those generating errors to GOTO UNFIN to make the compier happyAdded a few debugging markers to make sure I was following the program properlyChanged the connection string to match the server, username and password of the database I'm trying to connect to. Note: Target database uses SQLServer2008
On running the program, I get the following error message (generated by the show_error() function):
Messsage: [Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified
nSQLSTATE: IM002
Could it be something as simple as an ODBC setting that I need to toggle on my machine or a dependency I've missed in the project setup?
Here's the code. (Note that there are extra headers for other features being tested. Said other features are commented out in my current test program and deleted from the below copy-paste to reduce confusion)
#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;
}
EDIT/UPDATE:
Continuing to try and figure out where the error is. Using code based off the tutorial at EasySoft to get the list of DSN available feels a little bit like progress. Here's the updated program and result:
// 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 truncation\n");
}
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("Connected\n");
printf("Returned connection string was:\n\t%s\n", outstr);
if (ret == SQL_SUCCESS_WITH_INFO) {
printf("Driver reported the following diagnostics\n");
extract_error("SQLDriverConnect", dbc, SQL_HANDLE_DBC);
}
SQLDisconnect(dbc); /* disconnect from driver */
}
else {
fprintf(stderr, "Failed to connect\n");
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;
}
The program gives the following output. Error is the same for both 'EnglobalConn' and 'Englobal2'
SQL DATA SOURCES:
dBASE Files | Microsoft Access dBASE Driver (*dbf, *.ndx, *.mdx)
Excel Files | Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)
MS Access Database | Microsoft Access Driver (*.mdb, *.accdb)
Englobal2 | SQL Server
EnglobalConn | SQL Server
ATTEMPTING TO CONNECT TO DATA SOURCE USING:
DSN=EnglobalConn
Failed to connect
Message: [Miscrosoft][ODBC Driver Manager] Data source name not found and no default driver specified nSQLSTATE: IM002
One piece of advice I found while Googling was that a 64-bit Windows install has 2 ODBC sets, one in System32 and one in SysWOW64. I've run both and set the DSNs to be the same:
In C:\Windows\SysWOW64\odbcad32.exe:
User Data Sources: Englobal2 - SQL Server
System DSN: EnglobalConn - SQL Server
In C:\Windows\System32\odbcad32.exe:
User Data Sources: Englobal2 - SQL Server
System DSN: EnglobalConn - SQL Server
Hi I've struggled with exactly the same problem and exactly the same fail :)
(SQLWCHAR*)"DRIVER={SQL Server};SERVER=sqlserver.myhost.com, 1433;DATABASE=MyDatabase;UID=xxxxx;PWD=xxxxx",
Should be
(SQLWCHAR*)_T("DRIVER={SQL Server};SERVER=sqlserver.myhost.com, 1433;DATABASE=MyDatabase;UID=xxxxx;PWD=xxxxx"),
or
(SQLWCHAR*)TEXT("DRIVER={SQL Server};SERVER=sqlserver.myhost.com, 1433;DATABASE=MyDatabase;UID=xxxxx;PWD=xxxxx"),
Hooray! Found a solution that works:
Using the library http://otl.sourceforge.net/ (Designed for use with Oracle, but also works to connect to 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;
}