Basic primary key / foreign key with constraint, sequence, trigger - sql

Learner here in Oracle 11g. I'm having an issue with INSERTing some rows into two tables that are linked by a primary/foreign key relationship.
Basically I create a sequence to start with 1000 and increment by 1.
Then create a 'STORE' table with a ST_ID column
The ST_ID column is linked to the SEQUENCE with a TRIGGER.
Then I have an 'EMPLOYEE' table that has a EST_ID field that is a foreign key to the ST_ID column in the STORE table.
However, when I tried to insert rows I initially got a error saying EST_ID could not be null. So I created a sequence and trigger for EST_ID and now I'm getting an error saying the foreign key constraint is being violated.
I think that was maybe the wrong thing to do. Do I really want E_ID and EST_ID to be identical and how would I get that to happen? With some kind of trigger?
The actual code:
CREATE SEQUENCE "STORSEQ" MINVALUE 1000 MAXVALUE 9999 INCREMENT BY 1 START WITH 1000 NOCACHE NOORDER
NOCYCLE ;
CREATE TABLE "STORE"
( "ST_ID" CHAR(4) NOT NULL ENABLE,
"STADDR_ID" CHAR(4) NOT NULL ENABLE,
CONSTRAINT "STORE_PK" PRIMARY KEY ("ST_ID") ENABLE
) ;
CREATE TABLE "EMPLOYEE"
( "E_ID" CHAR(8) NOT NULL ENABLE,
"EF_NAME" VARCHAR2(20) NOT NULL ENABLE,
"EL_NAME" VARCHAR2(20) NOT NULL ENABLE,
"EST_ID" CHAR(4) NOT NULL ENABLE,
CONSTRAINT "EMPLOYEE_PK" PRIMARY KEY ("E_ID") ENABLE
) ;
alter table "EMPLOYEE" add CONSTRAINT "EMPLOYEE_CON" foreign key ("EST_ID") references
"STORE" ("ST_ID")
/
CREATE OR REPLACE TRIGGER "BI_STORE"
before insert on "STORE"
for each row
begin
if :NEW."ST_ID" is null then
select "STORSEQ".nextval into :NEW."ST_ID" from dual;
end if;
end;
/
At the moment my INSERT code looks like this:
INSERT INTO STORE
(ST_ID, STADDR_ID)
VALUES
(DEFAULT, DEFAULT);
INSERT INTO EMPLOYEE
(EF_NAME, EL_NAME)
VALUES
('James', 'Smith');

When you try to insert data into table that has foreign key reference, it will not get value for id automatically, you need to pass that value.
You can do this:
declare
v_store_id integer;
begin
INSERT INTO STORE (ST_ID, STADDR_ID) VALUES (DEFAULT, DEFAULT)
RETURNING ST_ID INTO v_Store_id;
INSERT INTO EMPLOYEE (EF_NAME, EL_NAME, EST_ID)
VALUES ('James', 'Smith', v_store_id);
end;
You can also insert id in store id table without trigger using this
declare
v_store_id integer;
begin
INSERT INTO STORE (ST_ID, STADDR_ID) VALUES ("STORSEQ".nextval, DEFAULT)
RETURNING ST_ID INTO v_Store_id;
INSERT INTO EMPLOYEE (EF_NAME, EL_NAME, EST_ID)
VALUES ('James', 'Smith', v_store_id);
end

Related

SQL Trigger Wont Generate Primary Key

