check for zero rows in select query - sql

My C program has an embedded sql query. This program runs on windows and queries the oracle database.
The query is similar to EXEC SQL SELECT ...
I need to add here a check to know if the query returns zero rows.
Basically I want to set a local valiable to know my query has returned no rows and
handle this condition accordingly.
How can I add it. I know that EXISTS statement can be used. But I am not getting
how do I use it in embedded sql.
Thanks for any help.

Use the sqlca struct
EXEC SQL include "sqlca.h"
#define NO_ROWS_FOUND (sqlca.sqlcode==1403)
EXEC SQL BEGIN DECLARE SECTION;
int val=0;
short ind=0;
EXEC SQL END DECLARE SECTION;
EXEC SQL
select value
int :val :ind
from mytable where rownum=1;
if(NO_ROWS_FOUND)
printf("No rows found\n");

Use SELECT COUNT(*) FROM ... and compare result to 0.

Related

postgres sql / dbweaver - Using a variable for tablename?

One of the SQL Queries use the same table name again and again -
Example -
select
rr.jdoc as child_node, json_agg(parent_rr.jdoc)::jsonb as parent_node , array_length(array_agg(parent_rr.jdoc)::jsonb[], 1) as count
from MYTABLE rr, MYTABLE parent_rr
where
parent_rr.jdoc #> (rr.jdoc->'somefield')::jsonb
group by rr.jdoc
UNION
select rr.jdoc, NULL as parent_id, null as pcount
from MYTABLE rr where
not (rr.jdoc ?? 'somefiled')
and ((rr.jdoc->'crazyfiled'->>'doublecrazyfiled')<>'gotyou')
You can see the same MYTABLE is used 3 times. The thing is, I have to run the same query for different tables i.e the MYTABLE substituted.
So I am trying to find - if anything like below is possible -
SET TABLENAME=CUS_DELTA --//then use the above like -
select * from $TABLENAME;
I am using postgres 13.5 with DBeaver for running the queries.
If not SQL, does DBeaver provide any such means.
If SQL can not support it, I am ok to use Dynamic SQL / PL SQL (though i have not idea about these) - if its not going to be too complicate for the above case. But I am not aware about the code, so request to share the same through an answer.
Read this article about Dynamic SQL carefully. Example from the docs:
EXEC SQL BEGIN DECLARE SECTION;
const char *stmt = "INSERT INTO test1 VALUES(?, ?);";
EXEC SQL END DECLARE SECTION;
EXEC SQL PREPARE mystmt FROM :stmt;
...
EXEC SQL EXECUTE mystmt USING 42, 'foobar';
Basically this way you can simply pass values. Now, your values are dynamic as well, but no worries. Declare your tablename as varchar and SELECT tbname INTO yourvariable FROM sometable. Then you can pass this variable to your dynamic query.
EDIT:
Minimalistic example:
Setting a variable to hard-coded value
SET TABLENAME = 'CUS_DELTA';
Setting a variable to a dynamic table name
SELECT tbname
INTO TABLENAME
FROM yourtable
And then let's use our TABLENAME variable like this:
EXEC SQL BEGIN DECLARE SECTION;
const char *stmt = "SELECT * FROM ?";
EXEC SQL END DECLARE SECTION;
EXEC SQL PREPARE mystmt FROM :stmt;
EXEC SQL EXECUTE mystmt USING TABLENAME;
The above is untested.

DB2 SQL considers IF ELSE condition a DDL statement?

I am trying to use a simple IF ELSE query to test a feature with DB2 SQL. However when I attempt to execute it, I run into an error stating that I am not allowed to execute DDL statements.
What is throwing me off is that as far as I know, only database structure altering statements are considered DDL statements.
What gives?
Code:
IF 'True' = 'True' THEN
SELECT * FROM RM_TRANSACTION
FETCH FIRST 2 ROWS ONLY
FOR READ ONLY WITH UR
ELSE
SELECT * FROM RM_TRANSACTION
FETCH FIRST 4 ROWS ONLY
FOR READ ONLY WITH UR
END IF
https://imgur.com/a/58RYjpu
The problem is that you can’t ‘select to nowhere’ in a compound statement in DB2. Db2 CLP can return you the result set of a single sql statement, but it doesn’t try to do the same for select statements in a compound statement.
If you want to print the result set from a select statement in a compound statement, you can, for example, declare a cursor, fetch it in a loop, and use dbms_output.put_line calls to print the values of variables.

Pro C dynamic SQL query

I have to execute the following query using Pro C to get the output and den display the output to the user.
i tried the following code snippet:
int count=0;
char query1[100]="select count(code) from customer where customer_type='a';";
EXEC SQL ALLOCATE DESCRIPTOR 'out' ;
EXEC SQL PREPARE statement FROM :query1 ;
EXEC SQL DESCRIBE OUTPUT statement USING DESCRIPTOR 'out' ;
EXEC SQL SET DESCRIPTOR 'out' VALUE 1 TYPE = :data_type,
LENGTH = :data_len, DATA = :count ;
EXEC SQL DECLARE c CURSOR FOR statement ;
EXEC SQL OPEN c ;
EXEC SQL FETCH c INTO DESCRIPTOR 'out' ;
EXEC SQL GET DESCRIPTOR 'out' VALUE 1 :count = DATA;
EXEC SQL CLOSE c ;
printf("%-8d ",count);
but the output i get is always 0.
How shall i proceed to get the proper output??
can anyone help pls...
It is quite possible you have some errors in there that arn't getting noticed.
Use the EXEC SQL WHENEVER to get some error checking going on.
The one thing that jumps out at me is the semicolon at the end of the query1 value. If I recall correctly, Pro*c will barf on it.
I would strongly recommend against using this method of Pro*C dynamic SQL (Oracle dynamic SQL method 4) unless you can possibly avoid it.
The only case you should need to use this method is when you are using dynamically generated SQL and you don't know how many host variables will be used. E.g. You don't know how many columns will be in the SELECT clause.
A fully fledged example of using Oracle dynamic SQL method 4 can be found at http://docs.oracle.com/cd/B28359_01/appdev.111/b28427/pc_15ody.htm#i7419.

