C++ SQLExecDirect INSERT doesn't work - c++

I've wrote a simple SQL C++ Wrapper-Class, where I encountered a real strange Problem. When I call an INSERT-Command with SQLExecDirect, the data does not appear in the SQL Database (SQL Server 2012), although SQLRowCount returns one row. The table, which I'm trying to write to, is named "Person" and has four columns (ID (AUTOINCREMENT), Firstname (nvarchar(100)), Lastname (nvarchar(100)), Birthday (date))
Here is my code:
Class-Constructor (EnvHandle, DBCHandle and StmtHandle are class-members)
SQLDatabase::SQLDatabase()
{
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &EnvHandle);
SQLSetEnvAttr(EnvHandle, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);
SQLAllocHandle(SQL_HANDLE_DBC, EnvHandle, &DBCHandle);
SQLSetConnectAttr(DBCHandle, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_OFF, SQL_IS_INTEGER);
}
Query-Member-Function
int SQLDatabase::ExecuteNonQuery(std::wstring Command)
{
SQLRETURN RetCode = -1;
SQLINTEGER RowCount = 0;
SQLAllocHandle(SQL_HANDLE_STMT, DBCHandle, &StmtHandle);
RetCode = SQLExecDirect(StmtHandle, (SQLWCHAR*)Command.c_str(), Command.length());
if (RetCode == SQL_SUCCESS || RetCode == SQL_SUCCESS_WITH_INFO)
{
SQLRowCount(StmtHandle, &RowCount);
SQLFreeHandle(SQL_HANDLE_STMT, StmtHandle);
return RowCount;
}
else
{
SQLFreeHandle(SQL_HANDLE_STMT, StmtHandle);
return -1;
}
}
Function-Call in main.cpp
wcout << "Firstname:\n>";
wcin >> Firstname;
wcout << "Lastname:\n>";
wcin >> Lastname;
wcout << "Birthday:\n>";
wcin >> Birthday;
InsRows = database.ExecuteNonQuery(L"INSERT INTO Person (Firstname,Lastname,Birthday) VALUES ('" + Firstname + L"','" + Lastname + L"','" + Birthday + L"')");
if (InsRows == -1)
database.Error();
else
std::wcout << InsRows << " rows affected!" << std::endl;
As already said, "database.ExecuteNonQuery" returns one row.
When take a look at the table in SQL Management Studio, the datarow hasn't been added. I've already traced the queries on the table. The query appears in the tracelog correctly without any additional info. My IDE is Visual Studio 2013.
Any ideas how I could get the data into the table?
Thanks!
Sebastian

In general, whenever a query is executed that changes a table (without error) and the results are not shown, this means that the changes were not committed.
Looking at your code, you have this:
SQLSetConnectAttr(DBCHandle, SQL_ATTR_AUTOCOMMIT,
(SQLPOINTER)SQL_AUTOCOMMIT_OFF, SQL_IS_INTEGER);}
You set the connection attribute to have auto commit turned off. Either specify you want auto commit on, or issue a call to SQLEndTran to commit the changes.

You're using SQL_AUTOCOMMIT_OFF, which means your statements won't be automatically committed, so your new record is visible only in your transaction and will never be committed in the database. Try to use the auto-commit feature of the MS SQL Server (setting SQL_ATTR_AUTOCOMMIT to SQL_AUTOCOMMIT_ON or just leave it uninformed since it's the default behaviour) or explicitly begin and commit your transaction.
http://msdn.microsoft.com/en-us/library/ms713605(v=vs.85).aspx

Related

Dynamic SQL Query with C++

Im working on a program that are accessing a SQL server.
I've established the connection, and i can get the stand i want, but only when my SQL Query is static.
I've read a post in here, where the same question was asked, tried his solution, which sadly didn't work (8 years old post also).
The function used to gain the Query is the following:
SQLWCHAR ConstructQuery()
{
wstring temp = L"SELECT Something FROM somewhere WHERE condition";
SQLWCHAR statement = (SQLWCHAR)temp.c_str();
return statement;
}
and my code for running this query is as follows:
SQLStatement = ConstructQuery();
SQLExecDirect(sqlStmtHandle,&SQLStatement, SQL_NTS))
SQLCHAR sqldata[SQL_RESULT_LEN];
SQLINTEGER ptrsqldata;
while (SQLFetch(sqlStmtHandle) == SQL_SUCCESS) {
SQLGetData(sqlStmtHandle, 1, SQL_CHAR, sqldata, SQL_RESULT_LEN, &ptrsqldata);
//display query result
cout << "\nQuery Result:\n\n";
cout << sqldata << endl;
}
The code runs, but i dont get any output.
Does anyone has any advice ? :-)

