How to execute PL/SQL that already exists. (Oracle APEX 21.1) - plsql

What I do to display the result of PL/SQL "PR_TEXT_CONCAT"?
I want display that result to Page3. This page has 3 Text Fields and 1 Button.
Enter text in P3_TEXT1 and P3_TEXT2, and press the button (P3_EXECUTE), show the string P3_TEXT1 + P3_TEXT2 on P3_TEXTOUT.
The procedure was created with the following SQL.
CREATE OR REPLACE PROCEDURE PR_TEXT_CONCAT
{
PARAM1 IN VERCHAR2,
PARAM2 IN VERCHAR2, PARAM2 IN VERCHAR2,
PARAMOUT OUT VERCHAR2
}
IS
BEGIN
PARAMOUT := 'SHOP: ' || PARAM1 || '+' || PARAM2;
END;
---Added--
It is written in PL/SQL Dynamic Content region.
Source - PL/SQL Code: :PARAMOUT := PR_TEXT_CONCAT;

Here is how to do this with a stored procedure. Note that there were some errors in your code (curly braces and "VERCHAR" are both not used in oracle)
Create the procedure
CREATE OR REPLACE PROCEDURE PR_TEXT_CONCAT
(
PARAM1 IN VARCHAR2,
PARAM2 IN VARCHAR2,
PARAMOUT OUT VARCHAR2
)
IS
BEGIN
PARAMOUT := 'SHOP: ' || PARAM1 || '+' || PARAM2;
END;
/
Create the apex page
Create a region with 3 items: P1_ITEM1, P1_ITEM2 and P1_ITEM3
Create a region button with action "Submit Page"
Create a page process with point "Processing" and code
PR_TEXT_CONCAT
(
PARAM1 => :P1_ITEM1,
PARAM2 => :P1_ITEM2,
PARAMOUT => :P1_ITEM3
);
This should do. Put a value in item 1 and item 2 and click the button. item 3 will contain the value returned from the stored proc

here is how I did
created 3 items + 1 button
created one page process (1)
run the page
input some text into fields
clicked the button saw the output(2)
(1) inside page process :P2_TEXTOUT := :P2_TEXT1 || :P2_TEXT2;
(2) example
2nd way:
create or replace function textOut (vText_1 in varchar2, vText_2 in varchar2)
return varchar2 is
vTextOut varchar2(20);
begin
vTextOut := vText_1 || vText_2;
return vTextOut;
end;
then call this function in your page process source;
select textOut (:p2_text1, :p2_text2) into :p2_textout from dual;

Related

Stored Procedure not reading from variable in IF-ELSE statement

I started writing this stored procedure and I faced some issues when I try to pass a variable in my conditional statement.
I can use the parameter BANKN which works fine, but when never I passed the declared variable AC_t somehow the PL/SQL ignores it.
Any idea please what I'm missing here?
create or replace PROCEDURE TTEST1 (
CR IN VARCHAR2,
BANKN IN VARCHAR2,
P_CURSOR OUT SYS_REFCURSOR
)
AS
G_AC CHAR(10);
AC_t Billing.Account %Type;
BEGIN
IF BANKN = 'WLNV' AND AC_t = 'Private'
THEN
IF CR IN (
'EUR',
'CZK',
'USD'
)
THEN
OPEN P_CURSOR
FOR
SELECT G_AC AS GL_ACC,
Billing.Account AS ACC_Type
INTO
G_AC,
AC_t
FROM Billing
INNER JOIN invoice ON Billing.ACC_NO = invoice.ACC_NO;
END IF ;
END IF ;
END;
My aim here is to expand this code by using AC_t value from Billing.ACCount and retrieve what ever data that can be 'Private' or 'Public'.
To do this, I need to use case or IF statement, however when I use
Billing.ACCount, I got an error "not allowed in this context", for this reason I use synonym AC_t but this don't read values from Billing table unless I use it in WHERE clause.
ACC_NO
Account
1
Private
2
Public
Extended code:
IF BANKN = 'WLNV' AND AC_t = 'Private'
THEN
...
...
ELSIF IF BANKN = 'WLNV' AND AC_t = 'Public'
THEN
....
...
You cannot use SELECT ... INTO with a cursor and you need to declare a value for the ac_t variable (but since it is a column in the table you may want a WHERE clause in the cursor). Like this:
CREATE PROCEDURE TTEST1 (
p_CR IN VARCHAR2,
p_BANKN IN VARCHAR2,
P_CURSOR OUT SYS_REFCURSOR
)
AS
BEGIN
IF p_BANKN = 'WLNV'
AND p_CR IN ( 'EUR', 'CZK', 'USD' )
THEN
OPEN P_CURSOR FOR
SELECT G_AC AS GL_ACC,
b.account AS ACC_Type
FROM Billing b
INNER JOIN invoice i
ON b.ACC_NO = i.ACC_NO
WHERE b.account = 'Private';
END IF;
END;
/
Which, if you have the sample data:
CREATE TABLE invoice (acc_no, g_AC) AS
SELECT 1, 2 FROM DUAL;
CREATE TABLE billing (acc_no, account) AS
SELECT 1, 'Private' FROM DUAL;
Then you can call the procedure and print the contents of the cursor using:
DECLARE
cur SYS_REFCURSOR;
v_g_ac INVOICE.G_AC%TYPE;
v_ac_t BILLING.ACCOUNT%TYPE;
BEGIN
ttest1('EUR', 'WLNV', cur);
LOOP
FETCH cur INTO v_g_ac, v_ac_t;
EXIT WHEN cur%NOTFOUND;
DBMS_OUTPUT.PUT_LINE( v_g_ac || ', ' || v_ac_t );
END LOOP;
CLOSE cur;
END;
/
Which outputs:
2, Private
db<>fiddle here