Sql update statement, any way of knowing what it actually did?

Typically, I test an update by running a query using the where statement and then after verifying that it does what I think I want it to copying the where clause to the update statement and executing it. But is there any way of getting the statement to return what the update did besides the '4 rows updated'
Sure, take a look at the output clause of T-SQL
http://msdn.microsoft.com/en-us/library/ms177564.aspx
You could load your records into a temp table/variable in SQL Server:
DECLARE #Temp TABLE(ID INT)
INSERT INTO #Temp (ID)
SELECT ID
FROM Customer
WHERE AcctBalance > 5000
--inspect as needed
UPDATE Customer
SET AcctBalance = 0
WHERE ID IN (SELECT ID FROM #Temp)
That depend in the server, library that you use, in php, pdo exec return number of row effected by delete or update cluase

EXEC(query) AT linkedServer With Oracle DB

I am using Microsoft SQL server 2005. I need to sync data between SQL server and an Oracle db. First thing I need is to find out if the count of data on Oracle side with certain filters(here I use ID as a simple example).
SELECT COUNT(*) FROM oracleServer..owner.table1 WHERE id = #id;
The problem I have is that the table on the lined server or Oracle is very big with 4M rows of data. The above query took about 2minutes to get data back. This code is just a simplied piece. Actually my SP has some other queries to update, insert data from the lined server to my SQL server. The SP took hours or 10+ hours to run with large Oracle db. Therefore T-SQL with lined server is not good for me.
Recently I found OPENQUERY and EXEC (...) AT linedServer. OPENQUERY() is very fast. It took about 0 time to get the same result. However, it does not support variable query or expressions. The query has to be a literal constant string.
EXEC() is in the same way to pass-through query to Oracle. It is fast as well. For example:
EXEC ('SELECT COUNT(*) FROM owner.table1 WHERE id = ' + CAST(#id AS VARCHAR))
AT oracleServer
The problem I have is how to pass the result COUNT(*) back. I tried to google examples in web and msdn. All I can find are SQL or ExpressSQL linedServer examples like:
EXEC ('SELECT ? = COUNT(*) FROM ...', #myCount OUTPUT) AT expressSQL
This query does not work for Oracle. It seems in Oracle, you can set value as output in this way:
SELECT COUNT(*) INTO myCount ...
I tried this:
EXEC ('SELECT COUNT(*) INTO ? FROM ...', #myCount OUTPUT) AT oracleServer
EXEC ('SELECT COUNT(*) INTO : FROM ...', #myCount OUTPUT) AT oracleServer
EXEC ('SELECT : = COUNT(*) FROM ...', #myCount OUTPUT) AT oracleServer
None of those working. I got error message saying query not executable on Oracle server.
I could write a .Net SQL Server project to do the job. Before that, I just wonder if there is anyway way to pass value out as oupput parameter so that I put the better performance T-SQL codes in my SP?
Just a quick update on this. I think I got the solution. I found it in a discussion on a similar issue at Dev NewsGroup. Based on the information, I tried this:
DECLARE #myCount int;
DECLARE #sql nvarchar(max);
set #sql =
N'BEGIN
select count(*) into :myCount from DATAPARC.CTC_MANUAL_DATA;
END;'
EXEC (#sql, #myCount OUTPUT) AT oracleServer;
PRINT #myCount; -- 3393065
Wa! I got the result back in 3 seconds comparing T-SQL query directly on Orable DB (+2minutes). The important thing is to use "BEGIN" and "END;" to wrap the query as anonymous block and don't miss ";" after END
You need anonymous block for output parameters. If you only have input or no parameters, you don't need the block and the query works fine.
Enjoy it! By the way, this is a quick update. If you don't see me again, I would not have any trouble on this issue.
With Linked Services the biggest issue is performance (IMHO)
[linkedserver]...[dbo.RemoteTable] vs OPENQUERY(linkedserver, 'Select * from dbo.RemoteTable') always use the second one
Now to answer the question. OPENQUERY and EXEC() AT is much quicker.
EXEC(Select * from dbo.RemoteTable) AT linkedserver will show the results, but there is no way to re-use.
My simple solution:
SELECT * INTO LocalTable FROM OPENQUERY(linkedserver, 'Select * from dbo.RemoteTable')
OR
INSERT INTO LocalTable SELECT * FROM OPENQUERY(linkedserver, 'Select * from dbo.RemoteTable')
much^10 faster than
SELECT * INTO LocalTable FROM [linkedserver]...[dbo.RemoteTable]