Excute create table in SQL Server with C++ - c++

I am trying to create a table in SQL Server with following code:
#include <iostream>
#include <windows.h>
#include <string>
#include <sql.h>
#include <sqltypes.h>
#include <sqlext.h>
using namespace std;
void main()
{
SQLHANDLE sqlevent, sqlconnection, sqlstatement;
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &sqlevent);
SQLSetEnvAttr(sqlevent, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0);
SQLAllocHandle(SQL_HANDLE_DBC, sqlevent, &sqlconnection);
SQLCHAR retstring[10000];
SQLDriverConnect(sqlconnection, NULL, (SQLCHAR*)("DRIVER={SQL Server Native Client 10.0};SERVER=SERVER;DATABASE=DATABASE;UID=CrystalReports;PWD=PASSWORD"), SQL_NTS, retstring, 10000, NULL, SQL_DRIVER_NOPROMPT);
SQLAllocHandle(SQL_HANDLE_STMT, sqlconnection, &sqlstatement);
string commandline;
commandline = "CREATE TABLE NEW_TABLE01(Name VARCHAR(10), Age INT, Salary DOUBLE PRECISSION)";
if(SQL_SUCCESS != SQLExecDirect(sqlstatement, (SQLCHAR*)(commandline.c_str()), SQL_NTS)) // SQLExecDirect always failed to excute
{
cout<<"The create table sql command hasn't been excuted successfully."<<endl;
return;
}
return;
}
However, the code if(SQL_SUCCESS != SQLExecDirect(sqlstatement, (SQLCHAR*)(commandline.c_str()), SQL_NTS)) always return a TRUE, which means the SQL command was not sucessfully excuted.
I've got all the permission to create a table, and I've check the SQL command in SQL server manually, and it works.
May I know what am I wrong? And how can I achieve my goal?
Many thanks in advance.

I think I've got answer since inspired by C++ SQL Database program
I realised that there are different schemas in SQL Server, thus I use CREATE TABLE [ROU].[NEW_TABLE01] instead. Now my code works well.

Related

Very long query execution using C++, Sql Server and ODBC connection

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.

What is segmentation fault in C++ mysql?

I am using C++ to send MySQL commands to a server. Why does it say "Segmentation fault" and what does it mean?
The output of the program when I run it is:
connection Succeeded
Segmentation fault
Edited the code to remove the i+1 line but still having same problem
the code:
#include <stdlib.h>
#include <iostream>
#include <mysql.h>
#include <stdio.h>
#define SERVER "localhost"
#define USER "root"
#define PASSWORD "coursework"
int main()
{
MYSQL *connect;
connect=mysql_init(NULL);
if (!connect)
{
std::cout<<"MySQL Initialization failed";
return 1;
}
connect=mysql_real_connect(connect, SERVER, USER, PASSWORD, NULL ,0,NULL,0);
if (connect)
{
std::cout<<"connection Succeeded\n";
}
else
{
std::cout<<"connection failed\n";
exit(1);
}
mysql_query (connect, "drop database if exists TTU;");
mysql_query (connect,"create database TTU;");
mysql_query (connect, "use TTU;");
mysql_query (connect, "create table students(tnumber char(8) PRIMARY KEY,");
mysql_query (connect, "firstname varchar(20) NOT NULL,");
mysql_query (connect, "lastname varchar(20) NOT NULL,");
mysql_query (connect, "dateofbirth date,");
mysql_query (connect, "INDEX 'lastname_i' ('lastname'),");
mysql_query (connect, "ENGINE=INNODB);");
mysql_query (connect, "insert into students(tnumber, firstname, lastname, dateofbirth)");
mysql_query (connect, "values (00001234, Joe, Smith, 1950-08-12);");
MYSQL_RES *res_set;
MYSQL_ROW row;
mysql_query (connect,"select * from students;");
unsigned int i =0;
res_set = mysql_store_result(connect);
unsigned int numrows = mysql_num_rows(res_set);
while ((row= mysql_fetch_row(res_set)) != NULL )
{
std::cout << row[i] << std::endl;
}
mysql_close (connect);
std::cout << "TEST" << std::endl;
return 0;
}
There are multiple bugs in the shown code. There are two major bugs: Incorrect usage of mysql_query(), and repeated failures to check the return value from various MySQL library functions, resulting in a failure to detect various errors.
mysql_query (connect, "create table students(tnumber char(8) PRIMARY KEY,");
This is not valid SQL. mysql_query() takes a complete SQL statement and executes it. It doesn't take individual fragments of an SQL statement, broken down across multiple consecutive invocations, and only executes it once a complete SQL statement gets parsed.
Because the shown code fails to check the return value from mysql_query(), it fails to detect that this whole sequence of mysql_query() calls have failed, and the table did not get created.
Subsequent call also fails to check the return value from other MySQL library functions.
The shown code is likely getting a NULL back from mysql_store_result(), fails to check for it, passes a NULL pointer to mysql_num_rows(), and crashes.

C++ SQLExecDirect INSERT doesn't work

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

Upload .csv to SQL server using C++

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

Process utf-8 data from MySQL in C++ and give result back

I just simply want to know - how to get MySQL results to C++ in string (or another similar "string" datatype) in a way that would not deform data saved in utf8_unicode_ci.
After C++ process, app should write results back (to another table) into the database where argument is encoded in utf8_unicode_ci as well.
I read somewhere that using wide char is not recommended by Unicode consortium, but my problem is still that a second argument for mysql_query() is string which is not wide enough.
I've already tried some "utf8 string" solutions, but unsuccessfully. I also tried to save data in common string and than write it into the database in the same way (byte after byte), but it doesn't work properly at all... (see my code below)
DATABASE:
save_text: text = ěščřžýáíé
AFTER PROCESS: save_newtext: text = ?š??žýáíé
#include <iostream>
#include <mysql.h>
#include <string>
#define ... // server conection
using namespace std;
MYSQL *connection, mysql;
MYSQL_RES *result;
MYSQL_ROW row;
int query_state;
int main(int argc, char** argv)
{
mysql_init(&mysql);
mysql_real_connect(&mysql,CTH_SERVER,CTH_USER,CTH_PASSWORD,CTH_DB_IN,0,0,0));
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "utf8");
mysql_options(&mysql, MYSQL_INIT_COMMAND, "SET NAMES utf8");
mysql_query(connection, "SELECT text FROM save_text WHERE id = 23");
result = mysql_store_result(connection);
if ((row = mysql_fetch_row(result)) != NULL) {
string sql;
sql = "INSERT INTO save_newtext (text) VALUES ('";
sql += row[0];
sql += "')";
mysql_query(connection, sql.c_str());
}
return 0;
}
Thanks in advance!!
From MySQL Reference
mysql_options() should be called after mysql_init() and before
mysql_connect() or mysql_real_connect().
So your code should be
mysql_init(&mysql);
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "utf8");
mysql_options(&mysql, MYSQL_INIT_COMMAND, "SET NAMES utf8");
mysql_real_connect(&mysql,CTH_SERVER,CTH_USER,CTH_PASSWORD,CTH_DB_IN,0,0,0));