PL/SQL Dynamic SQL - oracle

I need help. I have a problem in constructing my PL/SQL block.
In the cursor, I have a query constructed, and i want to insert a filter on cursor. Below is an example:
DECLARE
code NUMBER;
parameters_amb myOthertable%ROWTYPE;
CURSOR test is SELECT id from mytable
if parameters_amb.test2 is not null then
where mytable.name = 'NAMETABLE'
else
where mytable.name = 'NAMETABLE2';
Can anyone assist me in this construction?

You can use a parameterized cursor:
DECLARE
code NUMBER;
parameters_amb myOthertable%ROWTYPE;
param mytable.name%TYPE;
CURSOR test (p_name VARCHAR2) is
SELECT id
FROM mytable
WHERE mytable.name = p_name;
BEGIN
if parameters_amb.test2 is not null then
param := 'NAMETABLE'
else
param := 'NAMETABLE2';
end if;
OPEN test(param);
-- Add code to fetch and read from cursor
END;

You can try it like this:
DECLARE
code NUMBER;
parameters_amb myOthertable%ROWTYPE;
CURSOR test is SELECT id
from mytable
WHERE (parameters_amb.test2 is not null AND mytable.name = 'NAMETABLE' )
OR (parameters_amb.test2 is null AND mytable.name = 'NAMETABLE2' );
Or like this:
DECLARE
code NUMBER;
parameters_amb myOthertable%ROWTYPE;
CURSOR test is SELECT id
from mytable
WHERE mytable.name =
CASE WHEN parameters_amb.test2 is not null THEN 'NAMETABLE'
WHEN parameters_amb.test2 is null THEN 'NAMETABLE2' END

DECLARE
stmt varchar2(1000);
code NUMBER;
parameters_amb myOthertable%ROWTYPE;
BEGIN
stmt := 'SELECT id from mytable';
if parameters_amb.test2 is not null
then
stmt := stmt||' where mytable.name = ''NAMETABLE''';
else
stmt := stmt||' where mytable.name = ''NAMETABLE2''';
end if;
OPEN test FOR stmt;
...
...
END;

Here is a simple solution:
DECLARE
code NUMBER;
parameters_amb myOthertable%ROWTYPE;
CURSOR test is SELECT id from mytable
where mytable.name = NVL2(parameters_amb.test2, 'NAMETABLE', 'NAMETABLE2');

Related

How to set a variable and use it in a select query in Oracle PL/SQL?