How does prepared statements in Sqlite C++ work

I do not know how to implement prepared statements in my Sqlite3 code
#include <iostream>
#include <sqlite3.h>
#include <stdio.h>
static int callback (void* NotUsed, int argc, char** argv, char** azColName) {
int i;
for (i = 0; i < argc; i++) {
std::cout << ("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
std::cout << ("\n");
return 0;
}
int main (int argc, char* argv[]) {
sqlite3* db;
char* zErrMsg = 0;
int rc;
char* sql;
/* Open database */
rc = sqlite3_open ("test.db", &db);
if (rc) {
std::cerr << "Can't open database: \n" << sqlite3_errmsg (db);
return (0);
}
else {
std::cout << "Opened database successfully\n";
}
std::string newName;
std::cin >> newName;
/* Create SQL statement */
sql = "UPDATE company SET name = newName WHERE id = 1";
/* Execute SQL statement */
rc = sqlite3_exec (db, sql, callback, 0, &zErrMsg);
if (rc != SQLITE_OK) {
std::cout << "SQL error: \n" << zErrMsg;
sqlite3_free (zErrMsg);
}
else {
std::cout << "Records created successfully\n";
}
sqlite3_close (db);
return 0;
}
The user has to input newName and this variable should be used to Update a field in the Database. This way it does not work, because the Sql script is searching for a column. In the internet I found, that I had to use a prepared statement, but I do not know how to implement it.
You start with an sql statement that has placeholders for the parameters that you wish to bind later. Here, I use a single question mark for the placeholder, but there are other options described in the documentation.
std::string sql = "UPDATE company SET name = ? WHERE id = 1";
Then you construct a prepared statement (or "compile", as they say it in sqlite documentation). You'll normally use sqlite_prepare_v2 function, but there are others (for when your statement is encoded in something else than utf-8, for example).
sqlite3_stmt* stmt; // will point to prepared stamement object
sqlite3_prepare_v2(
db, // the handle to your (opened and ready) database
sql.c_str(), // the sql statement, utf-8 encoded
sql.length(), // max length of sql statement
&stmt, // this is an "out" parameter, the compiled statement goes here
nullptr); // pointer to the tail end of sql statement (when there are
// multiple statements inside the string; can be null)
Then you bind the parameter(s). There's a whole bunch of avaliable functions. Which one exactly you use depends on the type
of data that you're binding to the parameter. Here, we bind text, so we use sqlite3_bind_text:
std::string newName = /* get name from user */;
sqlite3_bind_text(
stmt, // previously compiled prepared statement object
1, // parameter index, 1-based
newName.c_str(), // the data
newName.length(), // length of data
SQLITE_STATIC); // this parameter is a little tricky - it's a pointer to the callback
// function that frees the data after the call to this function.
// It can be null if the data doesn't need to be freed, or like in this case,
// special value SQLITE_STATIC (the data is managed by the std::string
// object and will be freed automatically).
So, the prepared statement is ready to go. Now you execute it by passing it to sqlite3_step:
sqlite3_step(stmt); // you'll want to check the return value, read on...
Now, when you step through a statement that's supposed to return rows of a result table, this function will keep returning SQLITE_ROW as long as there are result rows to process, and SQLITE_DONE when there are none left. You can use sqlite3_column_* family of functions to get the single columns from a result row. I'll let you figure this out on your own.
For a simple update statements that you have, sqlite3_step will return SQLITE_DONE on the first call. More info and possible error codes are here.
When it's all done, you finish by destructing the prepared statement.
sqlite3_finalize(stmt);
I hope this should get you started.

SQLExecDirect command is not working same queries

I'm working Visual Studio 2017 and SQL Server 2017 .
I want to do is create a query with C ++ and that will run it on SQL Server.
if (SQL_SUCCESS != SQLExecDirect(sqlStmtHandle, (SQLWCHAR*)L"SELECT ##VERSION", SQL_NTS)) {
cout << "Database Already Exits or Cannot Created";
cout << "\n";
goto COMPLETED;
}
else {
cout << "Success !!!";
cout << "\n";
}
I use this sample : https://www.techhowtos.com/programming/how-to-connect-to-sql-server-from-visual-c-plus-plus/
But ,
if (SQL_SUCCESS != SQLExecDirect(sqlStmtHandle, (SQLWCHAR*)L"SELECT ##VERSION", SQL_NTS))
on this line , if i'm write
if (SQL_SUCCESS != SQLExecDirect(sqlStmtHandle, (SQLWCHAR*)L"**USE database_name**", SQL_NTS))
or
if (SQL_SUCCESS != SQLExecDirect(sqlStmtHandle, (SQLWCHAR*)L"**SELECT * FROM sampletable**", SQL_NTS))
or
if (SQL_SUCCESS != SQLExecDirect(sqlStmtHandle, (SQLWCHAR*)L"INSERT INTO sampletable (one,two,three) VALUES (1,2,3)", SQL_NTS))
this query is not working .
But ,
if i'm running this queries (some sample) ;
if (SQL_SUCCESS != SQLExecDirect(sqlStmtHandle, (SQLWCHAR*)L"**CREATE DATABASE blablabla**", SQL_NTS))
or
if (SQL_SUCCESS != SQLExecDirect(sqlStmtHandle, (SQLWCHAR*)L"**DELETE DATABASE blablabla**", SQL_NTS))
Queries are working .
i have a 2 function
void run_query(string query);
void create_query();
create query function working is normally . generate a query and this query goes to run_query .
What should I do in the run_query() function so that every created query works?
My all codes in here : https://paste.laravel.io/7c693fdb-2dc9-41cc-b183-6e45fd3d9b6d
Thanks for everything :)
SQLExecDirect can return values besides SQL_SUCCESS when the statement succeeds. For example, USE will normally return SQL_SUCCESS_WITH_INFO to indicate the statement succeeded and that informational/warning messages ("changed database context") were returned. Messages can be retrieved with SQLGetDiagRec if desired.
I suggest you consider at least all the "happy path" ODBC function call return values and handle each appropriately, raising an exception with diagnostic information when an unexpected value is returned.

sqlite - delete and get all values of some column from affected rows [duplicate]

I heard of using sqlite3_prepare_v2 instead of sqlite_exec to get integers from database, but I failed to find any examples. This page wasn't helpful also. Now I am getting strings from database, so I need to parse them with atoi and this seems to be slow and ineffective.
There a lot of similar questions on SO, but they are about obj-c and iOS SDK. I need C/C++ hint or example.
Thanks in advance.
After sqlite3_prepare has succeeded, you must not forget to clean up the statement with sqlite3_finalize.
To get the result records, call sqlite3_step until it does not return SQLITE_ROW.
To get the values of the current result record, call the sqlite3_column_* functions:
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(db, "SELECT 42", -1, &stmt, NULL) != SQLITE_OK)
...error...
else {
for (;;) {
int rc = sqlite3_step(stmt);
if (rc == SQLITE_DONE)
break;
if (rc != SQLITE_ROW) {
...error...
break;
}
printf("value: %d\n", sqlite3_column_int(stmt, 0));
}
sqlite3_finalize(stmt);
}
sqlite3_column_int(result, columnNum); will return one column from the current row of your result as an int.
Your prepare function is to prepare your query, it has nothing to do with how the results are interpreted. All data in sqlite3 is stored textually, you use the appropriate function to retrieve a value in the type you believe it should be.

