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
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!
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;
/
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.
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;
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.