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
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)
Im trying to build a sample database for a project about a real estate agency,on the table about the realties i have a column Realtie_id and i want it to start with 11%%% what type should it be (int or varchar ) and how do I make the constraint ?
create table Realties (
rid int not null,
address varchar(50),
m2 real not null,
r_type varchar(20),
primary key (rid),
constraint c_rid check(rid in (.....
);
It depends on what you'll be storing in there.
if it is a string, use VARCHAR2
if it is a number, use NUMBER (or INT)
Constraint in any case might be
SQL> create table realties
2 (rid int constraint ch_rid check (substr(to_char(rid), 1, 2) = '11'));
Table created.
SQL> insert into realties (rid) values ('abc');
insert into realties (rid) values ('abc')
*
ERROR at line 1:
ORA-01722: invalid number
SQL> insert into realties (rid) values ('245');
insert into realties (rid) values ('245')
*
ERROR at line 1:
ORA-02290: check constraint (SCOTT.CH_RID) violated
SQL> insert into realties (rid) values ('1245');
insert into realties (rid) values ('1245')
*
ERROR at line 1:
ORA-02290: check constraint (SCOTT.CH_RID) violated
SQL> insert into realties (rid) values ('11245');
1 row created.
SQL>
If your value is a number then make the column a numeric data type. The exception to this is when your value is a number string that can start with zeroes, like a phone number, when it should be a string data type; otherwise if you use a number data type then the, semantically important, leading zeroes will be stripped off. Since you want the number to start with 11 then this caveat does not apply.
As for the CHECK constraint, you can use LIKE '11%' and Oracle will implicitly convert it to a string to perform the check.
create table Realties (
rid int
not null
CONSTRAINT realties__rid__pk PRIMARY KEY
CONSTRAINT realties__rid__chk CHECK ( rid LIKE '11%' ),
address varchar(50),
m2 real
not null,
r_type varchar(20)
);
I've executed following query in toad:
CREATE TABLE ACTWEB.usuarios
(
id INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1),
matricula INTEGER,
nome CHAR(50) NOT NULL,
senha CHAR(50),
nivel INTEGER,
maleta INTEGER,
email CHAR(50),
acessos INTEGER,
datacriacao DATE,
dataalteracao DATE
UNIQUE (id)
)
LOGGING
NOCOMPRESS
NOCACHE
NOPARALLEL;
And got this ORA message:
ORA-00907 missing right parenthesis
Cause: A left parenthesis has been entered without a closing right parenthesis, or extra information was contained in the parentheses. All parentheses must be entered in pairs.
Action: Correct the syntax and retry the statement.
There are a couple of errors in your syntax. The NOT NULL has to occur after the IDENTITY clause. The range has to be specified without a , and the UNIQUE keyword has to appear at the column directly:
CREATE TABLE ACTWEB.usuarios
(
id INTEGER GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1) NOT NULL UNIQUE,
matricula INTEGER,
nome CHAR(50) NOT NULL,
senha CHAR(50),
nivel INTEGER,
maleta INTEGER,
email CHAR(50),
acessos INTEGER,
datacriacao DATE,
dataalteracao DATE
)
LOGGING NOCOMPRESS NOCACHE NOPARALLEL;
You specified unique not right, to solve it you have several ways:
First, create unique key explicitly:
create table tab1(
id number(10),
CONSTRAINT id_uk UNIQUE (id)
)
Second, create unique key as an option of the column:
create table tab1(
id number(10) UNIQUE
)
Third, add the unique key constraint using alter table:
create table tab1(
id number(10)
);
alter table tab1 add constraint id_uk unique(id);
Forth, create unique key implicitly by creating unique index:
create table tab1(
id number(10)
);
CREATE UNIQUE INDEX id_uk ON tab1 (id);
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.
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')
);