Is there a way to accept comma separated input in PLSQL - oracle

I am trying to confirm if it's acceptable to provide a comma separated input through a prompt in PLSQL query. For example the input to be like order_no = 12345;67890;09876
Thanks in advance!
Here is my code:
select order_no
from CUSTOMER_ORDER_JOIN
where order_no like nvl('&Order_no', '%')

Generally speaking, no, you can't do that because Oracle considers string you enter as a whole. For example, this query returns nothing because there's no job whose name is Clerk,Manager (both values).
SQL> with emp (ename, job) as
2 (select 'Smith', 'Clerk' from dual union all
3 select 'Allen', 'Salesman' from dual union all
4 select 'Ward' , 'Salesman' from dual union all
5 select 'Jones', 'Manager' from dual
6 )
7 select ename, job
8 from emp
9 where job in ('&par_jobs');
Enter value for par_jobs: Clerk,Manager
no rows selected
SQL>
However, if you have Apex installed in your database, and that Apex version supports apex_string.split function, then you can do something which is close to what you're looking for:
SQL> with emp (ename, job) as
2 (select 'Smith', 'Clerk' from dual union all
3 select 'Allen', 'Salesman' from dual union all
4 select 'Ward' , 'Salesman' from dual union all
5 select 'Jones', 'Manager' from dual
6 )
7 select ename, job
8 from emp
9 where job in (select * from table(apex_string.split('&par_jobs', ',')));
Enter value for par_jobs: Clerk,Manager
ENAME JOB
----- --------
Smith Clerk
Jones Manager
SQL>
Otherwise, you'll have to type a little bit more to achieve that, e.g.
SQL> with emp (ename, job) as
2 (select 'Smith', 'Clerk' from dual union all
3 select 'Allen', 'Salesman' from dual union all
4 select 'Ward' , 'Salesman' from dual union all
5 select 'Jones', 'Manager' from dual
6 )
7 select ename, job
8 from emp
9 where job in (select regexp_substr('&&par_jobs', '[^,]+', 1, level)
10 from dual
11 connect by level <= regexp_count('&&par_jobs', ',') + 1
12 );
Enter value for par_jobs: Clerk,Manager
ENAME JOB
----- --------
Smith Clerk
Jones Manager
SQL>
Basically, YMMV.

Related

How to insert values to newly added column

I am new to oracle thus this question.
There is a table already existed and I have added a new column to it.
There are 5 rows and I do not want to use update table with where clause to insert the values one by one in the new column. Is there a statement like INSERT ALL to insert the values into the new column in one shot ?
Thanks
You can also use something like below which in-effect I would say is multiple update only, wrapped in single statement.
SQL> select * from test_upd;
ID1 ID2
---------- ----------
1
2
3
4
SQL> update test_upd a set a.id2 =
2 (select
3 case
4 when id1=1 then 100
5 when id1=2 then 200
6 when id1=3 then 300
7 else 5000 end
8 from test_upd b
9 where a.id1=b.id1);
4 rows updated.
SQL> select * from test_upd;
ID1 ID2
---------- ----------
1 100
2 200
3 300
4 5000
Use a MERGE statement:
MERGE INTO your_table dst
USING (
SELECT 1 AS id, 'aaa' AS newvalue FROM DUAL UNION ALL
SELECT 2, 'bbb' FROM DUAL UNION ALL
SELECT 3, 'ccc' FROM DUAL UNION ALL
SELECT 4, 'ddd' FROM DUAL UNION ALL
SELECT 5, 'eee' FROM DUAL
) src
ON (dst.id = src.id)
WHEN MATCHED THEN
UPDATE SET value = src.newvalue;
Which, if you have the table:
CREATE TABLE your_table (id, value) AS
SELECT 1, CAST(NULL AS VARCHAR2(3)) FROM DUAL UNION ALL
SELECT 2, NULL FROM DUAL UNION ALL
SELECT 3, NULL FROM DUAL UNION ALL
SELECT 4, NULL FROM DUAL UNION ALL
SELECT 5, NULL FROM DUAL;
Then, after the MERGE, the table contains:
ID
VALUE
1
aaa
2
bbb
3
ccc
4
ddd
5
eee
db<>fiddle here

