How to execute dynamic SQL statement inside Postgres sql script - sql

Below is my script. I used Execute command to run the dynamic sql statement that i created but it doesn't run and give an output. It doesn't give an error either. How can I run this sql statement inside postgres sql script?
DO $$
DECLARE sqlCommand varchar(1000);
columnList varchar(75);
BEGIN
select '"BRANCH_NAME", "ADDRESS1"' into columnList;
select concat('SELECT ' , columnList , ' FROM "TESTSCHEMA"."BRANCH" ') into sqlCommand;
raise info 'COMMAND %', sqlCommand;
execute sqlCommand;
END $$;

Your example is safe, but if you are dealing with user input, always use the format function to construct the SQL string.
Anyway, your problem is that the EXECUTE statement has no INTO clause with a destination for the query results, si they are simply discarded.

Related

Cannot pass parameter inside stored procedure in redshift

I have written the procedure which calls the parameter in the select query, but it's not working. When I print that parameter it's working fine, but with the select query, it's not working.
I have used Aginity workbench for redshift to execute the stored procedure.
CREATE or replace PROCEDURE get_tbl_name(IN tablename varchar, IN columnname VARCHAR, IN mindate varchar) AS $$
Declare
evalmindate varchar;
BEGIN
Raise info 'tablename = %, columnname = %, mindate = %', tablename,columnname,mindate;
if mindate is null then
select min(columnname) into evalmindate from tablename;
else
evalmindate=mindate;
end if;
END;
$$ LANGUAGE plpgsql;
Calling Proc:
call get_tbl_name('test_bq', 'date',NULL);
Output:
tablename = test_bq, columnname = date, mindate = <NULL>
Error Message
42601: syntax error at or near "$2"
From the output, we can able to see the parameter inside the procedure when I print, but I can't pass the parameter to the select query, it throwing an error. Kindly help me with this.
You can't use the variable as a column or table name directly in a stored procedure query. Instead you need to compose a query string and execute that.
Also the INTO var syntax needs to come first in a plain query and last in an EXECUTE.
You have:
select min(columnname) into evalmindate from tablename;
Try this:
EXECUTE 'select min('|| columnname ||') from '|| tablename ||';' INTO evalmindate;

Teradata stored procedure with dynamic parameters called from R script

