Is this the best way to handle this insert, such that columns test1 and test2 are always equal?
CREATE SEQUENCE seq_temp
START WITH 1
INCREMENT BY 1
CACHE 50
NOCYCLE;
CREATE TABLE test_tbl (
test1 NUMBER,
test2 NUMBER
);
INSERT INTO test_tbl
SELECT
seq_temp.nextval,
seq_temp.currval
FROM dual;
It makes no difference - you must use nextval for at least one column, but for the other column nextval and currval will be the same value.
In other words, all the following statements will have the same effect:
SELECT seq_temp.nextval, seq_temp.currval FROM dual;
SELECT seq_temp.nextval, seq_temp.nextval FROM dual;
SELECT seq_temp.currval, seq_temp.nextval FROM dual;
Related
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,
...
...
How to add an extra column (say column_2) in the below INTO section of my code along with my Column_1. I assume we can do that by adding comma (,) and just add column_2 (like this INTO :new.Column_1, new.column_2). I'm missing something?
create or replace trigger trigger_name
BEFORE INSERT
ON table_name
FOR EACH ROW
BEGIN
SELECT SEQUENCE_NUMBER.NEXTVAL
INTO :new.Column_1
FROM dual;
END;
It is easy to confirm whether you are right (or wrong). I hope you got the answer during the past 6 hours. If not, here's an example:
SQL> create table test
2 (id number,
3 datum date);
Table created.
SQL> create sequence seq_test;
Sequence created.
SQL> create or replace trigger trg_bi_test
2 before insert on test
3 for each row
4 begin
5 select seq_test.nextval, sysdate
6 into :new.id, :new.datum
7 from dual;
8 end;
9 /
Trigger created.
SQL> insert into test (id) values (-1);
1 row created.
SQL> select * From test;
ID DATUM
---------- -------------------
1 21.06.2019 21:54:08
SQL>
I am trying to create a trigger in oracle like blow:
CREATE OR REPLACE TRIGGER TRIGGER_VC_PART_LIST
BEFORE INSERT ON VC_PART_LIST FOR EACH ROW
BEGIN
SELECT VC_PART_LIST_SEQ.NEWTVAL INTO :new.SEQ_ID FROM dual;
END;
/
anyone can help me?Thx.
In sequence to fetch the next value use NEXTVAL . Below is the correct syntax
CREATE OR REPLACE TRIGGER TRIGGER_VC_PART_LIST
BEFORE INSERT
ON VC_PART_LIST
FOR EACH ROW
BEGIN
SELECT VC_PART_LIST_SEQ.NEXTVAL INTO :new.SEQ_ID FROM DUAL;
END;
There are few issues in your code.
1) VC_PART_LIST_SEQ.NEWTVAL there is nothing called NEWTVAL in Oracle. It should be Nextval.
2) There is no need for a SQL statement.
See demo:
Trigger:
CREATE OR REPLACE TRIGGER TRIGGER_VC_PART_LIST
BEFORE INSERT
ON VC_PART_LIST
FOR EACH ROW
BEGIN
:new.SEQ_ID := VC_PART_LIST_SEQ.NEXTVAL;
END;
/
Table:
create table VC_PART_LIST (SEQ_ID number,
VC_VTC varchar2(20), PART_NO varchar2(20), CONSUME_QTY varchar2(20));
Sequence
create sequence VC_PART_LIST_SEQ start with 1 increment by 1;
Insertion:
INSERT INTO VC_PART_LIST (VC_VTC, PART_NO, CONSUME_QTY)
VALUES ('6175SMFGD132000D', 'SC25R136', '11');
Commit;
Selection:
SQL> select * from VC_PART_LIST;
SEQ_ID VC_VTC PART_NO CONSUME_QTY
---------- -------------------- -------------------- --------------------
1 6175SMFGD132000D SC25R136 11
I am using the following TRIGGER to Insert in my TEST Table:
create or replace
TRIGGER TRG_CYCLE
BEFORE INSERT ON TEST_CYCLE
FOR EACH ROW
BEGIN
IF :NEW.LOGID IS NULL
THEN SELECT SEQ_CYCLE.nextval INTO :NEW.LOGID from dual;
END IF;
END;
SEQ_CYCLE is the Sequence. Now I have to use the CYCLE option in order to start with 1 after the MAX_VALUE is reached. Since I don't want duplicate LOGIDs I want to do an UPDATE if the LOGID exists, if not an INSERT. Can I do this inside the Trigger?
If I understand well, you may need an INSTEAD OF trigger; to build such a trigger you need to create a VIEW over your table and build the trigger on this view.
For example, say you have:
create sequence SEQ_CYCLE maxValue 3 cycle nocache;
create table TEST_CYCLE ( logId number, someColumn varchar2(20));
You can create a view and a trigger over the view:
create or replace view v_test_cycle as select * from test_cycle;
create or replace trigger trgCycle
instead of insert on v_test_cycle
for each row
declare
vCheck number;
vSeqVal number := SEQ_CYCLE.nextVal;
begin
select count(*)
into vCheck
from v_test_cycle
where logId = vSeqVal;
--
if vCheck = 0 then
insert into test_cycle(logId, someColumn) values ( vSeqVal, :NEW.someColumn);
else
update test_cycle
set someColumn = :NEW.someColumn
where logId = vSeqVal;
end if;
end;
If you do the INSERTs on the view, this is what you get:
SQL> select * from test_cycle;
no rows selected
SQL> insert into v_test_cycle(someColumn) values('some value 1');
1 row created.
SQL> insert into v_test_cycle(someColumn) values('some value 2');
1 row created.
SQL> insert into v_test_cycle(someColumn) values('some value 3');
1 row created.
SQL> insert into v_test_cycle(someColumn) values('some value 4');
1 row created.
SQL> insert into v_test_cycle(someColumn) values('some value 5');
1 row created.
SQL> select * from test_cycle;
LOGID SOMECOLUMN
---------- --------------------
1 some value 4
2 some value 5
3 some value 3
SQL>
Is it possible to check the count of a table before any changes happen and the count after the insert and match them inside the same trigger?
for ex: old.count and new.count (before and after insert) ?
old.count and new.count (before and after insert)
Nothing stops you from using SELECT COUNT(*) in a before insert trigger. Of course, you won't do it in a after insert trigger, since a select count(*) on the same table on which an after trigger is defined would throw mutating table error. One way is autonomous transaction. But, in your case, it isn't that complex.
You could define a BEFORE INSERT TRIGGER and take the table count. The after insert count could be taken manually after the actual insert is done.
For example, I have a table t1 with one row. I have defined a before insert trigger on it, which would give me the table count before the insert happens.
SQL> DROP TABLE t1 PURGE;
Table dropped.
SQL>
SQL> CREATE TABLE t1 (A NUMBER);
Table created.
SQL>
SQL> INSERT INTO t1 VALUES (1);
1 row created.
SQL>
SQL> SELECT * FROM t1;
A
----------
1
SQL>
SQL> CREATE OR REPLACE TRIGGER trg
2 BEFORE INSERT
3 ON t1
4 FOR EACH ROW
5
6 DECLARE
7 val number;
8 BEGIN
9 SELECT COUNT(*)
10 INTO val
11 FROM t1;
12
13 DBMS_OUTPUT.PUT_LINE('TABLE COUNT BEFORE INSERT = '||val);
14
15 END;
16 /
Trigger created.
SQL>
SQL> set serveroutput on
SQL> INSERT INTO t1 VALUES (1);
TABLE COUNT BEFORE INSERT = 1
1 row created.
SQL>
SQL> SELECT COUNT(*) FROM t1;
COUNT(*)
----------
2
SQL>
So, you see TABLE COUNT BEFORE INSERT = 1 and then after insert the count is 2.