PLSQL Selecting from table using an array into a variable - sql

I am trying to select some records from a table using an array into the variable init_av_days but its not working out. init_av_days is to be committed to another table after this select query. How best do you suggest i do this?
declare
myarray APEX_APPLICATION_GLOBAL.VC_ARR2;
init_av_days varchar2(10);
begin
myarray := APEX_UTIL.STRING_TO_TABLE(:P592_AVAILABILITY_DAYS);
For i in 1.. myarray.count loop
select availability_days
into init_av_days
from sl_available_days
where location_code = :P592_LOCATION_CODE
and availability_days = myarray(i);
end loop;
end;

init_av_days is to be committed to another table after this select query
Best? Skip PL/SQL entirely, I'd say. Something like this:
insert into another_table (some_column)
select availability_days
from sl_available_days
where location_code in = (select regexp_substr(:P592_LOCATION_CODE, '[^:]+', 1, level)
from dual
connect by level <= regexp_count(:P592_LOCATION_CODE, ':') + 1
)
and availability_days = <I don't know what APEX_APPLICATION_GLOBAL.VC_ARR2 contains>
This code should be fixed because I don't know the last condition; if you know how, do it. If not, explain what's in vcc_arr2, maybe we can assist.

Related

How to create a Procedure with a specific WITH clause in Oracle?

I have a problem by creating a Procdure with a specific WITH clause. I use an Oracle database. I need a temp table for mapping specific values during time of execution.
In addition I have the following Oracle procedure. This Procedure will be created and executed by bringing into database:
How can I create this kind of Oracle SQL Procedure? Many thanks for helping me!
Use your WITH clause in a cursor FOR loop in your procedure:
DECLARE
PROCEDURE myProcedure(pinSchema IN VARCHAR2) AS
BEGIN
FOR aRow IN (WITH t AS (SELECT 'myFirstOldSchema' AS OLD_SCHEMA,
'myFirstNewSchema' AS NEW_SCHEMA
FROM DUAL UNION ALL
SELECT 'mySecondOldSchema' AS OLD_SCHEMA,
'mySecondNewSchema' AS NEW_SCHEMA
FROM DUAL UNION ALL
SELECT 'myThirdOldSchema' AS OLD_SCHEMA,
'myThirdNewSchema' AS NEW_SCHEMA
FROM DUAL)
SELECT t.*
FROM t
WHERE t.OLD_SCHEMA = pinSchema)
LOOP
-- Here a specific value from column "OLD_SCHEMA" must be inserted
EXECUTE IMMEDIATE 'INSERT INTO ' || aRow.OLD_SCHEMA ||
'.myTable(column_1, column_2, column_3)
(SELECT extern_column_1,
extern_column_2,
extern_column_3
FROM ' || aRow.NEW_SCHEMA || '.myExternTable)';
END LOOP;
END myProcedure;
BEGIN
FOR S IN (SELECT * FROM ROOT_SCHEMA.myTableWithSchema)
LOOP
-- First loop S.mySchemata represent the value 'myFirstOldSchema'
-- Second loop S.mySchemata represent the value 'mySecondOldSchema'
-- Third loop S.mySchemata represent the value 'myThirdOldSchema'
myProcedure(S.mySchemata);
END LOOP
COMMIT;
END;
Not tested on animals - you'll be first!

PLSQL Select more than one values and put it into more than one variable

is it possible to write a PLSQL Select Into Statement for many values?
Pseudocode:
SELECT X,Y,Z INTO v1,v2,v3 FROM.....
If so, can anyone show me an example?
You can use INTO clause for more than 1 variables. I have created a sample block for you.
declare
x int;
y int;
z int;
begin
select 1,2,3 into x,y,z from dual;
dbms_output.Put_line('x='||x||',y='||y||',z='||z);
end;
I know you are asking here about an INSERT INTO statement, but another option I would like to show here is the use of a cursor.
DECLARE
-- Fetch the first 5 entries of the table.
CURSOR cTableA IS
SELECT ColumnA, ColumnB, ColumnC
FROM TableA
WHERE ROWNUM <= 5;
rTableA cTableA%ROWTYPE; --Not realy needed this time, but some think it is neat.
BEGIN
FOR rTableA IN cTableA LOOP
DBMS_OUTPUT.PUT_LINE('ColumnA: ' || rTableA.ColumnA);
DBMS_OUTPUT.PUT_LINE('ColumnB: ' || rTableA.ColumnB);
DBMS_OUTPUT.PUT_LINE('ColumnB: ' || rTableA.ColumnC);
END LOOP;
END;
/

How to store multiple rows in a variable in pl/sql function?

