how to generate sequence number in plsql in a cyclic way - oracle

I want to generate sequence number from 91 to 100 using oracle plsql code and if my sequence reaches 100 next value should be 91 again .
Please help

Ummm ... no. That's not a PL/SQL issue. You should generate a sequence that does what you described:
create sequence seq_ng minvalue 91 maxvalue 100 cycle nocache;
SQL> create sequence seq_ng minvalue 91 maxvalue 100 cycle nocache;
Sequence created.
SQL> select seq_ng.nextval from dual;
NEXTVAL
----------
91
SQL> select seq_ng.nextval from dual;
NEXTVAL
----------
92
<snip>
SQL> select seq_ng.nextval from dual;
NEXTVAL
----------
100
SQL> select seq_ng.nextval from dual;
NEXTVAL
----------
91 --> it starts over again
SQL>

Related

sequence exceeds maxvalue problem in oracle

I am facing an issue with respect to sequence exceeds maxvalue while using sequence during data migration of a large set of data.
How to overcome this issue.
Do I need to recreate the table or sequence max limit can be altered?
Create a sequence with MAXVALUE (that's what you have now):
SQL> create sequence seqa maxvalue 3;
Sequence created.
SQL> select seqa.nextval from dual;
NEXTVAL
----------
1
SQL> select seqa.nextval from dual;
NEXTVAL
----------
2
SQL> select seqa.nextval from dual;
NEXTVAL
----------
3
SQL> select seqa.nextval from dual;
select seqa.nextval from dual
*
ERROR at line 1:
ORA-08004: sequence SEQA.NEXTVAL exceeds MAXVALUE and cannot be instantiated
Error, as expected (that's what you also have). So, alter and set nomaxvalue:
SQL> alter sequence seqa nomaxvalue;
Sequence altered.
Now it works again:
SQL> select seqa.nextval from dual;
NEXTVAL
----------
4
If you are using a sequence as a value in your table to uniquely identify a row you may want to consider an IDENTITY column so that's 1 less object you have to worry about
create table t1(
seq_num integer GENERATED BY DEFAULT AS IDENTITY (START WITH 1) NOT NULL,
...
...

Implement a sequence that increments by value of a function

I am looking to create a simple sequence:
CREATE SEQUENCE supplier_seq
MINVALUE 1
START WITH 3
INCREMENT BY 4
CACHE 20000;
However, I want to semi-randomize the incrementing values with a function determined by some factors implemented on the java side.
I thought the first step for testing this might look something like this:
CREATE SEQUENCE supplier_seq
MINVALUE 1
START WITH 3
INCREMENT BY myfunction
CACHE 20000;
I tried this:
CREATE SEQUENCE supplier_seq
MINVALUE 1
START WITH 3
INCREMENT BY (declare
rtrnt number;
begin
rtrnt :=semiRandomize();
end;
)
CACHE 20000;
which I realize is ridiculous.. but there must be some way to do something like this. Any pointers?
How about this? Not really a sequence, but - might suit your needs. It is a function that selects a random number and stores it into a table with a primary key. If the number has already been used, it is skipped. The function checks whether all numbers have been used; if so, it raises an error.
In this example, I'm creating a 5-numbers "sequence" (so that it fails soon enough).
Table & function:
SQL> create table t_seq (supseq number constraint pk_tseq primary key);
Table created.
SQL> create or replace function f_supseq
2 return number
3 as
4 l_range number := 5; -- number of values in a "sequence"
5 l_seq number; -- a new "sequence" number
6 l_cnt number; -- number of used numbers
7 pragma autonomous_transaction;
8 begin
9 select count(*) into l_cnt from t_seq;
10 if l_cnt < l_range then
11 -- there are still some available numbers so - let's get them
12
13 -- don't let anyone mess with the table
14 lock table t_seq in exclusive mode;
15 while l_seq is null loop
16 begin
17 insert into t_seq (supseq) values
18 (round(dbms_random.value(1, l_range)))
19 returning supseq into l_seq;
20 exception
21 when dup_val_on_index then
22 -- that number has already been used; skip it
23 null;
24 end;
25 end loop;
26 commit;
27 else
28 raise_application_error(-20001, 'No more available numbers');
29 end if;
30
31 return l_seq;
32 end;
33 /
Function created.
Fetching random "sequence" values:
SQL> select f_supseq from dual;
F_SUPSEQ
----------
2
SQL> select f_supseq from dual;
F_SUPSEQ
----------
4
SQL> select f_supseq from dual;
F_SUPSEQ
----------
1
SQL> select f_supseq from dual;
F_SUPSEQ
----------
3
SQL> select f_supseq from dual;
F_SUPSEQ
----------
5
SQL> select f_supseq from dual;
select f_supseq from dual
*
ERROR at line 1:
ORA-20001: No more available numbers
ORA-06512: at "SCOTT.F_SUPSEQ", line 28
Table contents:
SQL> select * From t_seq;
SUPSEQ
----------
1
2
3
4
5
SQL>

Suppress CURSOR message from sqlplus output

I have a function that returns a refcursor for a given query.
I call the function like this. Although this is a simple query my actual query is more dynamic with other parameters for where clause.
select myfunction('select * from employees') as f from dual;
and it gives me the output
F
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
EMPLOYEE_ID FIRST_NAME LAST_NAME EMAIL PHONE_NUMBER HIRE_DAT JOB_ID SALARY COMMISSION_PCT MANAGER_ID DEPARTMENT_ID
----------- -------------------- ------------------------- ------------------------- -------------------- -------- ---------- ---------- -------------- ---------- -------------
198 Donald OConnell DOCONNEL 650.507.9833 20070621 SH_CLERK 2600 124 50
199 Douglas Grant DGRANT 650.507.9844 20080113 SH_CLERK 2600 124 50
200 Jennifer Whalen JWHALEN 515.123.4444 20030917 AD_ASST 4400 101 10
201 Michael Hartstein MHARTSTE 515.123.5555 20040217 MK_MAN 13000 100 20
202 Pat Fay PFAY 603.123.6666 20050817 MK_REP 6000 201 20
203 Susan Mavris SMAVRIS 515.123.7777 20020607 HR_REP 6500 101 40
204 Hermann Baer HBAER 515.123.8888 20020607 PR_REP 10000 101 70
I don't want these lines at the top and only want the cursor's output.
CURSOR STATEMENT : 1
How do I stop sqlplus or SQL developer from displaying it? what commands should I use?
That looks like a function that returns a ref cursor; is it?
SQL> create or replace function f_my (par_select in varchar2)
2 return sys_refcursor
3 is
4 l_rc sys_refcursor;
5 begin
6 open l_rc for par_select;
7 return l_rc;
8 end;
9 /
Function created.
Here's what you currently have:
SQL> select f_my('select * From dept') as f from dual;
F
--------------------
CURSOR STATEMENT : 1
CURSOR STATEMENT : 1
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
So, how to get rid of those CURSOR STATEMENT : 1 lines? It is SQLPlus that's displaying them (some other tool might not do it). But, as you use SQLPlus, here's how:
SQL> var v_rc refcursor
SQL> exec :v_rc := f_my('select * from dept')
PL/SQL procedure successfully completed.
SQL> print v_rc
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
SQL>
Thanks to Littlefoot's answer. I am able to extract only the rows from the table
using the following lines in my script.
SET FEEDBACK OFF
SET PAGES 0
VARIABLE c REFCURSOR
spool /mypath/somefile.csv
EXEC :c := myfunction('select * from employees')
PRINT c

I'm making PL/SQL trigger to student enrollment system, but have a terrible issue

I'm trying to make Enroll Student into Class by Trigger. I have two tables: Student and Subject
Student table
Stuno Stuname
****** *******
1001 James
1002 Jacob
1003 Misa
Subject table
Subno Subname
***** *******************
51 Computer science
52 Statistic
53 Engineering Electromagnetics
I created Enrollments table - it is empty.
Enrollments table
eno stuno subno
**** ****** *********
I want to get expected output is like
eno stuno subno
**** ****** *********
1 1001 51
2 1002 52
3 1003 53
but got only issue..... when writing
insert into Enrollments values(1,1001,51);
insert into Enrollments values(1,1001,51)
ERROR at line 1:
ORA-01403: no data found
ORA-06512: at "SCOTT.ENROLL", line 14
ORA-04088: error during execution of trigger 'SCOTT.ENROLL'
I know why issue. Because Enrollments table is empty...no data
I don't know how can data insert into table when Enrollments is empty in pl/sql.
this is my coding... please help me.....
drop trigger Enroll;
create or replace trigger Enroll
before insert or update
on Enrollments FOR EACH ROW
declare
p_snum student.Stuno%type;
p_ClassNum subject.subno%type;
p_num_current_enrolled NUMBER;
p_num_max_capacity NUMBER;
BEGIN
p_num_current_enrolled := 0;
p_num_max_capacity := 0 ;
SELECT Count(*) into p_num_current_enrolled
from Enrollments
where subno = p_ClassNum;
SELECT capacity into p_num_max_capacity
from subject
where subno = p_ClassNum;
IF p_num_current_enrolled < p_num_max_capacity THEN
insert into Enrollments values(null,p_snum, p_ClassNum);
dbms_output.put_line('수강 신청을 완료 하였습니다.');
ELSE
dbms_output.put_line('정원이 초과 하였습니다.');
END IF;
end;
/
It was select capacity ... that raised the error; you used p_ClassNum in the WHERE clause, and its value is unknown (NULL). It should be :new.subno, actually.
Here's an example of what you might do.
First, test case:
SQL> create table student (stuno number, stuname varchar2(20));
Table created.
SQL> insert into student
2 select 1001, 'james' from dual union all
3 select 1002, 'jacob' from dual union all
4 select 1003, 'misa' from dual;
3 rows created.
SQL> create table subject (subno number, subname varchar2(20), capacity number);
Table created.
SQL> insert into subject
2 select 51, 'compsci' , 2 from dual union all
3 select 52, 'statistic', 3 from dual;
2 rows created.
SQL> create table enrollments (eno number, stuno number, subno number);
Table created.
SQL>
Trigger:
SQL> create or replace trigger trg_Enroll_1
2 before insert on enrollments
3 for each row
4 declare
5 l_num_current_enrolled number;
6 l_capacity number;
7 begin
8 select count(*)
9 into l_num_current_enrolled
10 from enrollments
11 where subno = :new.subno;
12 select capacity
13 into l_capacity
14 from subject
15 where subno = :new.subno;
16
17 if l_num_current_enrolled >= l_capacity then
18 raise_application_error(-20000, 'No more room for that subject');
19 end if;
20 end;
21 /
Trigger created.
SQL>
Testing:
SQL> insert into enrollments (eno, stuno, subno)
2 values (1, 1001, 51);
1 row created.
SQL> insert into enrollments (eno, stuno, subno)
2 values (2, 1002, 51);
1 row created.
SQL> insert into enrollments (eno, stuno, subno)
2 values (3, 1003, 51);
insert into enrollments (eno, stuno, subno)
*
ERROR at line 1:
ORA-20000: No more room for that subject
ORA-06512: at "SCOTT.TRG_ENROLL_1", line 15
ORA-04088: error during execution of trigger 'SCOTT.TRG_ENROLL_1'
SQL>

How to call a Stored procedure with aggregate result in output?

I have a simple select query that needs to be put into a stored procedure.
The query takes in 3 parameters and displays 2 columns as result, one of them being an aggregate.
CREATE OR REPLACE PROCEDURE "B_SP_GET_TOTAL_CLOCKED_IN_TIME"
(
cv_1 IN OUT TYPES.cursorType,
p_PARENT_CLIENT_ID IN NUMBER DEFAULT 10000,
p_START_TIME IN NVARCHAR2,
p_END_TIME IN NVARCHAR2
)
AS
v_sql VARCHAR2(4000);
BEGIN
v_sql := 'SELECT b.CLIENT_NAME, ROUND(SUM((a.ENDTIME-a.STARTTIME)*24*60),2) TOTAL_CLOCKIN_TIME
FROM TIMESHEET a
INNER JOIN CLIENTS b ON a.CLIENT_ID = b.CLIENT_ID
INNER JOIN CLOCKACTIONS c ON c.ID = a.CLOCKACTIONID
WHERE a.STARTTIME > p_START_TIME AND a.ENDTIME < p_END_TIME AND b.PARENT_CLIENT_ID = p_PARENT_CLIENT_ID
GROUP BY b.CLIENT_NAME';
OPEN cv_1 FOR v_sql;
END;
I executed the stored procedure and it got compiled, with no issues.
How do i check if its working properly? As in how do I test it now?
The statement I used to test the above procedure can be found below:
execute B_SP_GET_TOTAL_CLOCKED_IN_TIME(10000,'04-01-2015 00:00:00','05-01-2015 00:00:00');
This was the error I got:
Error starting at line : 1 in command - execute B_SP_GET_TOTAL_CLOCKED_IN_TIME(10000,'04-01-2015 00:00:00','05-01-2015 00:00:00')
Error report - ORA-06550: line 1, column 7:
PLS-00306: wrong number or types of arguments in call to 'B_SP_GET_TOTAL_CLOCKED_IN_TIME'
ORA-06550: line 1, column 7: PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
There is not need of (ab)using dynamic SQL. You could simple use OPEN FOR SELECT and use a SYS_REFCURSOR.
For example,
SQL> CREATE OR REPLACE
2 PROCEDURE p_get_emp(
3 p_deptno IN emp.deptno%TYPE,
4 p_ref OUT SYS_REFCURSOR)
5 AS
6 BEGIN
7 OPEN p_ref FOR
8 SELECT ename,
9 empno,
10 deptno
11 FROM emp
12 WHERE deptno = p_deptno
13 ORDER BY empno;
14 END p_get_emp;
15 /
Procedure created.
SQL>
SQL> sho err
No errors.
SQL>
Procedure created without any errors. Let's test it:
SQL> var p_ref refcursor
SQL>
SQL> EXEC p_get_emp (30, :p_ref);
PL/SQL procedure successfully completed.
SQL>
SQL> print p_ref
ENAME EMPNO DEPTNO
---------- ---------- ----------
ALLEN 7499 30
WARD 7521 30
MARTIN 7654 30
BLAKE 7698 30
TURNER 7844 30
JAMES 7900 30
6 rows selected.
SQL>

Resources