PL/SQL procedure, cursor, where clause

i ve got some database with customer id, names, surnames. I made procedure with some parameters, which includes cursor with parameters. And i want with that cursor show customer names, surnames, id. And i want show that, where i call procedure, and i for example write as parameters in procedure for example NULL NULL, it show me all record. Next if i write NULL, Surname, it show me records with that surnames. If i write firstname,NULL, it show record only records with that first name and if i write Firstname,lastname, it show me only that record which matching this. So my procedure works fine, but i need right where clause n cursor. This is my cursor
CREATE OR REPLACE PROCEDURE test_two(c_f_name VARCHAR2,c_l_name VARCHAR2) IS
CURSOR c2(f_name VARCHAR2,l_name VARCHAR2) IS
SELECT cus_id,cus_l_name,cus_f_name
FROM CUSTOMER
WHERE (cus_f_name IS NOT NULL AND (cus_f_name = f_name orcus_l_name
IS NULL))
AND (cus_l_name IS NOT NULL AND (cus_l_name = l_name or cus_f_name IS
NULL));
v_complex c2%ROWTYPE;
lv_show VARCHAR2(20);
f_name VARCHAR2(20) := c_f_name;
l_name VARCHAR2(20) := c_l_name;
BEGIN
open c2(f_name,l_name);
LOOP
FETCH c2 INTO v_complex;
dbms_output.put_line(v_complex.cus_id|| ' ' ||v_complex.cus_f_name|| ' '
||v_complex.cus_l_name);
EXIT WHEN c2%NOTFOUND;
END LOOP;
CLOSE c2;
END;
EVERYTHING IS IFNE IN THAT PROCEDURE BUT I NEED ONLY RIGHT WHERE CLAUSE! THANK YOU
You could use a combination of LIKE and NVL.
WHERE cus_f_name LIKE NVL(c_f_name, '%')
AND cus_l_name LIKE NVL(c_l_name, '%');
Explanation:
The function NVL returns the first parameter if it is not NULL.
Otherwise it returns the second parameter.

expression is of wrong type

I am trying to create a function that returns all values of the emp table Why do I get the error?
create or replace FUNCTION EMP_value
RETURN VARCHAR2
is
CURSOR a is select * from emp;
v_all emp%rowtype;
begin
open a;
LOOP
fetch a into v_all;
exit when a%notfound;
dbms_output.put_line(v_all.empno|| ' ' ||v_all.ename|| ' ' ||v_all.sal);
RETURN V_ALL;
end loop;
close a;
end;
Try to simplify your code as much as possible. If you want to return all the attributes of cursor from function, try using BULK collect and return it as complex data type. Here in this case its nested table type. Hope it helps.
--Create a schema level nested table type function
CREATE OR REPLACE TYPE emp_obj IS OBJECT
(
EMPNO NUMBER,
ENAME VARCHAR2(100),
SAL NUMBER,
MGR_NO NUMBER,
HIREDATE DATE
)
/
CREATE OR REPLACE TYPE emp_tab IS TABLE OF emp_obj
/
--Funtion to return all attributes from EMP tab
CREATE OR REPLACE FUNCTION EMP_value
RETURN emp_tab
AS
e_tab emp_tab;
begin
SELECT * BULK COLLECT INTO e_tab
FROM EMP;
RETURN e_tab;
end;
/

pl/sql displaying all columns of a table