I am trying to create a table that logs all inserts in the author table. Here is the author table, and the Audit_log Table:
CREATE TABLE Author(AuthorID INT PRIMARY KEY NOT NULL,
last_name CHAR(20),
first_name CHAR(20));
CREATE TABLE Audit_Log(Action_ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
table_name Char(40),
action_name Char(6),
Date_Time DATETIME DEFAULT CURRENT_TIMESTAMP);
Here is the simple trigger.
DELIMITER $$
CREATE TRIGGER Author_Trigger AFTER INSERT
ON Author
FOR EACH ROW BEGIN
INSERT INTO Audit_Log VALUES('Author', 'INSERT', CURRENT_TIMESTAMP);
END $$
DELIMITER ;
However, when I cause the trigger to occur by inserting into the author table, it says that the columns do not match row 1. How come my Primary key does not get auto generated, despite having the AUTO_INCREMENT Constraint?
How can I get this trigger to generate the primary key?
Basically MySQL thinks that 'Author' is being inserted as the PRIMARY KEY (Action_ID). What you can do to avoid this is specify wich attribute correspond to wich element of the INSERT query. This should work :)
DELIMITER $$
CREATE TRIGGER Author_Trigger AFTER INSERT
ON Author
FOR EACH ROW BEGIN
INSERT INTO Audit_Log(table_name, action_name, Date_Time)
VALUES('Author', 'INSERT', CURRENT_TIMESTAMP);
END $$
DELIMITER ;
For the value to autoincrement, since you do not have defined the data you must insert and place the autoincremental, it does not take it, so the first value is null and through this null it will autoincrement.
DELIMITER $$
CREATE TRIGGER Author_Trigger AFTER INSERT
ON Author
FOR EACH ROW BEGIN
INSERT INTO Audit_Log VALUES(null,'Author', 'INSERT', CURRENT_TIMESTAMP);
END $$
DELIMITER ;

How to insert multiple values in one column of type number in oracle?

I have table like
CREATE TABLE TEMP_TABLE
(
temp_acct number(10) NOT NULL,
temp_code varchar2(250),
temp_bal number(10,2),
CONSTRAINT TEMP_TABLE_PK PRIMARY KEY(temp_acct)
);
Is it possible to insert multiple values into column temp_bal in one row something like below,I know the syntax is incorrect but is there any way?
INTO TEMP_TABLE (temp_acct, temp_code, temp_bal)
VALUES (1000, 'code100, code101, code102, code103', '1000.00,2000.00,3000.00');

Creating trigger to allow INSERT if existing data is not null

I have the following table and I want to create a trigger that allows the insertion of values if the value of 'ActualLeaveDate' is not null:
CREATE TABLE Bed
(
PatBedNum NUMBER GENERATED BY DEFAULT AS IDENTITY START WITH 1 INCREMENT BY 1,
WardNum NUMBER(4),
BedNum NUMBER(2),
PatNum VARCHAR2(6) CHECK (PatNum LIKE '%P%'),
DateOnWaitlist DATE,
ExpectedStayDuration VARCHAR2(8) CHECK (ExpectedStayDuration LIKE '% days%'),
DatePlacedInWard DATE,
ExpectedLeaveDate DATE,
ActualLeaveDate DATE,
CONSTRAINT BedPK PRIMARY KEY (PatBedNum),
CONSTRAINT PatBedNum FOREIGN KEY (PatNum)
REFERENCES Patient (PatNum) ON DELETE CASCADE,
CONSTRAINT PatWardNum FOREIGN KEY (WardNum)
REFERENCES Ward (WardNum) ON DELETE CASCADE
);
I tried to create a trigger using the following script:
CREATE TRIGGER BedCheck2
BEFORE INSERT ON BED
FOR EACH ROW
BEGIN
IF (:Old.ActualLeaveDate IS NOT NULL)
THEN
INSERT INTO Bed (PatBedNum, WardNum, BedNum, PatNum, DateOnWaitlist, ExpectedStayDuration, DatePlacedInWard, ExpectedLeaveDate, ActualLeaveDate)
VALUES (:New.PatBedNum, :New.WardNum, :New.BedNum, :New.PatNum, :New.DateOnWaitlist, :New.ExpectedStayDuration, :New.DatePlacedInWard, :New.ExpectedLeaveDate, :New.ActualLeaveDate);
ELSE
RAISE_APPLICATION_ERROR (-20002, 'Bed ' || :Old.BedNum || 'is not empty!');
END IF;
END;
/
However, when I enter the following insert command, it skips the insertion portion of the trigger:
INSERT INTO BED VALUES (5, 11, 84, 'P10787', '12/1/20', '5 days', '17/1/20', '22/1/20', NULL);
Additionally, it straights directly to the RAISE_APPLICATION_ERROR even though the data in 'ActualLeaveDate' in the database IS NOT NULL.
Am I missing something here or doing something wrong?
Why not simply add a NOT NULL constraint to that column?
CREATE TABLE Bed (
...,
ActualLeaveDate DATE NOT NULL,
...
)
If you want to prevent both ActualLeaveDate and BedNum to be null (or not null), you can use a check constraint:
CREATE TABLE Bed (
...,
BedNum NUMBER(2),
ActualLeaveDate DATE,
...
CHECK (
(BedNum IS NOT NULL AND ActualLeaveDate IS NULL)
OR (BedNum IS NULL AND ActualLeaveDate IS NOT NULL)
)
)

