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.
Related
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 ? :-)
I'm using the following code to connect to a sql-server database. I can run all other queries with no difficulties using the same function. However, one query executes in Sql management studio and in R using RODBC in ~11 seconds but takes over an hour (at the "SQLExecDirect" function) using c++. Has anyone else had this issue and how did you resolve it?
std::string sqlQuery="[myquery]";
SQLHANDLE sqlconnectionhandle;
SQLAllocHandle(SQL_HANDLE_DBC, sqlenvhandle, &sqlconnectionhandle);
SQLCHAR retconstring[1024];
SQLDriverConnect (sqlconnectionhandle, NULL,
conn_str,
len, retconstring, 1024, NULL,SQL_DRIVER_NOPROMPT);
SQLHANDLE sqlstatementhandle;
SQLAllocHandle(SQL_HANDLE_STMT, sqlconnectionhandle, &sqlstatementhandle);
//this is where the program "hangs" for over an hour
if(SQL_SUCCESS!=SQLExecDirect(sqlstatementhandle, (SQLCHAR*)(sqlQuery.c_str()), SQL_NTS)){
show_error(SQL_HANDLE_STMT, sqlstatementhandle, errorMsg);
return;
}
int numRow=0;
while(SQLFetch(sqlstatementhandle)==SQL_SUCCESS){
for(int i=1; i<=numFields+1; ++i){
double myVal;
SQLGetData(sqlstatementhandle, i, SQL_C_DOUBLE, &myVal, 0, NULL);
cb(myVal, numRow, i-1); //callback function defined elsewhere
}
numRow++;
}
SQLFreeHandle(SQL_HANDLE_STMT, sqlstatementhandle );
SQLDisconnect(sqlconnectionhandle);
SQLFreeHandle(SQL_HANDLE_DBC, sqlconnectionhandle);
That is because the ArithAbort property on your database is off.
See also http://www.sommarskog.se/query-plan-mysteries.html
You can check it and correct it with this small script
declare #value sql_variant
select #value = SESSIONPROPERTY('ARITHABORT')
if #value <> 1
begin
USE master
ALTER DATABASE [your_database] SET ARITHABORT ON WITH NO_WAIT
use your_database
end
I figured this out: my connection string's default database was different than the one that I had as the default database in SSMS. Switching this made the query run in the same speed as SSMS.
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
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.
I am working with Visual Studio 2012 Express version under Windows 7. On the other hand, the SQL server is "SQL Server 2008 R2".
I've tried following C++ codes:
#include <iostream>
#include <windows.h>
#include <string>
#include <sql.h>
#include <sqltypes.h>
#include <sqlext.h>
using namespace std;
void main()
{
clock_t start = clock();
SQLHANDLE sqlevent, sqlconnection, sqlstatement;
if(SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &sqlevent))
{
cout<<"The sqlevent has failed to be created."<<endl;
system("pause");
return;
}
if(SQL_SUCCESS != SQLSetEnvAttr(sqlevent, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0))
{
cout<<"The sqlevent has failed to be initialized."<<endl;
system("pause");
return;
}
if(SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_DBC, sqlevent, &sqlconnection))
{
cout<<"The sqlconnection has failed to be created."<<endl;
system("pause");
return;
}
SQLCHAR retstring[10000];
SQLDriverConnect(sqlconnection, NULL, (SQLCHAR*)("DRIVER={SQL Server Native Client 10.0};SERVER=DATASERVER;DATABASE=DATABASE;UID=CrystalReports;PWD=PASSWORD"), SQL_NTS, retstring, 10000, NULL, SQL_DRIVER_NOPROMPT);
if(SQL_SUCCESS != SQLAllocHandle(SQL_HANDLE_STMT, sqlconnection, &sqlstatement))
{
cout<<"The sqlstatement has failed to be created."<<endl;
system("pause");
return;
}
string commandline;
commandline = "CREATE TABLE NEW_TABLE ( ID VARCHAR(10), AGE FLOAT) GO ";
if(SQL_SUCCESS != SQLExecDirect(sqlstatement, (SQLCHAR*)(commandline.c_str()), SQL_NTS))
{
cout<<"The create table sql command has failed to excute."<<endl;
system("pause");
return;
}
commandline = "BULK INSERT NEW_TABLE FROM 'C:/temp/datafile.csv' WITH ( FIELDTERMINATOR = ',', ROWTERMINATOR = '\n') GO";
if(SQL_SUCCESS != SQLExecDirect(sqlstatement, (SQLCHAR*)(commandline.c_str()), SQL_NTS))
{
cout<<"The import sql command has failed to excute."<<endl;
system("pause");
return;
}
clock_t end = clock();
cout<<"Import from .csv file to SQL Server costs "<<((end-start)/double(CLOCKS_PER_SEC))<<" seconds."<<endl;
system("pause");
return;
}
When I run this code, the program always stops at create table.
I wonder if I don't have the permission to create a table, thus I mannually created a table. And there is a warning pops out:
May I know if the warning shown in the above image is the reason my code fail, or I simply made mistakes in the code?
Many thanks.
Who owns the database? You need to find your database administrator and get them to grant you permission to add tables to the database.
You may want to check what permissions that account has been GRANTED.
You will need permissions to INSERT as well as to BULKADMIN server role.
But as you can see in this post it can get hairy depending on where the file is located. You can at