I would like to print my sql table contents and for that reason, I would like to retrieve the column name from the table. One solution I came across was :
SELECT sql FROM sqlite_master WHERE tbl_name = 'table_name' AND type = 'table'
But looks like I will have to parse the results.
Another suggestion was to use:
PRAGMA table_info(table_name);
but the below sqlite page suggests not to use this :
http://www.sqlite.org/pragma.html#pragma_full_column_names
Does there exists any way to achieve this. Also what would be the syntax to use
PRAGMA table_info(table_name);
Above solutions have been taken from here
Since your question is tagged c I assume you have access to the SQLite C API. If you create a prepared statement with one of the prepare_v2 functions that selects from the table you want you can use sqlite3_column_name to get the name of each column.
You can safely use PRAGMA table_info(table-name); since it's not deprecated in any way (yours post links to another pragma).
int sqlite3_get_table(
sqlite3 *db, /* An open database */
const char *zSql, /* SQL to be evaluated */
char ***pazResult, /* Results of the query */
int *pnRow, /* Number of result rows written here */
int *pnColumn, /* Number of result columns written here */
char **pzErrmsg /* Error msg written here */
);
If you are using c/c++, you can use the function sqlite3_get_table(db, query, result, nrow, ncol, errmsg);
Make the query as select * from table;
And the first few results result[0], result[1]...... will have the column names.
This setting will toggle showing column names as part of the return for select statements:
.headers on
Related
I'm working in c++ with SQLite, where I need to do some SELECT over a database. The problem is that the SELECT statement is one of the types
SELECT * FROM TABLE; //Unknown data type of columns
SELECT A,B FROM TABLE;//Unknown data type of columns
Where I don't know the types of the columns, but I need to store the retrieved values in corresponding c++ variables with a specific type. So the problem is that I don't know how to get the column data type of the result set given by the SQL SELECT statement after run the sqlite3_step to get the first result set.
In the code I have
//Prepare the statement
rc=sqlite3_prepare_v2
(
connection.database_handle,/* Database handle */
sql_command.c_str(), /* SQL statement, UTF-8 encoded */
sql_command.size(), /* Maximum length of zSql in bytes. */
&sql_statement_handle, /* OUT: Statement handle */
NULL /* OUT: Pointer to unused portion of zSql */
);
if(rc!=SQLITE_OK)
{
return -1;
}
To prepare the select command (in this case "SELECT * FROM TABLE;"), then I have the following to know the total columns in the result set
//Get the total number of columns
stmt_columns=sqlite3_column_count(sql_statement_handle);
if(stmt_columns<=0)
{
return -1;
}
sqlite_column_types=new int[stmt_columns];
After that iterating over the stmt_columns I have
sqlite_column_type=sqlite3_column_type(sql_statement_handle,i);
sqlite_column_types[i]=sqlite_column_type;
In order to retrieve the columns types. But the result is always the NULL data type which has no sense in this case. I tried running first the SQLite function sqlite3_step and then running the function sqlite3_column_type to get the columns type but the behavior is the same. So the question is how to know the columns data type of a SELECT command result set where I don't know in advance the columns types of the table or the query?
I generate a list of ID numbers. I want to execute an insert statement that grabs all records from one table where the ID value is in my list and insert those records into another table.
Instead of running through multiple execute statements (as I know is possible), I found this cx_Oracle function, that supposedly can execute everything with a single statement and list parameter. (It also avoids the clunky formatting of the SQL statement before passing in the parameters) But I think I need to alter my list before passing it in as a parameter. Just not sure how.
I referenced this web page:
https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-executemany.html
ids = getIDs()
print(ids)
[('12345',),('24567',),('78945',),('65423',)]
sql = """insert into scheme.newtable
select id, data1, data2, data3
from scheme.oldtable
where id in (%s)"""
cursor.prepare(sql)
cursor.executemany(None, ids)
I expected the SQL statement to execute as follows:
Insert into scheme.newtable
select id, data1, data2, data3 from scheme.oldtable where id in ('12345','24567','78945','65423')
Instead I get the following error:
ORA-01036: illegal variable name/number
Edit:
I found this StackOverflow: How can I do a batch insert into an Oracle database using Python?
I updated my code to prepare the statement before hand and updated the list items to tuples and I'm still getting the same error.
You use executemany() for batch DML, e.g. when you want to insert a large number of values into a table as an efficient equivalent of running multiple insert statements. There are cx_Oracle examples discussed in https://blogs.oracle.com/opal/efficient-and-scalable-batch-statement-execution-in-python-cx_oracle
However what you are doing with
insert into scheme.newtable
select id, data1, data2, data3
from scheme.oldtable
where id in (%s)
is a different thing - you are trying to execute one INSERT statement using multiple values in an IN clause. You would use a normal execute() for this.
Since Oracle keeps bind data distinct from SQL, you can't pass in multiple values to a single bind parameter because the data is treated as a single SQL entity, not a list of values. You could use %s string substitution syntax you have, but this is open to SQL Injection attacks.
There are various generic techniques that are common to Oracle language interfaces, see https://oracle.github.io/node-oracledb/doc/api.html#sqlwherein for solutions that you can rewrite to Python syntax.
using temporary table to save ids (batch insert)
cursor.prepare('insert into temp_table values (:1)')
dictList = [{'1': x} for x in ids]
cursor.executemany(None, dictList)
then insert selected value into newtable
sql="insert into scheme.newtable (selectid, data1, data2, data3 from scheme.oldtable inner join temp_table on scheme.oldtable.id = temp_table.id)"
cursor.execut(sql,connection)
the script of create temporary table in oracle
CREATE GLOBAL TEMPORARY TABLE temp_table
(
ID number
);
commit
I hope this useful.
I created a prompt in SAS EG that takes a text input and creates the macro variable called 'variableName'.
I am trying to reference this macro variable like so:
proc sql;
create table MyTable as
select * from Source_Table as a
where a.field = &variableName ;
This gives me an error that says: "Syntax error, expecting one of the following: a name, a quoted string, a numeric constant, a datetime constant, a missing value, BTRIM, INPUT, PUT, SUBSTRING, USER."
I have also tried enclosing &variableName in single and double quotes but when I do that I just don't get any results.
I am able to reference the prompt when I use query builder and filter data based on the prompt, but I am trying to use the prompt's value in calculated expressions, etc. and in queries I write without query builder. How can i reference the variable I created in the prompt??
Edit: code with a value that the macro variable would have
proc sql;
create table MyTable as
select * from Source_Table as a
where a.field = 'NAME OF PERSON';
When I run that, I get the results I want.
It needs to resolve to valid SAS code. Assuming &variableName is a string, then it would be something like:
proc sql;
create table MyTable as
select * from Source_Table as a
where a.field = "&variableName." ;
If this isn't working, please show a query that does work with the same value as the macro variable would have. And then we can suggest how to change your code.
Edit: based on your comment you do not have the prompt connected to your query. Right click the query and link the prompt to your query and it will run before the query to provide the value.
prep_stmt = con->prepareStatement("SELECT * FROM table WHERE customers in ( ? ) and alive = ?");
prep_stmt->setString(1,customer_string);
prep_stmt->setInt(2,1);
res = prep_stmt->executeQuery();
Here the customer_string is "12,1,34,67,45,14"
When I pass it as a String it always returns a single row, takes the first value only 12.
The sql statement prepared is:
SELECT * FROM table WHERE customers in ( "12,1,34,67,45,14" ) and alive = 1
but I want sql statement to be prepared as:
SELECT * FROM table WHERE customers in (12,1,34,67,45,14 ) and alive = 1
What is the easiest way to achieve the same in C++?
I am assuming you are using the MySQL C++ Connector. Unfortunately it seems that it is not possible to pass array as parameter of prepared statement using this API:
Connector/C++ does not support the following JDBC standard data types: ARRAY, BLOB, CLOB, DISTINCT, FLOAT, OTHER, REF, STRUCT.
https://dev.mysql.com/doc/connector-cpp/en/connector-cpp-usage-notes.html
You can place the value into the query directly by concatenating strings. Be VERY careful to not introduce SQL injection vulnerability. Alternatively use some other API.
I´m having the following code that insert a row into mysql database and return the inserted id:
/*
* Execute the statement
*/
std::string sql = "INSERT INTO TABLE (A, B, C) VALUES (1, 2, 3)";
sql::Statement *stmt;
stmt = connection->createStatement();
stmt->execute(sql);
/*
* Get the returned id
*/
stmt = connection->createStatement();
sql::ResultSet *res = stmt->executeQuery("SELECT ##identity AS id");
res->next();
model.modelId = res->getInt64("id");
My questions are:
Do I really need to call connection->createStatement() again ?
I think this may overload the code, as I need to call twice the database.
Is there a way to optimize this code ?
Is there other way to get the last inserted id ?
Thanks for helping.
Just for the reference, ##identity is MSSQL-specific system function, that also returns last-insert id but for MSSQL, not for MySQL.
To get last-insert id in MySQL, since you have asked specifically for MySQL, you need to change your SELECT statement to following:
SELECT LAST_INSERT_ID() AS id;
Also, since stmt->execute() and stmt->executeQuery() methods take String, as input argument, I am sure that you don't need to connection->createStatement() again. Just to confirm, I just googled it and found this link.
Please note that this answer is specifically for MySQL, as this question is about MySQL. Hope it helps.