Error in primary key in sqlplus?

I am beginner in sql.I am using sqlplus to run the sql query .I used simple query but it shows an error like "MISSING RIGHT PARENTHESIS".My objective is to create the autoincrement primary key .Can anyone solve the error?Thanks in advance...
create table student(rollno int identity(1,1) primary key,
name varchar(20),marks int);
For Oracle, the rollno column could be defined as NUMBER(0010) and primary key.
Then you would need to add an ON INSERT trigger to populate rollno from a SEQUENCE. There are many samples of triggers and sequences on this site.
In oracle 12 you can use a identity column to automatically fill your ID
CREATE TABLE students
(
"ID" NUMBER GENERATED BY DEFAULT AS IDENTITY MINVALUE 1 MAXVALUE 9999999999
INCREMENT BY 1 START WITH 1 ,
"NAME" VARCHAR2(20),
"MARKS" NUMBER(2,0),
CONSTRAINT PK_STUDENTS PRIMARY KEY (ID) ENABLE
);
/
This creates a table without any triggers needed and automatically fills the id column (of not specified with a value) with the next number up to 99999...
If you're using oracle 11 and below, you need a trigger on insert and assign a value (custom_sequence.nextval) to the id column.
CREATE TABLE students
(
"ID" NUMBER(5,0) not null,
"NAME" VARCHAR2(20),
"MARKS" NUMBER(2,0),
CONSTRAINT PK_STUDENTS PRIMARY KEY (ID) ENABLE
);
/
CREATE SEQUENCE SEQ_STUDENTS INCREMENT BY 1 START WITH 1;
/
TRIGGER TC_students
before insert on students
for each row
begin
if (:new.id is null) then
select SEQ_students.nextval into :new.id from dual;
end if;
end;
/
And please use VARCHAR2.

Oracle adding records from multiple tables

My objective is to build a master Serial No table from many different tables and each Serial No must be unique.
CREATE TABLE "TBL_SERIAL_NUMBER_MASTER"
( "INTERNAL_RECORD_ID" VARCHAR2(60) NOT NULL ENABLE,
"ASSET_ID" VARCHAR2(60),
"SERIAL_NUMBER" VARCHAR2(1000) NOT NULL ENABLE,
"VALID" VARCHAR2(60) DEFAULT 'Valid',
"HOST_NAME" VARCHAR2(255),
CHECK ( valid IN ('Invalid', 'Valid')) ENABLE,
CHECK ( valid IN ('Invalid', 'Valid')) ENABLE,
CHECK ( valid IN ('Invalid', 'Valid')) ENABLE,
CONSTRAINT "TBL_SERIAL_NUMBER_MASTER_CON" PRIMARY KEY ("SERIAL_NUMBER") ENABLE
) ;
CREATE OR REPLACE TRIGGER "TBL_SERIAL_NUMBER_MASTER_INTER" BEFORE
INSERT
ON tbl_serial_number_master FOR EACH ROW WHEN (
NEW.internal_record_id IS NULL
) BEGIN :NEW.internal_record_id := tbl_serial_number_master_inter.NEXTVAL;
END;
/
ALTER TRIGGER "TBL_SERIAL_NUMBER_MASTER_INTER" ENABLE;
I have already updated the SERIAL_NUMBER field using one table. Now I am trying to add more Serial Nos from another table. These other tables have duplicate and null value Serial Nos. Can you please advise how I can create the query to add unique Serial Nos that are already not in the TBL_SERIAL_NUMBER_MASTER.
Please assume following fields for the other table.
TABLE_SOURCE_B
ID :-PK
SERIAL_NUMBER
List item
Name
In your Master Table, 'Internal_Record_Id' has Not Null constraint. So I am inserting values of ID field of Source table into 'internal_record_id'.
Try the following query.
INSERT INTO
TBL_SERIAL_NUMBER_MASTER (INTERNAL_RECORD_ID,SERIAL_NUMBER)
SELECT ID,SERIAL_NUMBER
FROM TABLE_SOURCE_B B
WHERE B.SERIAL_NUMBER NOT IN(SELECT SERIAL_NUMBER
FROM TBL_SERIAL_NUMBER_MASTER);
Hope it helps!