I am student
i doing assignement , do auto increment
How to create an auto increment in Oracle ?
CREATE TABLE mua_thi
(
mamuathi varchar2(10) not null,
check(mamuathi like 'MT%')
)
mamuathi = MT + auto_increment;
create or replace trigger tangmuathi
before insert or update
on mua_thi
begin
set new.mamuathi := MT + muathitang.nextval from Dual;
end;
create sequence muathitang start
with 1 increment by 1;
mamuathi = MT + auto_increment;
Don't structure your table like that. That's a smart key (a single string with several components concatenated). Smart keys are dumb. If the "MT" is crucial (why have a key with a hardcoded, unchanging element?) make it a separate column.
CREATE TABLE mua_thi ( mamuathi varchar2(2) not null
, id number (8) not null
, primary key (mamuathi, id )
, check(mamuathi = 'MT')
);
Actually there's still some bad practice there. One, name the constraints - it makes life easier:
, constraint mt_pk primary key (mamuathi, id )
, constraint mt_ck check(mamuathi = 'MT')
Two, if mamuathi is genuinely a constant it's pointless using it in the key:
, constraint mt_pk primary key ( id )
Three, mamuathi may evolve to several values , so think about whether a foreign key to a look-up table might be better.
Obviously the drawback to splitting a smart key is the need to refrence multiple columns. In 11g we can use the virtual column feature to avoid that inconveience:
CREATE TABLE mua_thi ( mamuathi varchar2(2) not null
, id number (8) not null
, mamuathi_disp AS mamuathi||lpad(id,8,'0')
, primary key (mamuathi, id )
, check(mamuathi = 'MT')
);
Related
I'm transferring data from Oracle.
There is table named A and when there are overlapping columns in the process of moving them to table C, I am trying to delete them and put them in.
However, if A and C have the same column configuration, it works smoothly, but the column configuration is different, so I don't know what to do if I convert it.
What I've tried so far is as follows.
CREATE TABLE test.test_pk_a
(
col_one VARCHAR2(4) NOT NULL,
col_two VARCHAR2(5) NOT NULL,
col_three VARCHAR2(8) NOT NULL,
CONSTRAINT test_pk_a_pk PRIMARY KEY(col_one,col_two)
);
INSERT INTO test_pk_a VALUES('A',1,1);
INSERT INTO test_pk_a VALUES('A',2,1);
INSERT INTO test_pk_a VALUES('A',3,1);
CREATE TABLE test.test_pk_c
(
col_one_v VARCHAR2(4) NOT NULL,
col_two_v VARCHAR2(5) NOT NULL,
col_three_v VARCHAR2(8) NOT NULL,
CONSTRAINT test_pk_c_pk PRIMARY KEY(col_one_v,col_two_v)
);
INSERT INTO test_pk_c VALUES(10,'c',1);
INSERT INTO test_pk_c VALUES(20,'a',1);
DELETE
FROM (SELECT *
FROM test.test_pk_a A, test.test_pk_c C
WHERE A.col_two*10 = C.col_one_v
AND LOWER(A.col_one)= C.col_two_v);
How should I modify this Query in order to make it work?
If you've meant to delete from the table A, then you can precede the subquery with EXISTS such as
DELETE test_pk_a
WHERE EXISTS (SELECT 0
FROM test_pk_a A
JOIN test_pk_c C
ON A.col_two * 10 = C.col_one_v
AND LOWER(A.col_one) = C.col_two_v);
if you meant the common column names by configuration wouldn't be the case(no problem whether to have the same column names or not)
create table doctor
(
name varchar2(20)
, d_id varchar2(20)
, address varchar2(50)
, phone_number number(10)
, qualification varchar2(20)
, gender varchar2(20)
, constraint pk_doctor primary key(d_id)
)
;
create table room
(
room_id varchar2(5)
, room_type varchar2(20)
, constraint pk_room primary key(room_id)
)
;
create table patient
(
p_id varchar2(10)
, p_name varchar2(20)
, p_age number(3)
, p_gender varchar2(10)
, address varchar2(50)
, date_admission date
, phone_number number(10)
, room_id varchar2(5)
, constraint pk_patient primary key(p_id)
, constraint fk_p1 foreign key(room_id) references room
)
;
create table bill
(
bill_no varchar2(10)
, bill_date date
, p_id varchar2(10)
, p_name varchar2(20)
, p_age number(3)
, p_gender varchar2(10)
, date_admission date
, date_discharge date
, room_charges number(10)
, pathology_fees number(10)
, d_fees number(10)
, miscellaneous number(10)
, total_amount number(10)
, constraint pk_bill primary key(bill_no)
, constraint fk_b1 foreign key(p_id) references patient
, constraint fk_b2 foreign key(p_name) references patient
, constraint fk_b3 foreign key(p_age) references patient
, constraint fk_b4 foreign key(p_gender) references patient
, constraint fk_b5 foreign key(date_admission) references patient
)
;
Error starting at line : 15 in command -
create table bill
(
bill_no varchar2(10)
, bill_date date
, p_id varchar2(10)
, p_name varchar2(20)
, p_age number(3)
, p_gender varchar2(10)
, date_admission date
, date_discharge date
, room_charges number(10)
, pathology_fees number(10)
, d_fees number(10)
, miscellaneous number(10)
, total_amount number(10)
, constraint pk_bill primary key(bill_no)
, constraint fk_b1 foreign key(p_id) references patient
, constraint fk_b2 foreign key(p_name) references patient
, constraint fk_b3 foreign key(p_age) references patient
, constraint fk_b4 foreign key(p_gender) references patient
, constraint fk_b5 foreign key(date_admission) references patient
)
Error report -
ORA-02267: column type incompatible with referenced column type
02267. 00000 - "column type incompatible with referenced column type"
*Cause: The data type or collation of the referencing column was
incompatible with the data type or collation of the referenced
column.
*Action: Select a compatible data type for the referencing column.
Also, the collation of a character column in a foreign key must
match the collation of the corresponding column in the primary
key.
I understand what the error is trying to tell but my datatypes are same in both tables but still, it is showing the error??
Please tell me where I made a mistake. I would be very grateful.
From the documentation:
If you identify only the parent table or view and omit the column name, then the foreign key automatically references the primary key of the parent table or view.
So you're effectively actually doing:
, constraint fk_b1 foreign key(p_id) references patient
, constraint fk_b2 foreign key(p_name) references patient(p_id)
, constraint fk_b3 foreign key(p_age) references patient(p_id)
, constraint fk_b4 foreign key(p_gender) references patient(p_id)
, constraint fk_b5 foreign key(date_admission) references patient(p_id)
which obviously isn't what you want, and explains the error you get.
You need to specify the matching non-PK columns:
, constraint fk_b1 foreign key(p_id) references patient
, constraint fk_b2 foreign key(p_name) references patient(p_name)
, constraint fk_b3 foreign key(p_age) references patient(p_age)
, constraint fk_b4 foreign key(p_gender) references patient(p_gender)
, constraint fk_b5 foreign key(date_admission) references patient(date_admission)
However, this will not get
ORA-02270: no matching unique or primary key for this column-list
because those four columns aren't suitable targets; none can really be unique, at least safely. And it wouldn't allow data to change - name and gender could, but age will, for example. These may be recording the patient's status on admission though, so then those wouldn't change, other than to correct mistakes.
It doesn't really make sense to duplicate/denormalise the data. You can just have the PK reference and join to the main table as needed to get the other information.
db<>fiddle
Splitting patient into a table to identify an individual (with date of birth rather than age) and a separate table that records each stay for that patient - with room and admission/discharge dates, for example - might make more sense. Only recording the discharge date on the bill seems odd.
The problem you're facing comes from bad data model which is needed for some rework.
The "bill" table contains p_name, p_age, p_gender, and date_admission columns. Same columns exist in the "patient" table, so you don't need them in the "bill". Just remove the columns from the "bill" definition and it'll be fine.
Whenever you need to get patient's name for the bill, you can always get it using p_id:
select p.p_name, p.p_age
from patient p
join bill b
on b.p_id, p.p_id
where b.bill_no = 'some_bill_no'
And keeping patient's age will lead to an engineering overhead because you'll have to update this field constantly once per year. I'd suggest you to store patient's birth_date and calculate his/her age when needed.
Of course when it is not a homework with gives table structure
I have two tables. Tables A and B, each has a primary key that is autoincremented and foreign must not be null. Both tables are in a 1:1 relationship.
So, for every record in A there must be a B.
What I can't get working is the inserting into such tables. The error I get is "parent key not found".
I'm new to oracle, so thanks for helping.
Here is a screen of ER:
Here's my insert:
INSERT ALL
INTO NASTAVENI_TARIFU (ZADANI_D, ID_OBJEDNAVKY, ID_DODATKU, ID_TARIF, ID_NABIDKY) VALUES (TO_DATE('2018-01-01', 'yyyy-mm-dd' ), 1, SQ_SMLUVNI_DODATEK.nextval, 2, NULL)
INTO SMLUVNI_DODATKY (PROLONGACE_D,ID_NASTAVENI_TARIFU) VALUES (TO_DATE('2019-12-22', 'yyyy-mm-dd' ), SQ_NASTAVENI_TARIFU.currval)
SELECT * FROM DUAL
Here are the definitions:
CREATE TABLE nastaveni_tarifu (
id_nastaveni_tarifu INTEGER NOT NULL,
zadani_d DATE NOT NULL,
id_objednavky INTEGER NOT NULL,
id_dodatku INTEGER NOT NULL,
id_tarif INTEGER NOT NULL,
id_nabidky INTEGER
);
CREATE TABLE smluvni_dodatky (
id_dodatku INTEGER NOT NULL,
prolongace_d DATE NOT NULL,
id_nastaveni_tarifu INTEGER NOT NULL
);
ALTER TABLE smluvni_dodatky
ADD CONSTRAINT fk_dodatek_nast_tarifu FOREIGN KEY ( id_nastaveni_tarifu )
REFERENCES nastaveni_tarifu ( id_nastaveni_tarifu );
ALTER TABLE nastaveni_tarifu
ADD CONSTRAINT fk_nast_tarifu_dodatek FOREIGN KEY ( id_dodatku )
REFERENCES smluvni_dodatky ( id_dodatku );
CREATE SEQUENCE sq_nastaveni_tarifu START WITH 1 MINVALUE 1 NOCACHE ORDER;
CREATE OR REPLACE TRIGGER tr$ntpreinsert BEFORE
INSERT ON nastaveni_tarifu
FOR EACH ROW
WHEN ( new.id_nastaveni_tarifu IS NULL )
BEGIN
:new.id_nastaveni_tarifu := sq_nastaveni_tarifu.nextval;
END;
CREATE SEQUENCE sq_smluvni_dodatek START WITH 1 MINVALUE 1 NOCACHE ORDER;
CREATE OR REPLACE TRIGGER tr$sdpreinsert BEFORE
INSERT ON smluvni_dodatky
FOR EACH ROW
WHEN ( new.id_dodatku IS NULL )
BEGIN
:new.id_dodatku := sq_smluvni_dodatek.nextval;
END;
... I'm starting to hate Oracle, this shouldn't be that hard :(
As I mentioned, this is a bad design as there's circular reference between two tables.
The problem with your insert all statement is that there's no way the second into clause could see SQ_NASTAVENI_TARIFU.nextval as it can get initialised only when the statement as a whole is completed.
Even if you convert this to 2 insert statements, it wouldn't work because there's no way you could ensure to have a row in one table when the value is dependent on other in each case and also the foreign key columns are declared not null.
Either you define them as NULL and try to first insert nulls and then update it or use a Deferred Constraints as a workaround only.
ALTER TABLE smluvni_dodatky
ADD CONSTRAINT fk_dodatek_nast_tarifu FOREIGN KEY ( id_nastaveni_tarifu )
REFERENCES nastaveni_tarifu ( id_nastaveni_tarifu )
deferrable initially deferred;
ALTER TABLE nastaveni_tarifu
ADD CONSTRAINT fk_nast_tarifu_dodatek FOREIGN KEY ( id_dodatku )
REFERENCES smluvni_dodatky ( id_dodatku ) deferrable initially deferred;
Now, there's another problem with your second Trigger, unless the primary key of the table smluvni_dodatky generated using the sequence sq_smluvni_dodatek can store the same value which was insert into nastaveni_tarifu, the constancy can't be maintained.
Hence in your Trigger tr$sdpreinsert, change the assignment expression to this
:new.id_dodatku := sq_smluvni_dodatek.currval;
Now, running both inserts as separate statements like this would work because the constraint checking is not done until a commit is issued.
INSERT INTO nastaveni_tarifu (
zadani_d,id_objednavky,id_dodatku,id_tarif,id_nabidky
) VALUES (
TO_DATE('2018-01-01','yyyy-mm-dd'), 1,sq_smluvni_dodatek.NEXTVAL, 2,NULL
) ;
INSERT INTO smluvni_dodatky (
prolongace_d,id_nastaveni_tarifu
) VALUES (
TO_DATE('2019-12-22','yyyy-mm-dd'),sq_nastaveni_tarifu.currval);
commit;
DEMO
Table has been created in system this way
CREATE TABLE INSTANCES
(
DM INTEGER NOT NULL,
INSTANCEID VARCHAR2(512) NOT NULL,
INSTANCENAME VARCHAR2(64) NOT NULL UNIQUE,
HOSTNAME VARCHAR2(32) NOT NULL,
CONSTRAINT PK_INSTANCES PRIMARY KEY (INSTANCEID, HOSTNAME)
);
The new crete table statement is as below:
CREATE TABLE INSTANCES
(
DM INTEGER NOT NULL,
INSTANCEID VARCHAR2(512) NOT NULL UNIQUE,
INSTANCENAME VARCHAR2(64) NOT NULL UNIQUE,
HOSTNAME VARCHAR2(32) NOT NULL,
CONSTRAINT PK_INSTANCES PRIMARY KEY (INSTANCEID, HOSTNAME)
);
The differnce is INSTANCEID has UNIQUE in it. How do i Alter the table? I used the below statement and it did not work for me.
ALTER TABLE INSTANCES ADD CONSTRAINT ab UNIQUE ( INSTANCEID);
It gave an error:
ALTER TABLE INSTANCES ADD CONSTRAINT ab UNIQUE ( INSTANCEID)
Error report:
SQL Error: ORA-02261: such unique or primary key already exists in the table
02261. 00000 - "such unique or primary key already exists in the table"
*Cause: Self-evident.
*Action: Remove the extra key.
Please help me to Alter the table as required above. Thanks!
Here is the output of SELECT con.constraint_name, col.column_name, con.constraint_type
FROM user_cons_columns col
JOIN user_constraints con ON (col.constraint_name = con.constraint_name)
WHERE col.table_name = 'INSTANCES';
"CONSTRAINT_NAME","COLUMN_NAME","CONSTRAINT_TYPE"
"SYS_C0016531","DM","C"
"SYS_C0016532","INSTANCEID","C"
"SYS_C0016533","INSTANCENAME","C"
"SYS_C0016534","HOSTNAME","C"
"PK_INSTANCES","HOSTNAME","P"
"PK_INSTANCES","INSTANCEID","P"
"SYS_C0016536","INSTANCENAME","U"
You have already stated that INSTANCEID is supposed to be UNIQUE, so a constraint has been created.
CREATE TABLE INSTANCES
(
DM INTEGER NOT NULL,
INSTANCEID VARCHAR2(512) NOT NULL UNIQUE, -- UNIQUE constraint
INSTANCENAME VARCHAR2(64) NOT NULL UNIQUE,
HOSTNAME VARCHAR2(32) NOT NULL,
CONSTRAINT PK_INSTANCES PRIMARY KEY (INSTANCEID, HOSTNAME)
);
Edit: Ok, after reading your comment, try this:
SELECT con.constraint_name, col.column_name, con.constraint_type
FROM user_cons_columns col
JOIN user_constraints con ON (col.constraint_name = con.constraint_name)
WHERE col.table_name = 'INSTANCES'
AND con.constraint_type = 'U'
;
It will list UNIQUE constraints and associated columns for INSTANCE table. Please check if there is a unique constraint on the INSTANCEID column (and if that constraint has no other associated columns).
Example at SQLFiddle: http://sqlfiddle.com/#!4/43b43/6
Edit #2: creating named constraints, all options:
-- CREATE TABLE - "In Line" Constraints
CREATE TABLE ports (
ID NUMBER CONSTRAINT PORT_ID_PK PRIMARY KEY,
NAME VARCHAR2(20)
);
CREATE TABLE ports (
ID NUMBER,
NAME VARCHAR2(20) CONSTRAINT NAME_NN NOT NULL
);
CREATE TABLE ports (
ID NUMBER,
NAME VARCHAR2(20) CONSTRAINT NAME_UQ UNIQUE
);
CREATE TABLE ports (
ID NUMBER,
STATUS NUMBER CONSTRAINT PROPER_STATUS_CK
CHECK (STATUS IN (4, 5))
);
CREATE TABLE ships (
SHIP_ID NUMBER,
NAME VARCHAR2(20),
HOME_PORT_ID NUMBER CONSTRAINT SHIP_PORT_FK
REFERENCES PORTS (ID)
);
-- CREATE TABLE - "Out of Line" Constraints
CREATE TABLE ports (
ID NUMBER,
NAME VARCHAR2(20),
CONSTRAINT PORT_ID_PK PRIMARY KEY (ID)
);
-- NOT NULL constraints can not be created "Out of Line"!
CREATE TABLE ports (
ID NUMBER,
NAME VARCHAR2(20),
CONSTRAINT NAME_UQ UNIQUE (NAME)
);
CREATE TABLE ports (
ID NUMBER,
STATUS NUMBER,
CONSTRAINT PROPER_STATUS_CK
CHECK (STATUS IN (4, 5))
);
CREATE TABLE ships (
SHIP_ID NUMBER,
NAME VARCHAR2(20),
HOME_PORT_ID NUMBER,
CONSTRAINT SHIP_PORT_FK FOREIGN KEY
(HOME_PORT_ID) REFERENCES PORTS (ID)
);
-- ALTER TABLE - "In Line" Constraints
ALTER TABLE PORTS MODIFY ID
CONSTRAINT PORT_ID_PK PRIMARY KEY;
ALTER TABLE PORTS MODIFY NAME
CONSTRAINT NAME_NN NOT NULL;
ALTER TABLE PORTS MODIFY NAME
CONSTRAINT NAME_UQ UNIQUE;
ALTER TABLE SHIPS MODIFY HOME_PORT_ID
CONSTRAINT SHIP_PORT_FK REFERENCES PORTS (ID);
-- ALTER TABLE - "Out of Line" Constraints
ALTER TABLE PORTS ADD CONSTRAINT
PORT_ID_PK PRIMARY KEY (ID);
-- NOT NULL constraints can not be created "Out of Line"!
ALTER TABLE PORTS ADD CONSTRAINT
NAME_UQ UNIQUE (NAME);
ALTER TABLE PORTS ADD
CONSTRAINT PROPER_STATUS_CK
CHECK (STATUS IN (4, 5));
ALTER TABLE SHIPS ADD CONSTRAINT SHIP_PORT_FK
FOREIGN KEY (HOME_PORT_ID)
REFERENCES PORTS (ID);
NOT NULL constraints cannot be create of out line.
Is it possible to set a unique constraint as a foreign key in another table?
If yes, how would you go about declaring it?
How would you go about assigning a candidate key?
Is it possible?
Example:
I have a product table that consists of:
prod_id, prod_name, prod_price, QOH
Where I want prod_name to link to the despatch table:
desp_id, prod_name, shelfLoc, quantity
What I was thinking is that I may need to create a unique constraint which will look like this:
ALTER TABLE product
ADD CONSTRAINT prod_nameID_uc
UNIQUE (prod_id,prod_name)
What I'm wondering is, if it is possible to refer to a unique key as a foreign key in the despatch table. I have to have prod_name rather than prod_id in the despatch table so that the information is more meaningful to the user when reading it, rather than seeing an id number.
I am using iSQL plus on oracle.
It is perfectly possible to reference a UNIQUE constraint in an Oracle FOREIGN KEY:
SQL> create table products (
2 prod_id number not null
3 , prod_name varchar2 (30) not null
4 , constraint prod_pk primary key ( prod_id )
5 , constraint prod_uk unique ( prod_name )
6 )
7 /
Table created.
SQL> create table despatch (
2 desp_id number not null
3 , prod_name
4 , constraint desp_pk primary key ( desp_id )
5 , constraint desp_prod_pk foreign key ( prod_name )
6 references products ( prod_name )
7 )
8 /
Table created.
SQL>
It is however bad practice. The main reason for using a primary key alongside a unique key is to provide a synthetic key for use in foreign keys. I were you I would be concerned that your teachers are giving you an assignment riddled with bad practice.
This is necessarily DBMS dependent. In the DBMSes I'm familiar with, the unique constraint and the foreign key constraint are separate considerations, you can have both, and they both act normally when combined.