I have two tables:
create table Number( num number(5));
create table Entry(id number(3), name varchar(50));
How can I increment the num field of Number table in Oracle whenever I insert something in the Entry table?
You should use a SEQUENCE instead. The "Number" table is an inherently bad idea, because when two sessions are inserting rows concurrently, each session only sees the uncommited value in the Number table.
This is what you should do instead:
create sequence entrySeq;
create table Entry(id number(3), name varchar(50));
create trigger tr_entry before insert on Entry for each row
begin
select entrySeq.nextval into :new.number from dual;
end;
/
Do you want number.num to continually represent the number of rows iin the Entry table? If so you could just define it as a view:
create view number_view
as
select count(*) from Entry
create sequence entrySeq;
create table Entry(id number(3), name varchar(50));
insert into Entry value (entrySeq.nextval, 'MyName');
(You don't need a trigger).
A sequence returns a unique and increasing number value but Oracle doesn't guarantuee that it is gapless. When sometimes transactions are rollbacked the values of column id will contain gaps.
Related
I am getting data from a feed file which is stored in Oracle Table TYPE.
Table TYPE created:
CREATE OR REPLACE TYPE typ_employee AS OBJECT
(
EMP_NAME DATE,
EMP_DEPT NUMBER,
EMP_SALARY NUMBER,
);
/
How can I find the unique records from this object and insert in another table.
Please help with this query.
You can use nested table and then use SET(Nested_table) which gives you distinct records in the nested table.
Or You can insert data from one table to another using cursor and use exception dup_val_on_index in exception block and you can skip that records (primary key should be added in second table) or update the existing one
I have the below Nested table created :
create or replace TYPE access_t AS OBJECT (
AccessID VARCHAR2(50),
Eligibility char(1)
);
/
create or replace TYPE Access_tab IS TABLE OF access_t;
/
create or replace TYPE add_t AS OBJECT (
city VARCHAR2(100),
state VARCHAR2(100),
zip VARCHAR2(10),
APOINTSARRAY Access_tab )
;
/
create or replace TYPE add_tab IS TABLE OF add_t;
/
CREATE TABLE RQST_STATUS
( RQST_ID NUMBER,
ADDRESS add_tab
)
NESTED TABLE ADDRESS STORE AS RQST_STATUS_ADDRESS
( NESTED TABLE APOINTSARRAY STORE AS RQST_STATUS_AP)
;
If i need to change ADDRESS type to new_add_tab with some additional columns instead of add_tab , Can i just use ALTER TABLE .. MODIFY .. command ?
I am getting ORA-00922 or ORA-22913 errors . I cannot change the type directly because it is used somewhere else too. Also, the table is already loaded with data.
Please suggest.
You can do that but you have to alter the TYPE not the TABLE.
Check the documentation ALTER TYPE Statement: alter_method_spec
Most important is the CASCADE key word.
Examples:
ALTER TYPE access_t ADD ATTRIBUTE NEW_Eligibility INTEGER CASCADE;
ALTER TYPE access_t DROP ATTRIBUTE Eligibility CASCADE;
ALTER TYPE access_t MODIFY ATTRIBUTE AccessID VARCHAR2(100) CASCADE;
Here is a step-by-step description of my suggestion. It might not be the most elegant, but I think that it would be best for you to have something you can fully understand (as opposed to an obscure trick).
Also, and since I don't really know what kind of changes you need to do for the internal table, I'm leaving the maximal flexibility for you to do any change you may wish to do.
Let's call your table T1 that contains a columns C_T which is your internal table.
The internal table contains columns C_1, C-2 and C_3, and you want the new structure for the record to be D_1, D_2, D_3, D_4 and D_5, where the mapping is:
C_1 -> D_5,
C_2 -> D_1,
C_3 -> D_2,
{new} -> D_3,
{new} -> D_4.
Create a tempo table TEMPO_T with a column SOURCE_ROWID (varchar2(64)) and the new columns D_1,..., D5.
Write a small anonymous block having a cursor that selects the ROWID of each row of table T1 and all the records within the internal table in column C_T (order by ROWID). The result would look like (this is just an example of course):
ROWID C_1 C_2 C_2
wwereeedffff 1 a ww
wwereeedffff 2 b xx
wwereeedffff 7 l yy
ertrtrrrtrrr 5 d PP
ertrtrrrtrrr 99 h mm
...
[Note: The use of ROWID is under the assumption that you don't have a column that can serve as a unique identifier for each row in table T1; if there is such column - one defined as UNIQUE INDEX - you can use that field instead]
Having this query ready, convert it into an INSERT into the temporary table TEMPO_T along with whatever values you need to store for columns D_3 and D_4.
Now, you have a backup of the original contents of column C_T and hence can delete the column.
Now, you can update the type that defines the structure of column C_T to its new form (i.e. D_1,...,D_5) and alter table T1 by adding a column whose type is the updated one.
Finally, you can insert the contents of column C_T with that stored in the temporary table (since you already have this, I assume that you know how to implement it - inserting a table within a cell column of the outer table).
That's it.
Needless to say, I would make a backup of your data before engaging into this.
Hope this description is detailed enough to enable you to complete the task at hand.
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?
I have a table STUDENT with columns st_id,name,age,dept_name. Now I want to create a new table STUDENT_DESC with columns st_id,dept_name,st_desc. So I need to copy all the values of st_id and dept_name to the newly created table STUDENT_DESC. I need to ensure relationship while copying st_id and dept_name , the dept_name should be corresponding to st_id.So how can I do it in PL/SQL?
insert into STUDENT_DESC (select st_id, dept_name, null from student);
this will simply copy all the records. The third column st_desc is left empty (null)
To ensure referential integrity you would add a primary key and a referential integrity constraint to the STUDENT_DESC table
However, note that in many cases it could be "wrong" to introduce a second table containing student data like that. It could be "better" to add st_desc to the STUDENT table.
I'm not sure I understand your data model, but at face value you can create your table simply:
CREATE TABLE student_desc AS SELECT st_id, dept_name FROM student;
ALTER TABLE student_desc ADD (st_desc VARCHAR2(..));
Fill in the .. with the desired max size for st_desc.
I create a table in Oracle 11g with the default value for one of the columns. Syntax is:
create table xyz(emp number,ename varchar2(100),salary number default 0);
This created successfully. For some reasons I need to create another table with same old table structure and data. So I created a new table with name abc as
create table abc as select * from xyz.
Here "abc" created successfully with same structure and data as old table xyz. But for the column "salary" in old table "xyz" default value was set to "0". But in the newly created table "abc" the default value is not set.
This is all in Oracle 11g. Please tell me the reason why the default value was not set and how we can set this using select statement.
You can specify the constraints and defaults in a CREATE TABLE AS SELECT, but the syntax is as follows
create table t1 (id number default 1 not null);
insert into t1 (id) values (2);
create table t2 (id default 1 not null)
as select * from t1;
That is, it won't inherit the constraints from the source table/select. Only the data type (length/precision/scale) is determined by the select.
The reason is that CTAS (Create table as select) does not copy any metadata from the source to the target table, namely
no primary key
no foreign keys
no grants
no indexes
...
To achieve what you want, I'd either
use dbms_metadata.get_ddl to get the complete table structure, replace the table name with the new name, execute this statement, and do an INSERT afterward to copy the data
or keep using CTAS, extract the not null constraints for the source table from user_constraints and add them to the target table afterwards
You will need to alter table abc modify (salary default 0);
new table inherits only "not null" constraint and no other constraint.
Thus you can alter the table after creating it with "create table as" command
or you can define all constraint that you need by following the
create table t1 (id number default 1 not null);
insert into t1 (id) values (2);
create table t2 as select * from t1;
This will create table t2 with not null constraint.
But for some other constraint except "not null" you should use the following syntax
create table t1 (id number default 1 unique);
insert into t1 (id) values (2);
create table t2 (id default 1 unique)
as select * from t1;