My code is necessary to distinguish whether Sql statement is SELECT or not.
If the result is more than 1, it is easy to distinguish select.
But there is no result when the statement executed, how do I distinguish it?
sqlite_stmt *some_stmt;
//case 1 : (the table has no row)
sqlite3_prepare("select * from some_table", &some_stmt);
//case 2 :
sqlite3_prepare("create table some_table2", &some_stmt);
int result = sqlite3_step(some_stmt);
result is same :
SQLITE_DONE;
I can distinguish it with two method,
1st is get substring from the statement. but i don't want do it, it seems to be incorrectly way.
2st is use sqlite3_column_count(). Usually column_count has one or more than if the statement is SELECT.
Is it correct way using sqlite3_coulmn_count()? Isn't there anything that No-column-table in sqlite or etc?
I want correct way to distinguish whether Statement is SELECT or Not.
There are other statements that return data (e.g., some PRAGMAs), so you cannot search for "SELECT".
As documented, sqlite3_column_count() is the correct way:
This routine returns 0 if pStmt is an SQL statement that does not return data (for example an UPDATE).
In SQL, there is no such thing as a table without columns. Even in a construct that does not actually look at any data (such as EXISTS (SELECT ...)), you have to use some dummy column(s).
Related
To simplify my question, consider the following table in dolphindb:
t=table(1..5 as id, 1 NULL 3 NULL NULL as x)
I would like to forward fill nulls ONLY for the rows that I specify. For example, only for the row with id=2. I tried the following SQL query but the result was unexpected.
update t set x=ffill(x) where id=2
The table t was not updated at all. I would appreciate it if someone can point out the mistake in my code. Thanks!
The 'where' condition in SQL is always executed before the 'select' calculations. Therefore in this case you lose the information about id=1. Try this:
update t set x=iif(id==2, ffill(x), x)
This uses dolphindb function iif. Effectively it is a loop.
I have this PostgreSQL PL/pgSQL function:
CREATE OR REPLACE FUNCTION get_people()
RETURNS SETOF people AS $$
BEGIN
RETURN QUERY SELECT * FROM people;
END;
$$ LANGUAGE plpgsql;
Then I try to read the data in an application using SOCI, with this code:
session sql {"postgresql://dbname=postgres"};
row person {};
procedure proc = (sql.prepare << "get_people()", into(person));
proc.execute(true);
I would expect that person have the data of the first person, but it contains only one column with the name of the stored procedure (i.e., "get_people").
So I don't know what I am doing wrong here, or not doing. Is it the PL/pgSQL code or the SOCI code? Maybe SOCI does not support dynamic binding for stored procedures. Also, this method would allow me to read the first row only, but what about the rest of rows? I know SOCI comes with the rowset class for reading result sets, but the documentation says it only works with queries. Please help.
SELECT get_people() will return a single column, of type people, named after the procedure.
SELECT * FROM get_people() will give you the expected behaviour, decomposing the people records into their constituent fields.
Judging from the source, it looks like the SOCI procedure class (or at least, its Postgres implementation) is hard-wired to run procedures as SELECT ... rather than SELECT * FROM ....
I guess this means you'll need to write your own query, i.e.:
statement stmt = (sql.prepare << "SELECT * FROM get_people()", into(person));
Problem: I have a C++ application that executes different Oracle commands. My application can execute this SQL statement the following way (I have ommited error checking and a few earlier steps):
strcpy(szProcName,"select grantee, granted_role from DBA_ROLE_PRIVS;");
rc=SQLPrepare(sqlc.g_hstmt,(SQLCHAR*)szProcName,(SQLINTEGER)strlen(szProcName));
rc = SQLExecute(sqlc.g_hstmt);
The select statement's data is placed/binded into an MFC List Control. This works without problem...
The issue comes when I try to execute long-length select statements.
I now wish to use the same method, but to run this long SQL statement:
SELECT a.GRANTEE, a.granted_role as "Connect", b.granted_role as "APPUSER" FROM
(SELECT GRANTEE, granted_role from DBA_ROLE_PRIVS where GRANTED_ROLE = 'CONNECT') a
FULL OUTER JOIN
(SELECT GRANTEE, granted_role from DBA_ROLE_PRIVS where GRANTED_ROLE = 'APPUSER') b
ON a.GRANTEE=b.GRANTEE;
Setting that entire statement into szProcName seems like the wrong way to go about things.
What I have tried: I tried to add all the SQL text into szProcName, but it does not fit and makes the code terribly messy. I also thought to create a Stored Procedure to call in C++. The Stored Procedure requires that I use an INTO clause and does not produce a table that I can use in C++. Is there a better way to do this?
Edit: I have found one working way. By increasing szProcName's size and usingstrcat(), I can add each line and then execute. I still wonder if there is a more appropriate way, especially if my statements become any larger (which they probably will).
I have found one working way. By increasing szProcName's size and using strcat(), I can add each line and then execute. I still wonder if there is a more appropriate way, especially if my statements become any larger (which they have).
while writing code we can either use select statement or select field list or find method on table for fetching the records.
I wonder which of the statement helps in better performance
It really depends on what you actually need.
find() methods must return the whole table buffer, that means, all of the columns are projected into the buffer returned by it, so you have the complete record selected. But sometimes you only need a single column, or just a few. In such cases it can be a waste to select the whole record, since you won't use the columns selected anyway.
So if you're dealing with a table that has lots of columns and you only need a few of them, consider writing a specific select statement for that, listing the columns you need.
Also, keep in mind that select statements that only project a few columns should not be made public. That means that you should NOT extract such statements into a method, because imagine the surprise of someone consuming that method and trying to figure out why column X was empty...
You can look at the find() method on the table and find out the same 'select'-statement there.
It can be the same 'select; statement as your own an the performance will be the same in this case.
And it can be different select statement then your own and the performance will be depend on indexes on the table, select statement, collected statistics and so on.
But there is no magic here. All of them is just select statement - no matter which method do you use.
I have been searching for a while on how to get the generated auto-increment ID from an "INSERT . INTO ... (...) VALUES (...)". Even on stackoverflow, I only find the answer of using a "SELECT LAST_INSERT_ID()" in a subsequent query. I find this solution unsatisfactory for a number of reasons:
1) This will effectively double the queries sent to the database, especially since it is mostly handling inserts.
2) What will happen if more than one thread access the database at the same time? What if more than one application accesses the database at the same time? It seems to me the values are bound to become erroneous.
It's hard for me to believe that the MySQL C++ Connector wouldn't offer the feature that the Java Connector as well as the PHP Connector offer.
An example taken from http://forums.mysql.com/read.php?167,294960,295250
sql::Statement* stmt = conn->createStatement();
sql::ResultSet* res = stmt->executeQuery("SELECT ##identity AS id");
res->next();
my_ulong retVal = res->getInt64("id");
In nutshell, if your ID column is not an auto_increment column then you can as well use
SELECT ##identity AS id
EDIT:
Not sure what do you mean by second query/round trip. First I thought you are trying to know a different way to get the ID of the last inserted row but it looks like you are more interested in knowing whether you can save the round trip or not?
If that's the case, then I am completely agree with #WhozCraig; you can punch in both your queries in a single statement like inser into tab value ....;select last_inserted_id() which will be a single call
OR
you can have stored procedure like below to do the same and save the round trip
create procedure myproc
as
begin
insert into mytab values ...;
select last_inserted_id();
end
Let me know if this is not what you are trying to achieve.