employee table schema
employee(id, name, company, salary);
procedure created to display all the column values
create or replace procedure p1
IS
BEGIN
select * from employee;
END;
/
exe p1;
However, this does not display the data.
Your PL/SQL block is not valid, and won't even run. You need to either return the data back to the client, or if you're using SQL*Plus use dbms_output.put_line to print the query resultset.
create or replace procedure p1
IS
BEGIN
DBMS_OUTPUT.ENABLE;
FOR emp_rec in select * from employee LOOP
dbms_output.put_line('EMployee id: || emp_rec.emp_id || ' Name: ' || emp_rec ename);
END LOOP
END;
/
Change the column name suitably

How to use a comma-separated list of strings as pl/sql stored function parameter inside a "NOT IN" clause of a select statement

I have a list of comma-separated strings (from a user input) and I'd like to use this list as a parameter in a pl/sql stored function in a nested sql block using a "not in where clause".
I can't find an elegant way to make it work...
That's what I'm thinking of:
CREATE TABLE example ( somevalue VARCHAR(36) NOT NULL);
--
INSERT INTO example VALUES ('value1');
INSERT INTO example VALUES ('value2');
INSERT INTO example VALUES ('value3');
--
SELECT * FROM example;
--
CREATE OR REPLACE
FUNCTION resultmaker(
ignoreList IN VARCHAR2)
RETURN VARCHAR2
IS
result VARCHAR2(4000);
BEGIN
result := 'Here is my calculated result, using ignorelist=' || ignoreList || ':' || CHR(10);
FOR rec IN
(SELECT DISTINCT somevalue
FROM example
WHERE somevalue NOT IN resultmaker.ignoreList -- here's my issue, the NOT IN clause using the parameter value
)
LOOP
result := result || 'not in ignorelist: ' || rec.somevalue || CHR(10);
END LOOP;
result := result || '.' || CHR(10);
--
RETURN result;
END resultmaker;
/
--
-- simulate function call with user input 'value2, value3'
SELECT resultmaker('value2, value3') FROM dual; -- doesn't work
--
DROP TABLE example;
DROP FUNCTION resultmaker;
Just pass the parameter like '"value2","value3"' and have your statement replace the double quote with single quotes like REPLACE(#Param1,'"','''').
Call to function: SELECT * FROM Function1('"value2","value3"')
Inside function: NOT IN REPLACE(#Param1,'"','''')
In every case you should parse that input. As there is no built-in string tokenizer in PL/SQL (at least I couldn't find it) You may want to look into these options,
http://blog.tanelpoder.com/2007/06/20/my-version-of-sql-string-to-table-tokenizer/
Does PL/SQL have an equivalent StringTokenizer to Java's?
After you parsed the string, you may create a new string like:
not_in_statement varchar2(1000);
CURSOR c1 IS select token from tokenized_strings_table;
BEGIN
not_in_statement := '('
FOR rec IN c1 LOOP
not_in_statement := not_in_statement || '''||rec.token||'''||','
END LOOP
not_in_statement := not_in_statement||')'
END
SELECT DISTINCT somevalue
FROM example
WHERE somevalue NOT IN not_in_statement
You may need to make it dynamic SQL, I did not have time to try.
Here's my solution using dynamic sql for my original question above:
CREATE TABLE example ( somevalue VARCHAR(36) NOT NULL);
--
INSERT INTO example VALUES ('value1');
INSERT INTO example VALUES ('value2');
INSERT INTO example VALUES ('value3');
--
SELECT * FROM example;
--
CREATE OR REPLACE
FUNCTION resultmaker(
ignoreList IN VARCHAR2)
RETURN VARCHAR2
IS
result VARCHAR2(4000);
example_cursor sys_refcursor;
rec example.somevalue%type;
BEGIN
result := 'Here is my calculated result, using ignorelist=' || ignoreList || ':' || CHR(10);
OPEN example_cursor FOR ( 'SELECT DISTINCT somevalue FROM example WHERE somevalue NOT IN (' || ignoreList || ')' );
FETCH example_cursor INTO rec;
WHILE example_cursor%found
LOOP
result := result || 'not in ignorelist: ' || rec || CHR(10);
FETCH example_cursor INTO rec;
END LOOP;
CLOSE example_cursor;
result := result || '.' || CHR(10);
--
RETURN result;
END resultmaker;
/
--
-- simulate function call with user input 'value2', 'value3'
SELECT resultmaker('''value2'', ''value3''') FROM dual;
--
DROP TABLE example;
DROP FUNCTION resultmaker;
The classic and probably correct solution would be to use PL/SQL table passing it as prameter...
There are some good solutions at asktom.oracle.com regarding taking a string of values and dynamically creating an IN clause for them:
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:210612357425

Resources