SQL: prevent update if field value below certain value - sql

I would like to add a constraint to my table:
create table asset (
id number(19,0) not null,
name varchar2(255 char),
description varchar2(255 char),
type varchar2(255 char),
height number(10,0),
width number(10,0),
bytes blob,
primary key (id)
);
after have stored on it Assets with ID from 0 to 8:
ALTER TABLE ASSET ADD CONSTRAINT check_if_id_bigger_than_eight CHECK (ID > 8)
to avoid further modifications of rows with IDs from 0 to 8, unfortunately the above is not working because its not allowed to have data which violate the constraints, is there an easy way to do it?

This trigger may work (sql server syntax)
create trigger TR_8
on asset
after insert, update
as
if exists(
select * -- checks if new or modified datum has id between 0 and 8
from inserted
where inserted.id between 0 and 8
)
begin
RAISERROR ('Ids between 0 and 8 must stay untouched', 16, 10); --if so, rollback the transaction giving an error
rollback transaction
end

Related

Oracle - Using a trigger to delete a row

When an insert is made to Condo_assign I am using multiple triggers to add entries to a reserveError table to indicate what the error was. After they are logged in reserveError I am now attempting to use another trigger to delete the record from condo_assign that caused the problem. Basically, the erroneous insert should be logged in ReserveError and Deleted from Condo_assign. The problem is that while my delete trigger compiles and causes no problems, it doesn't appear to do anything. when I select * from condo_assign the erroneous entries are still there.
Condo_Assign table:
CREATE TABLE Condo_Assign (
MID INT
, RID VARCHAR2(3)
, CONSTRAINT Condo_Assign Primary Key (MID,RID)
, CONSTRAINT MID_Assign_FK Foreign Key (MID) references SkiClub (MID)
, CONSTRAINT RID_Assign_FK Foreign Key (RID) references Condo_Reservation (RID)
);
reserveError Table:
CREATE TABLE ReserveError (
Err INT PRIMARY KEY
, MID INT
, RID VARCHAR2(3)
, errorDate DATE
, errorCode VARCHAR2(6)
, errorMsg VARCHAR2(60)
, CONSTRAINT Error_MID_FK FOREIGN KEY (MID) REFERENCES SkiClub
, CONSTRAINT Error_RID_FK FOREIGN KEY (RID) REFERENCES Condo_Reservation
);
Procedure that causes trigger to fire:
CREATE OR REPLACE Procedure addCondo_Assign
(
inMID in Condo_Assign.MID%type
, inRID in Condo_Assign.RID%type
, inPaymentDate in Payment.PaymentDate%type
, inPayment in Payment.Payment%type
)
is
begin
insert into Condo_Assign (MID,RID) values (inMid,inRid);
IF inPayment >= 50 then
insert into Payment (MID,RID,PaymentDate,Payment) values (inMID,inRID,inPaymentDate,inPayment);
ELSE
raise_application_error(-20088,'Deposit less than 50');
end if;
exception
when others then
raise_application_error(-20005,'Cannot add to entry to Condo_Assign Table.');
end addCondo_Assign;
/
Trigger that writes to ReserveError table
-- Trigger to prevent gender mismatchs in room assignment
CREATE OR REPLACE TRIGGER Gender_Assign_Trigger
BEFORE INSERT ON Condo_Assign
FOR EACH ROW
DECLARE
Room_Gender Char(1);
Guest_Gender Char(1);
BEGIN
SELECT Gender
INTO Room_Gender
From Condo_Reservation
WHERE RID = :new.RID;
SELECT Gender
INTO Guest_Gender
FROM SkiClub
WHERE MID = :new.MID;
IF Room_Gender = 'M' AND Guest_Gender = 'F' THEN
addReserveError(:new.MID,:new.RID,SYSDATE,'g00001','Female guest assigned to male room');
ELSIF Room_Gender = 'F' AND Guest_Gender = 'M' THEN
addReserveError(:new.MID,:new.RID,SYSDATE,'g00002','Male guest assigned to female room');
END IF;
END Gender_Assign_Trigger;
/
Trigger that should delete entry from condo_assign:
CREATE OR REPLACE TRIGGER Remove_errors_trigger
after Insert on ReserveError
FOR EACH ROW
BEGIN
DELETE FROM Condo_Assign
WHERE MID = :new.MID and RID = :new.RID;
END remove_errors_trigger;
/
The entire process is started in a before insert trigger.
The code that tries to delete the record won't delete anything because the record has not been inserted yet. There is nothing to delete at the time the delete code is being fired.
Usually checks in triggers prevent the insertion of incorrect data throwing an exception. The code inserting the data will have to handle the exception.
But you already have a procedure that handles the insert. It even performs a check on the deposit. Why not handle the gender check there?

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!