PL/SQL program using CURSOR for frequency distribution in table

finaltableA has two columns WORDS, WCOUNTS. The program should insert every word of intitaltableA into finaltableA exactly once. In the column WCOUNTS the program should put how often the word occurs.
intitaltableA
COVID
is
a
disease
COVID
can
be
treated
with
antibodies
COVID
is
a
serious
disease
there
is
a
vaccination
available
for
COVID
finaltableA should look like this -
WORDS
WCOUNTS
a
3
antibodies
1
available
1
be
1
can
1
COVID
4
disease
2
for
1
is
3
serious
1
there
1
treated
1
vaccination
1
with
1
I should use a cursor to insert and update the table. I am new to PL/SQL.
It is quite obvious that you can do this without any cursor in PLSQL, so I guess that means that you are trying to solve a homework problem or a training question. Anyway, here you can see two simple options to get the result you want, with and without PLSQL.
Option 1 - Without PLSQL
with x ( words )
as
(
select 'COVID' from dual union all
select 'is' from dual union all
select 'a' from dual union all
select 'disease' from dual union all
select 'COVID' from dual union all
select 'can' from dual union all
select 'be' from dual union all
select 'treated' from dual union all
select 'with' from dual union all
select 'antibodies' from dual union all
select 'COVID' from dual union all
select 'is' from dual union all
select 'a' from dual union all
select 'serious' from dual union all
select 'disease' from dual union all
select 'there' from dual union all
select 'is' from dual union all
select 'a' from dual union all
select 'vaccination' from dual union all
select 'available' from dual union all
select 'for' from dual union all
select 'COVID' from dual
)
select words, count(words) as counter
from x
group by words
order by 2 desc;
If you execute it, it gives you the output you want
SQL> with x ( words )
2 as
3 (
4 select 'COVID' from dual union all
5 select 'is' from dual union all
6 select 'a' from dual union all
7 select 'disease' from dual union all
8 select 'COVID' from dual union all
9 select 'can' from dual union all
10 select 'be' from dual union all
11 select 'treated' from dual union all
12 select 'with' from dual union all
13 select 'antibodies' from dual union all
14 select 'COVID' from dual union all
15 select 'is' from dual union all
16 select 'a' from dual union all
17 select 'serious' from dual union all
18 select 'disease' from dual union all
19 select 'there' from dual union all
20 select 'is' from dual union all
21 select 'a' from dual union all
22 select 'vaccination' from dual union all
23 select 'available' from dual union all
24 select 'for' from dual union all
25 select 'COVID' from dual
26 )
27 select words, count(words) as counter
28 from x
29 group by words
30* order by 2 desc
SQL> /
WORDS COUNTER
----------- ----------
COVID 4
is 3
a 3
disease 2
there 1
available 1
for 1
serious 1
antibodies 1
can 1
vaccination 1
WORDS COUNTER
----------- ----------
treated 1
be 1
with 1
14 rows selected.
Option 2 - Using PLSQL and a CURSOR
In the below example, I'm going to use dbms_output to show the results. Keep in mind that here there are dozens of ways to do the same, I am just using the simplest one I can think of.
SQL> create table t ( words varchar2(40) ) ;
Table created.
SQL> insert into t
2 with x ( words )
3 as
4 (
5 select 'COVID' from dual union all
6 select 'is' from dual union all
7 select 'a' from dual union all
8 select 'disease' from dual union all
9 select 'COVID' from dual union all
10 select 'can' from dual union all
11 select 'be' from dual union all
12 select 'treated' from dual union all
13 select 'with' from dual union all
14 select 'antibodies' from dual union all
15 select 'COVID' from dual union all
16 select 'is' from dual union all
17 select 'a' from dual union all
18 select 'serious' from dual union all
19 select 'disease' from dual union all
20 select 'there' from dual union all
21 select 'is' from dual union all
22 select 'a' from dual union all
23 select 'vaccination' from dual union all
24 select 'available' from dual union all
25 select 'for' from dual union all
26 select 'COVID' from dual
27* ) select words from x
SQL> /
22 rows created.
SQL> commit ;
Commit complete.
SQL> declare
2 begin
3 for i in ( select words, count(words) as counter from t group by words order by 2 desc )
4 loop
5 dbms_output.put_line( 'Words: '||i.words||' - Wcount is: '||i.counter||' ');
6 end loop;
7* end;
SQL> /
Words: COVID - Wcount is: 4
Words: is - Wcount is: 3
Words: a - Wcount is: 3
Words: disease - Wcount is: 2
Words: antibodies - Wcount is: 1
Words: for - Wcount is: 1
Words: be - Wcount is: 1
Words: vaccination - Wcount is: 1
Words: can - Wcount is: 1
Words: available - Wcount is: 1
Words: treated - Wcount is: 1
Words: there - Wcount is: 1
Words: with - Wcount is: 1
Words: serious - Wcount is: 1
PL/SQL procedure successfully completed.

