Reputation: 36
This is for homework, so I understand if you don't want to just give me the answer. That being said, if you do decide to "give" me anything, please explain what it does, and why, and how, because, to be perfectly honest, I'm in an online program and the teacher/class style is very unhelpful. I.E. When we ask for help, we just get a link to the MSDN main page and are told to figure it out. (PS: if anyone ever considers going to 'City University' for a MS in CS: don't).
I've been working on this 1 problem for over 30 hours now, and searched high and low on this website and many others, and have been coming up with not much to show for it. Any help, explanations, tips, etc, would be greatly appreciated.
The assignment is to take user input in a C++/CLI console app, connect it to a mySQL database via ODBC32, and run a loop asking for user choice about which table to pull up and display. I have done the loop, I have gotten the db connected (I think/hope), but I can't seem to convert the users choice into a valid SQL query, or maybe it's just a display issue. Since I am quite literally teaching myself, I have to admit that I don't really know if this is where the true root of the problem lies, or if I have grossly misunderstood what this code is and does.
My current code:
#include "stdafx.h"
#include <string>
#include <sql.h>
#include <sqlext.h>
#pragma comment( lib, "odbc32.lib" )
#define EMPLOYEE_ID_LEN 32
SQLHENV henv = NULL;
SQLHDBC hdbc = NULL;
SQLRETURN retcode;
SQLHSTMT hstmt = NULL;
SQLSMALLINT sCustID;
SQLCHAR szEmployeeID[EMPLOYEE_ID_LEN];
SQL_DATE_STRUCT dsOrderDate;
SQLINTEGER cbCustID = 0, cbOrderDate = 0, cbEmployeeID = SQL_NTS;
int main()
{
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3, 0);
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
retcode = SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
retcode = SQLConnect(hdbc, (SQLWCHAR*) "MySqlWorld", SQL_NTS, (SQLWCHAR*)NULL, 0, NULL, 0);
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
bool boolExit = false;
while (boolExit == false)
{
String^ strChoice = "";
do {
if (strChoice == "a")
{
strChoice = "city";
break;
}
else if (strChoice == "b")
{
strChoice = "country";
break;
}
else if (strChoice == "c")
{
strChoice = "countrylanguage";
break;
}
else if (strChoice == "e")
{
boolExit = true;
break;
}
else
{
Console::WriteLine();
Console::WriteLine("Please choose from the following options:");
Console::WriteLine("A: Enter last name to retreive first name, home address, and work phone number.");
Console::WriteLine("B: Enter last name to retrieve department.");
Console::WriteLine("C: Enter department to retrieve list of employee last names, addresses, and work phone numbers for members of that department.");
Console::WriteLine("E: Exit");
strChoice = Console::ReadLine()->ToLower();
}
} while (true);
if (boolExit == false)
{
char* cstrTempQuery = (char*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(strChoice);
SQLCHAR sqlTempQuery[32];
strcpy_s((char*)sqlTempQuery, _countof(sqlTempQuery), (const char *)cstrTempQuery);
retcode = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, EMPLOYEE_ID_LEN, 0, sqlTempQuery, 0, &cbEmployeeID);
retcode = SQLPrepare(hstmt, (SQLWCHAR*)"SELECT * from ?", SQL_NTS);
retcode = SQLExecute(hstmt);
}
} // end while (boolExit == false)
} // end main()
The code results in no errors of any sort, but doesn't do anything. My loop shows, I make a selection, and nothing happens, except that the loop repeats.
I got most of this code from this page: https://learn.microsoft.com/en-us/sql/odbc/reference/syntax/sqlbindparameter-function
Upvotes: 0
Views: 191
Reputation: 5615
You cannot bind tablename or field name parameters. You can dynamically construct the query using using curly braces. It is not advised but possible with this: https://stackoverflow.com/a/11327831/5389997
Something similar to : SELECT * FROM {$mytable}
Since you're specifying your tables that you need then you don't have to worry so much about the SQL injection angle.
It also looks like you're not updating the boilerplate code to have your variables.
#include "stdafx.h"
#include <string>
#include <sql.h>
#include <sqlext.h>
#pragma comment( lib, "odbc32.lib" )
#define QUERY_LEN 32
SQLHENV henv = NULL;
SQLHDBC hdbc = NULL;
SQLRETURN retcode;
SQLHSTMT hstmt = NULL;
SQLCHAR szQueryVar[QUERY_LEN];
SQLCHAR queryVar = SQL_NTS;
int main()
{
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3, 0);
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
retcode = SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
retcode = SQLConnect(hdbc, (SQLWCHAR*) "MySqlWorld", SQL_NTS, (SQLWCHAR*)NULL, 0, NULL, 0);
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
bool boolExit = false;
while (boolExit == false)
{
String^ strChoice = "";
String^ tableName = "";
String^ queryField = "";
String^ queryVar = "";
do {
if (strChoice == "a")
{
tableName = "address";
queryField = "last_name";
queryVar = Console::ReadLine();
break;
}
else if (strChoice == "b")
{
tableName = "department";
queryField = "last_name";
queryVar = Console::ReadLine();
break;
}
else if (strChoice == "c")
{
tableName = "department";
queryField = "department";
queryVar = Console::ReadLine();
break;
}
else if (strChoice == "e")
{
boolExit = true;
break;
}
else
{
Console::WriteLine();
Console::WriteLine("Please choose from the following options:");
Console::WriteLine("A: Enter last name to retreive first name, home address, and work phone number.");
Console::WriteLine("B: Enter last name to retrieve department.");
Console::WriteLine("C: Enter department to retrieve list of employee last names, addresses, and work phone numbers for members of that department.");
Console::WriteLine("E: Exit");
strChoice = Console::ReadLine()->ToLower();
}
} while (true);
if (boolExit == false)
{
char* cstrTempQuery = (char*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(strChoice);
SQLCHAR sqlTempQuery[32];
strcpy_s((char*)sqlTempQuery, _countof(sqlTempQuery), (const char *)cstrTempQuery);
retcode = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, QUERY_LEN, 0, sqlTempQuery, 0, &queryVar);
query = (SQLCHAR*)"SELECT * from {$tableName} where {$queryField} = ?";
retcode = SQLPrepare(hstmt, queryVar, SQL_NTS);
retcode = SQLExecute(hstmt);
}
} // end while (boolExit == false)
} // end main()
Upvotes: -1