I do have 3 tables. I want to generate ID for each below table and that should be unique across each table.
Table1 ID - primary
ID
1 -> 2 -> 3
Table2 ID - primary
ID
4 -> 5
Table3 ID - primary
ID
6 -> 7 -> 8
Whenever a new entry is made to the above tables it should generate unique values across the tables
For next time when I want to insert 2 records to table 1 it should be
Table1 ID - primary
ID
9 -> 10.
Do we can create a trigger to accomplish this in Oracle
Use a trigger on each table and create a Sequence
CREATE SEQUENCE seq
START WITH 1
INCREMENT BY 1
NOCACHE
NOCYCLE;
Then on the trigger on insert do something like:
select seq.nextval
into :new.id
from dual;
This was asked before. Look here
CREATE OR REPLACE TRIGGER my_trigger
BEFORE INSERT
ON qname
FOR EACH ROW
-- Optionally restrict this trigger to fire only when really needed
WHEN (new.qname_id is null)
DECLARE
v_id qname.qname_id%TYPE;
BEGIN
-- Select a new value from the sequence into a local variable. As David
-- commented, this step is optional. You can directly select into :new.qname_id
SELECT qname_id_seq.nextval INTO v_id FROM DUAL;
-- :new references the record that you are about to insert into qname. Hence,
-- you can overwrite the value of :new.qname_id (qname.qname_id) with the value
-- obtained from your sequence, before inserting
:new.qname_id := v_id;
END my_trigger;
Related
How to increment the value of the unique constraint column value in ORACLE, in the select statement.
For example, in a table 'BILLING_TABLE' - column BLNG_Sk is the unique key (Autoincremented).
So while inserting a new record into the BILLING_TABLE, for the column BLNG_SK we need to give the value (Which is the increment by 1 from the present max value.)
For example, if BLNG_SK max value is 12321.
new record should be 12322.
how to achieve this in Oracle?
Oracle has a SEQUENCE object which provides the functionality you require.
You create one using the CREATE SEQUENCE SQL statement.
The Oracle documentation provides all the required information and the documentation is available via Oracle's Web site.
Assuming you are on Oracle 12.1 or later, define it as an identity column and do not pass any value when inserting:
create table testtable
( test_id number generated always as identity
constraint testtable_pk primary key
, othercol varchar2(10) );
insert into testtable (othercol) values ('Demo');
select * from testtable;
TEST_ID OTHERCOL
---------- ----------
1 Demo
insert into testtable (othercol) values ('Demo #2');
select * from testtable;
TEST_ID OTHERCOL
---------- ----------
1 Demo
2 Demo #2
Try creating a sequence and a trigger. This is the case when you provide the value manually.
CREATE SEQUENCE dept_seq START WITH 12322;
Trigger definition:
CREATE OR REPLACE TRIGGER dept_bir
BEFORE INSERT ON BILLING_TABLE
FOR EACH ROW
BEGIN
SELECT dept_seq.NEXTVAL
INTO :new.id
FROM dual;
END;
/
This question already has answers here:
How to create id with AUTO_INCREMENT on Oracle?
(18 answers)
Closed 8 years ago.
I am facing issue while inserting multiple row in one go into table because column id has primary key and its created based on sequence.
for ex:
create table test (
iD number primary key,
name varchar2(10)
);
insert into test values (123, 'xxx');
insert into test values (124, 'yyy');
insert into test values (125, 'xxx');
insert into test values (126, 'xxx');
The following statement creates a constraint violoation error:
insert into test
(
select (SELECT MAX (id) + 1 FROM test) as id,
name from test
where name='xxx'
);
This query should insert 3 rows in table test (having name=xxx).
You're saying that your query inserts rows with primary key ID based on a sequence. Yet, in your insert/select there is select (SELECT MAX (id) + 1 FROM test) as id, which clearly is not based on sequence. It may be the case that you are not using the term "sequence" in the usual, Oracle way.
Anyway, there are two options for you ...
Create a sequence, e.g. seq_test_id with the starting value of select max(id) from test and use it (i.e. seq_test_id.nextval) in your query instead of the select max(id)+1 from test.
Fix the actual subselect to nvl((select max(id) from test),0)+rownum instead of (select max(id)+1 from test).
Please note, however, that the option 2 (as well as your original solution) will cause you huge troubles whenever your code runs in multiple concurrent database sessions. So, option 1 is strongly recommended.
Use
insert into test (
select (SELECT MAX (id) FROM test) + rownum as id,
name from test
where name='xxx'
);
as a workaround.
Of course, you should be using sequences for integer-primary keys.
If you want to insert an ID/Primary Key value generated by a sequence you should use the sequence instead of selecting the max(ID)+1.
Usually this is done using a trigger on your table wich is executed for each row. See sample below:
CREATE TABLE "MY_TABLE"
(
"MY_ID" NUMBER(10,0) CONSTRAINT PK_MY_TABLE PRIMARY KEY ,
"MY_COLUMN" VARCHAR2(100)
);
/
CREATE SEQUENCE "S_MY_TABLE"
MINVALUE 1 MAXVALUE 999999999999999999999999999
INCREMENT BY 1 START WITH 10 NOCACHE ORDER NOCYCLE NOPARTITION ;
/
CREATE OR REPLACE TRIGGER "T_MY_TABLE"
BEFORE INSERT
ON
MY_TABLE
REFERENCING OLD AS OLDEST NEW AS NEWEST
FOR EACH ROW
WHEN (NEWEST.MY_ID IS NULL)
DECLARE
IDNOW NUMBER;
BEGIN
SELECT S_MY_TABLE.NEXTVAL INTO IDNOW FROM DUAL;
:NEWEST.MY_ID := IDNOW;
END;
/
ALTER TRIGGER "T_MY_TABLE" ENABLE;
/
insert into MY_TABLE (MY_COLUMN) values ('DATA1');
insert into MY_TABLE (MY_COLUMN) values ('DATA2');
insert into MY_TABLE (MY_ID, MY_COLUMN) values (S_MY_TABLE.NEXTVAL, 'DATA3');
insert into MY_TABLE (MY_ID, MY_COLUMN) values (S_MY_TABLE.NEXTVAL, 'DATA4');
insert into MY_TABLE (MY_COLUMN) values ('DATA5');
/
select * from MY_TABLE;
I have table with two rows which one ID with auto increment and there are much row last number ID is 89. And then I truncate data/row in the table. And then I insert row again.
But number ID from 90 not from 1 (one). If in mysql if I truncate data in table auto increment start from 1 (one) again. So how in oracle I want to ID autoincrement from one again. Thanx.
Below step when I create table:
// create table;
CREATE TABLE tes (
id NUMBER NULL,
ip_address varchar2(25) NOT NULL
PRIMARY KEY (id)
);
// and create increment;
CREATE SEQUENCE tes_sequence START WITH 1 INCREMENT BY 1;
// and create trigger;
CREATE OR REPLACE TRIGGER tes_trigger
BEFORE INSERT
ON tes
REFERENCING NEW AS NEW
FOR EACH ROW
BEGIN
SELECT tes_sequence.nextval INTO :NEW.ID FROM dual;
END;
Oracle sequence is a separate object and is not connected with table. If you need to start sequence after truncating a table you need to alter the sequence. Have a look here: How do I reset a sequence in Oracle?
In my vb application I want an autogenerated id of alphanumeric characters, like prd100. How can I increment it using Oracle as backend?
Any particular reason it needs to be alphanumeric? If it can just be a number, you can use an Oracle sequence.
But if you want just a random string, you could use the dbms_random function.
select dbms_random.string('U', 20) str from dual;
So you could probably combine these 2 ideas (in the code below, the sequence is called oid_seq):
SELECT dbms_random.string('U', 20) || '_' || to_char(oid_seq.nextval) FROM dual
There are two parts to your question. The first is how to create an alphanumeric key. The second is how to get the generated value.
So the first step is to determine the source of the alpha and the numeric components. In the following example I use the USER function and an Oracle sequence, but you will have your own rules. I put the code to assemble the key in a trigger which is called whenever a row is inserted.
SQL> create table t1 (pk_col varchar2(10) not null, create_date date)
2 /
Table created.
SQL> create or replace trigger t1_bir before insert on t1 for each row
2 declare
3 n pls_integer;
4 begin
5 select my_seq.nextval
6 into n
7 from dual;
8 :new.pk_col := user||trim(to_char(n));
9 end;
10 /
Trigger created.
SQL>
The second step requires using the RETURNING INTO clause to retrieve the generated key. I am using SQL*PLus for this example. I confess to having no idea how to wire this syntax into VB. Sorry.
SQL> var new_pk varchar2(10)
SQL> insert into t1 (create_date)
2 values (sysdate)
3 returning pk_col into :new_pk
4 /
1 row created.
SQL> print new_pk
NEW_PK
--------------------------------
APC61
SQL>
Finally, a word of warning.
Alphanumeric keys are a suspicious construct. They reek of "smart keys" which are, in fact, dumb. A smart key is a value which contains multiple parts. At somepoint you will find yourself wanting to retrieving all rows where the key starts with 'PRD', which means using SUBSTR() or LIKE. Even worse someday the definition of the smart key will change and you will have to cascade a complicated update to your table and its referencing foreign keys. A better ides is to use a surrogate key (number) and have the alphanumeric "key" defined as separate columns with a UNIQUE composite constraint to enforce the business rule.
SQL> create table t1 (id number not null
2 , alpha_bit varchar2(3) not null
3 , numeric_bit number not null
4 , create_date date
5 , constraint t1_pk primary key (id)
6 , constraint t1_uk unique (alpha_bit, numeric_bit)
7 )
8 /
Table created.
SQL>
I have two Oracle questions.
How can I set the primary key of a table when the table is made up of an object type? e.g.
CREATE TABLE object_names OF object_type
I have created a Varray type,
CREATE TYPE MULTI_TAG AS VARRAY(10) OF VARCHAR(10);
but when I try to do
SELECT p.tags.count FROM pg_photos p;
I get an invalid identifier error on the "count" part. p.tags is a MULTI_TAG, how can I get the number of elements in the MULTI_TAG?
First of all I wouldn't recommend storing data in Object tables. Objects are a great programmatic tool but querying Object tables leads to complicated SQL. I would advise storing your data in a standard relationnal model and using the objects in your procedures.
Now to answer your questions:
A primary key should be immutable, so most of the time an Object type is inappropriate for a primary key. You should define a surrogate key to reference your object.
You will have to convert the varray into a table to be able to query it from SQL
For example:
SQL> CREATE TYPE MULTI_TAG AS VARRAY(10) OF VARCHAR(10);
2 /
Type created
SQL> CREATE TABLE pg_photos (ID number, tags multi_tag);
Table created
SQL> INSERT INTO pg_photos VALUES (1, multi_tag('a','b','c'));
1 row inserted
SQL> INSERT INTO pg_photos VALUES (2, multi_tag('e','f','g'));
1 row inserted
SQL> SELECT p.id, COUNT(*)
2 FROM pg_photos p
3 CROSS JOIN TABLE(p.tags)
4 GROUP BY p.id;
ID COUNT(*)
---------- ----------
1 3
2 3
1)
A primary key is a constraint, to add constrains on object tables check this link:
http://download-west.oracle.com/docs/cd/B28359_01/appdev.111/b28371/adobjdes.htm#i452285
2)
The COUNT method can't be used in a SQL statement:
REF LINK IN COMMENTS
So in my case I had to do
SELECT p.pid AS pid, count(*) AS num_tags FROM pg_photos p, TABLE(p.tags) t2 GROUP BY p.pid;