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.
Related
Im at a loss right now because even on the most simple statement,
BEGIN
DECLARE rs1 CURSOR WITH RETURN FOR
select * from table1;
END
WITH RETURN is generating a
SQL Error [42613]: [SQL0628] Clauses not valid in same definition.
The Documentation https://www.ibm.com/docs/en/i/7.3?topic=codes-listing-sql-messages says:
Clauses specified to define the attributes of a column, a sourced function, a procedure, a trigger, or an index are not valid. One of the following has occurred:
WITH RETURN is specified for a cursor in a compound (dynamic) statement.
How is this Select statement supposed to be called for a Cursor without being considered a dynamic statement?
See documentation
WITH RETURN
Specifies that the result table of the cursor is intended to be used as a procedure result set. If the DECLARE CURSOR statement is not
contained within the source code for a procedure, the clause is
ignored.
I am inside a SQLScript procedure and would like to return the last SQL Statement from this procedure, like the last rowcount:
/********* Begin Procedure Script ************/
BEGIN
select 1 as "my_data" from dummy;
select '::last_SQL' as "last executed sql" from dummy;
select ::ROWCOUNT as "rowcount" from dummy;
END;
/********* End Procedure Script ************/
The column "last executed SQL" should be populated with select 1 as "my_data" from dummy in this case. Is there any variable holding the last statement (or any easy way to retrieve the query plan)?
Maybe you can query sys.m_sql_plan_cache system view
Please check following SELECT statement
select
statement_string, last_execution_timestamp
from SYS.M_SQL_PLAN_CACHE
where user_name = 'KODYAZ'
order by last_execution_timestamp desc;
I believe you can improve the query by introducing new filter criteria.
There is no way to programmatically get the last executed SQL statement in SQLScript. This is due to the fact that not all statements will be executed in the form and order as they appear in the source code.
If you want to analyse the performance of a procedure, you can run PlanViz against the procedure call. Generally, there is no such thing as "the performance of a procedure/function" as they always occur in a specific context.
If used within a SQL query, things like query-transformation can radically change the way certain results are computed.
I have a requirement where-in I need to read a table (table name provided as input parameter of the SP), store the results in a temp table and then store the count of the read table into a variable. Please advise how can this be achieved. I have been able to read the table and its count using dynamic query but am not able to put the results in a temp table/ variable. 'Select' and 'Into' clauses do not seem to be working with 'Execute Immediate'. Thanks.
It is not very clear to me exactly what is being asked, but you should be able to execute a SELECT statement in the following manner:
CREATE PROCEDURE p1(IN tablename VARCHAR) AS
BEGIN
execute immediate 'SELECT * FROM ' || :tablename;
END;
Then the following statements create a table and call the procedure to retrieve the result:
create table T (i integer);
insert into T values (123);
The following would produce a result set with one row/column with the value 123:
CALL p1('T')
Please note that with this type of functionality, you need to be very careful not to allow any user-provided input to be given directly to a procedure that uses EXECUTE IMMEDIATE to avoid the possibility of SQL injection attacks.
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.
I'm trying to write a trigger within SQL, and the code within needs to determine whether an entry exists in the table before either attempting to update, or insert.
I have tried using both
IF EXISTS
UPDATE
ELSE
INSERT
And
UPDATE
IF ##ROWCOUNT = 0
INSERT
But neither of them work. I'm partial to using the latter because my employer is nuts about efficiency (well...duh...) For this reason I'm also reluctant to use
IF SELECT COUNT(*) = 0
UPDATE
ELSE
INSERT
Does anybody know any ways to get around this?
--
UPDATE: I am trying to use MERGE, but I am receiving several errors...
MERGE INTO [tableName] AS Target
USING (SELECT :NEW.PIDM) AS Source (PIDM)
ON (Target.PIDM = Source.PIDM)
WHEN MATCHED THEN
[UPDATE STATEMENT]
WHEN NOT MATCHED THEN
[INSERT STATEMENT]
This gives me an error complaining that I'm missing the 'USING' keyword, as well as another complaining about the WHEN statement...
Use MERGE instead
In PL/SQL, you would use SQL%ROWCOUNT instead of ##ROWCOUNT:
UPDATE (...);
IF SQL%ROWCOUNT = 0 THEN
INSERT (...);
END IF;
Or, you could use SQL%NOTFOUND, which I personally think is easier to understand the intent:
UPDATE (...);
IF SQL%NOTFOUND THEN
INSERT (...);
END IF;
As for the MERGE command, the Oracle syntax is slightly different from the SQL Server which #zerkms linked to. In particular, you should leave the word "AS" out of the table alias, and you shouldn't list columns after the "USING" clause. Also, in Oracle SQL, the FROM clause is mandatory. You can use the DUAL table to mimic SQL Server's behavior. Putting it all together (this is untested):
MERGE INTO tableName Target
USING (SELECT :NEW.PIDM FROM DUAL) Source
ON (Target.PIDM = Source.PIDM)
WHEN MATCHED THEN
[UPDATE STATEMENT]
WHEN NOT MATCHED THEN
[INSERT STATEMENT]