How do I fix SQL Error: ORA-00001: unique constraint (ALERTS2.PK_UP_MODULE_MASTER) violated

Gives me error when I try to insert and it finally inserts after couple of retries with out any error.
SQL Error: ORA-00001: unique constraint (ALERTS2.PK_UP_MODULE_MASTER) violated.
*Cause: An UPDATE or INSERT statement attempted to insert a duplicate key.
INSERT statement:
INSERT INTO up_module_master
(
mr_id,
mr_name,
mr_desc,
mr_parent,
created_by,
created_date,
modified_date,
module_type,
module_link,
link_text,
help_text shortcut_link,
shortcut_name,
shortcut_flag,
module_display_name
)
SELECT max(u1.mr_id)+1,
'Notification Engine',
'Notification Engine Module',
0,1,
SYSDATE,
'',
'',
'../../jalsweb/Logout.jsp',
'HTTP',
'',
'',
'',
0,
'Notification Engine'
FROM up_module_master u1;
Below is the table definition:
CREATE TABLE "up_module_master"
(
"mr_id" NUMBER (10, 0) NOT NULL ENABLE,
"mr_name" VARCHAR2 (200 byte) NOT NULL ENABLE,
"mr_desc" VARCHAR2 (250 byte),
"mr_parent" NUMBER,
"created_by" NUMBER,
"created_date" TIMESTAMP (6),
"modified_date" TIMESTAMP (6),
"module_type" VARCHAR2 (100 byte),
"module_link" VARCHAR2 (200 byte),
"link_text" VARCHAR2 (250 byte),
"help_text" VARCHAR2 (250 byte),
"shortcut_link" VARCHAR2 (400 byte),
"shortcut_name" VARCHAR2 (100 byte),
"shortcut_flag" NUMBER,
"module_display_name" VARCHAR2 (100 byte),
"audit_type" VARCHAR2 (100 byte),
"service_id" NUMBER,
"module_regis_type" NUMBER DEFAULT 1,
CONSTRAINT "PK_UP_MODULE_MASTER" PRIMARY KEY ("mr_id"),
CONSTRAINT "UP_MODULE_MASTER_UP_MODUL_FK1" FOREIGN KEY ("mr_parent")
REFERENCES "up_module_master" ("mr_id") ENABLE
)
Looks like MR_ID is not an identity seed. If another process is attempting to insert a record at the same time as you, both will try to insert the same ID and you will get this error. I suggest that you change the column to be auto incrementing. You will need to create a sequence and then a trigger if using pre version 12 or the identity column if using later versions:
Oracle: how to create an identity column?
The link above has all the details for doing this.
the problem is, that someone other inserted and commited a row with the same key meanwhile
consider using a sequence (it looks like the sequence is already defined):
SELECT seq_name.nextval, ... FROM dual
The reason why it's failing is because "select max(mr_id) + 1 ..." is going to be a fixed number for all rows that you're selecting - it's not going to increment for each row in your select statement. (Duh! See comments below!)
As others have said, use a sequence! (Yes, there are other ways you could use to get unique values as part of your select statement, but they'd be the wrong thing to use. Sequences FTW!)

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

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