Getting int values from SQLite

I heard of using sqlite3_prepare_v2 instead of sqlite_exec to get integers from database, but I failed to find any examples. This page wasn't helpful also. Now I am getting strings from database, so I need to parse them with atoi and this seems to be slow and ineffective.
There a lot of similar questions on SO, but they are about obj-c and iOS SDK. I need C/C++ hint or example.
Thanks in advance.
After sqlite3_prepare has succeeded, you must not forget to clean up the statement with sqlite3_finalize.
To get the result records, call sqlite3_step until it does not return SQLITE_ROW.
To get the values of the current result record, call the sqlite3_column_* functions:
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(db, "SELECT 42", -1, &stmt, NULL) != SQLITE_OK)
...error...
else {
for (;;) {
int rc = sqlite3_step(stmt);
if (rc == SQLITE_DONE)
break;
if (rc != SQLITE_ROW) {
...error...
break;
}
printf("value: %d\n", sqlite3_column_int(stmt, 0));
}
sqlite3_finalize(stmt);
}
sqlite3_column_int(result, columnNum); will return one column from the current row of your result as an int.
Your prepare function is to prepare your query, it has nothing to do with how the results are interpreted. All data in sqlite3 is stored textually, you use the appropriate function to retrieve a value in the type you believe it should be.