Oracle Apex Pivot sorting

I have an interactive report, which using Pivot, but I was trying to custom sort the report by row column of pivot "Age Group", but I couldn't.
I need this report in such this sorting:
How I can do that?
Thanks
Looks like you'd want to sort by the first digit(s), and then by age_group itself (as a string). Something like this (sample data in lines #1 - 10; query you might be interested in begins at line #11):
SQL> with test (age_group) as
2 (select 'wahine 45-64' from dual union all
3 select 'wahine 25-44' from dual union all
4 select 'rangtahi 15-24' from dual union all
5 select 'pepis 0_4' from dual union all
6 select 'pakeke 45-64' from dual union all
7 select 'pakeke 25-44' from dual union all
8 select 'N/A' from dual union all
9 select 'kuia 65+' from dual
10 )
11 select age_group
12 from test
13 order by to_number(regexp_substr(age_group, '\d+')), age_group;
AGE_GROUP
--------------
pepis 0_4
rangtahi 15-24
pakeke 25-44
wahine 25-44
pakeke 45-64
wahine 45-64
kuia 65+
N/A
8 rows selected.
SQL>

Like operator or with any other operator that can used

I want the records to be shown like BTN GLOBAL not BT airways.There should be no record like BT shops or BT cars or BT airways.Please guide with the query.
Would this help?
SQL> with test (col) as
2 (select 'BTN global' from dual union all
3 select 'BT airways' from dual union all
4 select 'BT shops' from dual union all
5 select 'BTX Little' from dual
6 )
7 select * From test
8 where not regexp_like(col, '^BT ');
COL
----------
BTN global
BTX Little
SQL>

Select Group on Department

I have data like below. I want to select those Emp_id where only HR is the only DEPT present. From the below, only 100994 and 100998 should be selected.
**EMP_ID DEPT**
100017 FIN
100017 HR
100017 ADMIN
100994 HR
100997 ADMIN
100997 FIN
100998 HR
100999 FIN
Here's one option:
SQL> with test (emp_id, dept) as
2 (select 100017, 'FIN' from dual union all
3 select 100017, 'HR' from dual union all
4 select 100017, 'ADMIN' from dual union all
5 select 100994, 'HR' from dual union all
6 select 100997, 'ADMIN' from dual union all
7 select 100997, 'FIN' from dual union all
8 select 100998, 'HR' from dual union all
9 select 100999, 'FIN' from dual
10 )
11 select emp_id
12 from test
13 group by emp_id
14 having min(dept) = max(dept)
15 and min(dept) = 'HR';
EMP_ID
----------
100998
100994
SQL>
I would recomment to use a subquery to count the records.
If records count for specific id is more than 1 then skip the id.
SELECT `emp_id`, `dept` FROM (
SELECT SUM(1) AS `count`, `emp_id`, `dept`
FROM `table1`
GROUP BY `emp_id`
) AS `derived`
WHERE `count` = 1 AND `dept` = 'HR'

Resources