I need to extract some data from Teradata to process in R. I have around 84 Dep/sec keys with most of them having a different time span so my thought was to create a stored procedure in Teradata that will accept the Dep, Sec and Dates as parameters. I could then loop over the list in R calling the SP each time to create my data set.
The SP I have created to test this idea is a very simple one but I can't get it to work.
CREATE PROCEDURE procTest4 (IntN integer)
BEGIN
CALL DBC.SysExecSQL('SELECT top' || IntN || '*
from TableName');
END;
Teradata does create the SP but I don't know how to execute it and pass the paramters to it. When I try:
Call procText4(10)
I get the following error:
5568: SQL statement is not supported within a stored procedure.
The only other option for me is to create the SQL string in R and then run it from there but there is multiple passes of SQL which create volatile tables and the RODBC package doesn't seem to like them, plus it's a very messy way of doing it.
Any help is much appreciated.
The syntax for returning a result set from a Stored Procedure using Dynamic SQL is a bit complex:
CREATE PROCEDURE procTest4 (IntN INTEGER)
DYNAMIC RESULT SETS 1
BEGIN
DECLARE SqlStr VARCHAR(1000);
DECLARE rslt CURSOR WITH RETURN ONLY FOR stmt;
SET SQLStr = 'SELECT top ' || IntN || ' * from TableName';
PREPARE stmt FROM SqlStr;
OPEN rslt;
END;
But you should double check if you can rewrite those loops...

Passing a table to run in execute command in oracle

I need to write multiple statements given below
EXECUTE ssc.iqv_calculation ('PWCD_PRODUCT_CATEGORY', 'PRODUCT_CATEGORY');
EXECUTE ssc.iqv_calculation ('PWCD_CONTRACTING_LOCATION', 'CONTRACTING_LOCATION');
EXECUTE ssc.iqv_calculation ('PWCD_CNTRY_INCORPORATION', 'CNTRY_INCORPORATION');
EXECUTE ssc.iqv_calculation ('PWCD_COUNTRY_OF_OPERATIONS', 'COUNTRY_OF_OPERATIONS');
EXECUTE ssc.iqv_calculation ('PWCD_XBORDER_ACTIVITY', 'XBORDER_ACTIVITY');
EXECUTE ssc.iqv_calculation ('PWCD_APPROVED_EXCHANGE', 'APPROVED_EXCHANGE');
EXECUTE ssc.iqv_calculation ('PWCD_LEGAL_STRUCTURE', 'LEGAL_STRUCTURE');
These are few but I need to write 100 such statements.
How can I send them in a loop given that I have a table containing two columns having the list of the two parameters.
One way is excel. How can I do it in Oracle itself.
begin
for rec in (select param1, param2 from your_table) loop
execute immediate 'begin ssc.iqv_calculation(:1, :2); end;'
using
in rec.param1,
in rec.param2;
end loop;
end;
/
Enjoy.

EXECUTE IMMEDIATE ' some commands '

Is it possible to execute some sql commands within one EXECUTE IMMEDIATE block?
What is wrong with this syntax:
declare
pragma autonomous_transaction;
begin
execute immediate
'begin
COMMENT ON TABLE t1 IS ''description1'';
COMMENT ON TABLE t2 IS ''description2'';
end;';
end;
For one SQL command it works fine:
declare
pragma autonomous_transaction;
begin
execute immediate ' COMMENT ON TABLE t1 IS ''description1'' ';
end;
The begin end within the string to execute immediate is going to be treated as a PL/SQL anonymous block. DDL, such as COMMENT is not allowed in PL/SQL. If it were you wouldn't need to use execute immediate. Oracle essentially works with either a block of PL/SQL statement or a single SQL statement at a time. Though there are APIs to batch SQL statements too.
So, to run COMMENT within a PL/SQL block or procedure, you will need to execute immediate statements.
Without more context I can not intelligently comment on whether that is the right approach, or if just having the two comment statements stand alone would be better.
Well, you could do this:
begin
execute immediate
'begin
execute immediate ''COMMENT ON TABLE t1 IS ''''description1'''' '';
execute immediate ''COMMENT ON TABLE t2 IS ''''description2'''' '';
end;';
end;
But there's not much point.

Condition in SQL script

I've got an SQL-script executed by SQL*Plus, that needs to run with Oracle 10g and Oracle 11g.
That script gives grants on a package that does not exist before 11g:
GRANT EXECUTE ON sys.dbms_result_cache TO my_user;
I would like to avoid the exception on 10g, since I want to react to other exceptions in the script.
One way is to use Conditional Compilation and dbms_db_version:
BEGIN
$IF dbms_db_version.ver_le_10 $THEN NULL; $ELSE
EXECUTE IMMEDIATE 'GRANT EXECUTE ON sys.dbms_result_cache TO my_user';
$END
END;
/
Is there any other way, preferable without using PL/SQL?
Your question and one of the comments indicate that you want to avoid PL/SQL blocks and EXECUTE IMMEDIATE. I also assume that by "react to other exceptions" you mean abort execution of the script when an exception is encountered.
If so, I think the best you can do in pure SQL/SQL*Plus is to ignore the exception exit for the grant statement:
... first part of script (with exit on sqlerror in effect)
WHENEVER SQLERROR CONTINUE
GRANT EXECUTE ON sys.dbms_result_cache TO my_user;
WHENEVER SQLERROR EXIT SQL.SQLCODE
... remaining part of script
you could check if the object exists beforehand:
BEGIN
FOR cc IN (SELECT NULL
FROM all_objects
WHERE owner = 'SYS'
AND object_name = 'DBMS_RESULT_CACHE'
AND ROWNUM = 1) LOOP
EXECUTE IMMEDIATE 'GRANT EXECUTE ON sys.dbms_result_cache TO my_user';
END LOOP;
END;
You can simulate branching by writing SQL that generates SQL and spools it to a sql script. Then run the sql script:
define temp_file='somefile.sql'
set heading off
set feedback off
spool &&temp_file
SELECT 'GRANT EXECUTE ON sys.dbms_result_cache TO my_user;'
FROM all_objects
WHERE owner = 'SYS'
AND object_name = 'DBMS_RESULT_CACHE';
spool off
#&&temp_file
host rm &&temp_file
Thanks to #Vincent for the data dictionary query.