I'm writing a pl/sql function. I need to select multiple rows from select statement:
SELECT pel.ceid
FROM pa_exception_list pel
WHERE trunc(pel.creation_date) >= trunc(SYSDATE-7)
if i use:
SELECT pel.ceid
INTO v_ceid
it only stores one value, but i need to store all values that this select returns. Given that this is a function i can't just use simple select because i get error, "INTO - is expected."
You can use a record type to do that. The below example should work for you
DECLARE
TYPE v_array_type IS VARRAY (10) OF NUMBER;
var v_array_type;
BEGIN
SELECT x
BULK COLLECT INTO
var
FROM (
SELECT 1 x
FROM dual
UNION
SELECT 2 x
FROM dual
UNION
SELECT 3 x
FROM dual
);
FOR I IN 1..3 LOOP
dbms_output.put_line(var(I));
END LOOP;
END;
So in your case, it would be something like
select pel.ceid
BULK COLLECT INTO <variable which you create>
from pa_exception_list
where trunc(pel.creation_Date) >= trunc(sysdate-7);
If you really need to store multiple rows, check BULK COLLECT INTO statement and examples. But maybe FOR cursor LOOP and row-by-row processing would be better decision.
You may store all in a rowtype parameter and show whichever column you want to show( assuming ceid is your primary key column, col1 & 2 are some other columns of your table ) :
SQL> set serveroutput on;
SQL> declare
l_exp pa_exception_list%rowtype;
begin
for c in ( select *
from pa_exception_list pel
where trunc(pel.creation_date) >= trunc(SYSDATE-7)
) -- to select multiple rows
loop
select *
into l_exp
from pa_exception_list
where ceid = c.ceid; -- to render only one row( ceid is primary key )
dbms_output.put_line(l_exp.ceid||' - '||l_exp.col1||' - '||l_exp.col2); -- to show the results
end loop;
end;
/
SET SERVEROUTPUT ON
BEGIN
FOR rec IN (
--an implicit cursor is created here
SELECT pel.ceid AS ceid
FROM pa_exception_list pel
WHERE trunc(pel.creation_date) >= trunc(SYSDATE-7)
)
LOOP
dbms_output.put_line(rec.ceid);
END LOOP;
END;
/
Notes from here:
In this case, the cursor FOR LOOP declares, opens, fetches from, and
closes an implicit cursor. However, the implicit cursor is internal;
therefore, you cannot reference it.
Note that Oracle Database automatically optimizes a cursor FOR LOOP to
work similarly to a BULK COLLECT query. Although your code looks as if
it fetched one row at a time, Oracle Database fetches multiple rows at
a time and allows you to process each row individually.

looping and executing dynamic query in Oracle

I'm having some trouble truncating some tables that get generated in my base.
The table names get saved and I can do it manually, but I wanted to see if it could be automated until its fixed.
What I've done so far is get all the table names and a id/number into my own help table. My errors begin around the loop/Execute immediate where im not sure how to use the data I've gotten in the syntax and i cant find any similar examples.
create table HlpTruncTable as SELECT SUBSTR(argument, 3) as tblName, rownum as Nr
FROM tblLogHlp
WHERE status = 'E' and argument like '0,awfh%' and LAST_UPDATE <= ADD_MONTHS(sysdate,-1);
for i in 1..(select max(nr) from HlpTruncTable) LOOP
execute immediate TRUNCATE TABLE (select tblName from HlpTruncTable where nr = (i));
END LOOP;
drop table hlpTruncTable;
I would do it like this:
declare
cursor HlpTruncTable is
SELECT SUBSTR(argument, 3) as tblName
FROM tblLogHlp
WHERE status = 'E' and argument like '0,awfh%' and LAST_UPDATE <= ADD_MONTHS(sysdate,-1);
BEGIN
FOR aTable IN HlpTruncTable LOOP
execute immediate 'TRUNCATE TABLE '||aTable.tblName;
END LOOP;
END;

Oracle SQL - Check duplicates in whole table

I have a table with columns
BIN_1_1
BIN_1_2
BIN_1_3
all the way to BIN_10_10
The user enter a value, and the value needs to be checked in all the columns starting from BIN_1_1 to BIN_10_10.
If there is a duplicate value, it prints a msg and gets out of the procedure / function.
How do I go about this?
Do you mean something like this?
create or replace
procedure check_duplicate( p_val yourtable.bin_1_1%type) is
v_dupl number;
begin
begin
select 1 into v_dupl from yourtable
where p_val in (bin_1_1, bin_1_2, ... bin_10_10) and rownum <=1;
exception
when no_data_found
then v_dupl := 0;
end;
if v_dupl = 1
then
dbms_output.put_line('your message about duplication');
return;
else
dbms_output.put_line('here you can do anything');
end if;
end;
Try this query,
INSERT INTO yourTable values ('your values') where
WHERE BIN_1_1 NOT IN (
SELECT bins FROM (
SELECT BIN_1_1 FROM yourTable
UNION
SELECT BIN_1_2 FROM yourTable
UNION
SELECT BIN_1_3 FROM yourTable
) AS bins
)
P.S. I din't run this query.
Unpivot your table, then it's easy. You may want to write a query that will write the query below for you. ("Dynamic" SQL just to save yourself some work.)
select case when count(*) > 1 then 'Duplicate Found' end as result
from ( select *
from your_table
unpivot (val for col in (BIN_1_1, BIN_1_2, ........, BIN_10_10))
)
where val = :user_input;
Here :user_input is a bind variable - use whatever mechanism works for you (end-user interface, SQL Developer, whatever).
You need to decide what outcome you want when the value is not duplicated in the table - you didn't mention anything about that.