How can I do something like this in oracle SQL developer?
DECLARE
p_name products.product_name%TYPE;
BEGIN
p_name := 'Strawberry';
SELECT * FROM products WHERE product_name = p_name;
END;
Use a cursor:
DECLARE
p_name VARCHAR2(100);
p_cur SYS_REFCURSOR;
BEGIN
p_name := 'Strawberry';
OPEN p_cur FOR
SELECT * FROM products where product_name=p_name;
-- do something with the cursor.
END;
/
Or use a SQL/Plus-style bind variable declaration:
VARIABLE p_name VARCHAR2;
BEGIN
:p_name := 'Strawberry';
END;
/
SELECT * FROM products where product_name=:p_name;
If only one row will ever be returned from your query (i.e. product_name is UNIQUE) then you can use SELECT ... INTO ...:
DECLARE
p_name VARCHAR2(100);
p_value1 products.value1%TYPE;
p_value2 products.value2%TYPE;
p_value3 products.value3%TYPE;
BEGIN
p_name := 'Strawberry';
SELECT value1, value2, value3
INTO p_value1, p_value2, p_value3
FROM products
WHERE product_name=p_name;
-- do something with the values.
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
-- Handle the exception
WHEN TOO_MANY_ROWS THEN
NULL;
-- Handle the exception
END;
/
You need to give the SELECT statement somewhere to put the results of the query:
DECLARE
p_name VARCHAR2(100);
aProducts_row PRODUCTS%ROWTYPE;
BEGIN
p_name := 'Strawberry';
SELECT *
INTO aProducts_row
FROM products
where product_name=p_name;
-- Add code to manipulate data in aProducts_row here, as in...
DBMS_OUTPUT.PUT_LINE('PRODUCT_NAME = ''' ||
aProducts_row.PRODUCT_NAME || '''');
END;
Or if you're expecting more than one row to be returned you can use a cursor:
DECLARE
p_name VARCHAR2(100);
BEGIN
p_name := 'Strawberry';
FOR aProducts_row IN (SELECT *
FROM products
where product_name=p_name)
LOOP
-- Add code to manipulate data in aProducts_row here, as in...
DBMS_OUTPUT.PUT_LINE('PRODUCT_NAME = ''' ||
aProducts_row.PRODUCT_NAME || '''');
END LOOP;
END;
If the question is not about setting variables but is actually about output from a PL/SQL anonymous block then it is already answered here.
declare
rc sys_refcursor;
begin
open rc for select 'Hello' as test from dual;
dbms_sql.return_result(rc);
end;
You can set any variable you want using the normal PL/SQL assignment syntax. If there is some part of the documentation that is not clear then please provide an example of what you are trying to do.

Using variable in FROM clause pl/sql

SET SERVEROUTPUT ON
DECLARE
table_name varchar2(80) := 'dual';
BEGIN
SELECT * FROM table_name WHERE dummy = 'X';
END;
The above code throws error. I want to use a variable in the from clause.
For a dynamic query you can use EXECUTE IMMEDIATE.
DECLARE
table_name VARCHAR2 (80) := 'dual';
v_query VARCHAR2 (200);
BEGIN
v_query := 'SELECT *
FROM ' || table_name || '
WHERE dummy = ''X''';
EXECUTE IMMEDIATE v_query;
END;

passing parameter to a function in a select statement dynamically

how to use dynamic value while passing the parameter in select statement.
I have a function like below ....
create or replace function get_old_GSL (p_vendor_site_id in varchar2) return varchar2
is
v_sup_gsl VARCHAR2(30);
v_ret_val VARCHAR2(30);
BEGIN
BEGIN
SELECT SUBSTR(ATTRIBUTE52,1,6)
INTO v_sup_gsl
FROM gecm_dff_ext
WHERE primary_table ='AP_SUPPLIER_SITES_ALL'
AND primary_key = p_vendor_site_id
and attribute52 is not null;
EXCEPTION
WHEN OTHERS THEN
v_sup_gsl := NULL;
END;
BEGIN
IF v_sup_gsl IS NOT NULL THEN
SELECT segment1
INTO v_ret_val
FROM ap_suppliers
WHERE segment1 = v_sup_gsl;
END IF;
EXCEPTION
WHEN OTHERS THEN
v_ret_val := NULL;
END;
return(v_ret_val);
END;
Testing the function:
---------------------
--> select GET_OLD_GSL(22758460) as xyz from dual;
--> select GET_OLD_GSL(22758529) as xyz from dual;
--> select GET_OLD_GSL(22760317) as xyz from dual;
--> select GET_OLD_GSL(22758389) as xyz from dual;
--> select GET_OLD_GSL(22759519) as xyz from dual;
Here, iam using column 'vendor_site_id' of 'ap_supplier_sites_all' table .
My requirement is passing this parameter dynamically without hard coding the parameter each time i pass.

Set boolean to true if select returns something

How can I set a boolean to true if a select query returns something ?
Like that :
declare
isExist boolean;
begin
select count(1) into isExist from MYTABLE where ID = 1;
end;
Oracle's SQL (still) doesn't support the boolean datatype, only PL/SQL does that - but a SQL statement embedded in PL/SQL has to conform to the rules of Oracle's SQL; this sometimes causes a bit of confusion.
Of course there are many workarounds possible, for example:
declare
n number;
isExist boolean;
begin
select count(1) into n from MYTABLE where ID = 1;
isExist := (n>0);
end;
There is a lot of ways to do it:
DECLARE
l_temp NUMBER(1);
l_exists boolean;
BEGIN
SELECT count(*)
INTO l_temp
FROM dual
WHERE EXISTS (SELECT NULL FROM YOUR_TABLE WHERE id = 1)
;
-- l_temp is 1 if there are something in your table and 0 if there is nothing in your table.
l_exists := l_temp = 1;
END;
Also you can try to use cursor:
DECLARE
l_cursor SYS_REFCURSOR;
l_temp YOUR_TABLE.id%TYPE;
l_exists boolean;
BEGIN
open l_cursor for SELECT id FROM YOUR_TABLE WHERE id = 1;
fetch l_cursor into l_temp;
l_exists := l_cursor%FOUND;
close l_cursor;
END;

How to find out if this SELECT query executed successfully?

CREATE PROCEDURE Pname(in_empno IN NUMBER out_name OUT VARCHAR2)
AS
BEGIN
select EmpName into out_name from emptable where Empno = in_empno;
END Pname;
In the above procedure, how can I check if the SELECT query executed successfully or not with the given condition?
You can use the EXCEPTION block to determine if rows were returned or if some other exceptions occurred. Try this
BEGIN
SELECT EmpName into out_name from emptable where Empno = in_empno
EXCEPTION
WHEN NO_DATA_FOUND THEN
out_name := NULL;
END;
If you would like to see the output of out_name parameter try as follows
CREATE OR REPLACE PROCEDURE pname (in_empno IN NUMBER, out_name OUT VARCHAR2)
IS
BEGIN
SELECT empName
INTO out_name
FROM emptable
WHERE empno = in_empno;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
raise_application_error (
-20000,
'Unable to execute procedure because of: ' || SQLERRM
);
END pname;
This procedure can be executed from sql plus as
var ret varchar2(512);
exec pname(2345,:ret);
print ret;
Update 1
If you would like to return a value if sql query executes successfully and if there is an error return another value then do as
CREATE OR REPLACE PROCEDURE pname (in_empno IN VARCHAR2,
out_name OUT VARCHAR2,
returnval IN OUT NUMBER
)
IS
BEGIN
SELECT employee_name
INTO out_name
FROM employees
WHERE emp_number = in_empno;
returnval := 0;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
returnval := 1;
END pname;
and call the procedure from sql plus as
var ret varchar2(512);
var ret2 number;
exec pname(2346,:ret,:ret2);
print ret;
print ret2;
In this example i can stop using one more out variable for return right? and ill check for the condition in my front end like if 'out_name' returns null ill handle in someway, if it returns value it'll be handled in other way, Which one is efficient?????Using one more out variable for Retvalue, or doing like this
CREATE OR REPLACE PROCEDURE pname (in_empno IN VARCHAR2, out_name OUT VARCHAR2)
IS
BEGIN
SELECT employee_name
INTO out_name
FROM employees
WHERE emp_number = in_empno;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
out_name := NULL;
END;

Resources