check constraint check the column twice - oracle

What is wrong in this error ?
alter table INFO add constraint chk_app check
(CASE WHEN app IS NULL THEN app = 'A');
If its because app = 'A' I am calling it twice then how to have a check constraint to check if app is null then it should have value A

If you want to set the column app to 'A' whenever a row is inserted with a NULL value, I'd use a DEFAULT construct:
ALTER TABLE info MODIFY (app VARCHAR2(xxx) DEFAULT 'A');
If no value is specified during an INSERT, an 'A' is inserted into column app. Of course, a user can override this behaviour by explicitly inserting a NULL value. This can be prevented by a NOT NULL constraint:
ALTER TABLE info MODIFY (app VARCHAR2(xxx) DEFAULT 'A' NOT NULL);
From Oracle version 12c on, you can specify the required behaviour more clearly:
ALTER TABLE info MODIFY (app VARCHAR2(xxx) DEFAULT ON NULL 'A' NOT NULL);

This is bacause check constraint only checks the value, it is not able to change it.
You can simply add default value to app column or write before insert or update trigger like this
create or replace trigger info_briu
before insert or update of info
for each row
begin
if :new.app is null then
:new.app := 'A';
end if;
end;

Related

Why do I keep getting this error when creating a trigger?

I am creating a trigger that checks if the Majorcode column is null BEFORE INSERT OR UPDATE and if it is it enters the default value "100"
My code:
CREATE TRIGGER MUmajorcode_changes
BEFORE INSERT OR UPDATE ON M_Students
FOR EACH ROW
BEGIN
IF NEW.Majorcode = null THEN
SET NEW.Majorcode = '100';
END IF;
I get the following message after running it
Warning: Trigger created with compilation errors.
Then when I actually insert a new value with blank major code.
I receive the following message/error:
ERROR at line 1:
ORA-04098: trigger 'SCOTT.MUMAJORCODE_CHANGES' is invalid and failed re-validation.
This is how I setup the table initially:
CREATE TABLE M_Students
(
ID CHAR(3) PRIMARY KEY,
FName VARCHAR2(25),
LName VARCHAR2(25),
Status VARCHAR2(25),
Majorcode CHAR(3) REFERENCES Departments(DeptCode),
GPA NUMBER (4,2),
AdmittedDate DATE
);
Cannot figure out where I am going wrong?
When you get the message "created with compilation errors" it means your script is invalid, it has compile time errors. If your IDE does not show them you to you then if you are using sqlplus then run "show errors" if you are using an IDE run the query "select * from user_errors" (and get a new IDE). Either will show the errors in the script, they must be corrected; your script will not run until they are.
The suggestions of setting a DEFAULT value in the table definition has merit but will fail on a couple conditions. When Inserting the default will be taken when the column name is not mentioned in column list. (Note Omitting the column list is implicitly mentioning all columns so the default would not be set.) Nor would it handle update condition.
Your trigger itself can be reduced to a single statement with the coalesce function:
create or replace trigger mumajorcode_changes
before insert or update of mumajorcode
on m_students
for each row
begin
:new.majorcode := coalesce(:new.majorcode, '100');
end;
You have some syntax errors:
CREATE OR REPLACE TRIGGER MUmajorcode_changes /* better use REPLACE to avoid dropping the trigger */
BEFORE INSERT OR UPDATE
ON M_Students
FOR EACH ROW
BEGIN
IF :new.Majorcode IS NULL /* :new, with the colon (:) */
THEN
:new.Majorcode := '100'; /* :new, and no SET */
END IF;
END; /* a missing END */
Also, never check null values with =, but always use is [not] null.
There are some obvious syntax errors such as wrong assignment, missing or superfluous keywords, but you don't need to create a database trigger to handle this operation. Just modify the related columns property by
ALTER TABLE M_Students
MODIFY Majorcode DEFAULT '100' NOT NULL
Through this property, Majorcode column is already populated by the value '100' during the insertion automatically, and updating that column to NULL won't be possible because of the NOT NULL constraint.
Demo

SQL_Before_Insert_Trigger

we have the problem in the select clause. How can we control which users can access which documents and present this to a trigger.
Task:
Implement a trigger that guarantees that an entry (insert) in the "Access" table may only be made if the accessing user for the document belonging to the versionid is also entered in the "Access Permission" table.
create or replace trigger access_trg
before insert
on access
referencing new as newRow
for each row
declare accessvar varchar2(32);
begin
dbms_output.put_line('enter access');
dbms_output.put_line(':newRow.user = ' || :newRow.user);
dbms_output.put_line(':newRow.version = ' || :newRow.version);
dbms_output.put_line(':newRow.date = ' || :newRow.date);
dbms_output.put_line(':newRow.art = ' || :newRow.art);
--------------------------???????????????---------------------------
--------------------------???????????????---------------------------
Select z.version into accessvar from access-permission z
where z.user = :newRow.user;
if (:newRow.version in (accessvar))
then
dbms_output.put_line('Access');
else if
raise_application_error(-54781, 'No Access');
end if;
end access_trg
create table version (
versionId varchar2(15) primary key,
createdby references user(userId) not null,
creatdate date not null,
document references document(documentid) not null,
text clob,
unique (createdby, creatdate, document));
create table accesspermission (
user references user(userid) not null,
document references document(documentid) not null,
primary key(user, document));
create table access (
user references user(userid) not null,
version references version(versionid) not null,
date date not null,
type varchar(10) check(type in ('new', 'read')),
primary key (user, version, date));
Tables with inserts
Certainly you have a problem with SELECT; apart from syntax error (table name shouldn't contain a "minus" sign; it's probably an "underline"), you are selecting a column (version) which does not exist in the access_permission table. It is difficult to suggest anything if data model you presented isn't correct.
I presume that - once you fix that - you might hit the TOO_MANY_ROWS error if table contains more than a single row for that :newRow.user. What to do? It depends; one option is to add another condition(s) to where clause, or to use aggregate function (such as max) and select the highest version, maybe to use exists ... can't tell.
Furthermore, you're raising error -54781; Oracle reserved -20000 to -20999 for us, developers. Your value is out of that range, so - you should change it.

Modify column value Oracle

Hello I have made a Trigger it compiles
CREATE OR REPLACE TRIGGER livraisonfinie
BEFORE UPDATE ON Expedition
FOR EACH ROW
DECLARE
BEGIN
IF :NEW.date_livraison <> TO_DATE('3000/01/01 00:00:00', 'yyyy/mm/dd hh24:mi:ss')
THEN
INSERT INTO Commande (etat) VALUES ('livree');
DELETE FROM cmdalivrer CMD WHERE :NEW.numero_commande=CMD.id_cmd WHERE :NEW.numero_commande= Commande.numero_commande;;
END IF ;
END;
/
When I try to update a value of expedition table I get this error
ORA-01400: cannot insert NULL into ("HAMZA"."COMMANDE"."NUMERO_COMMANDE")
ORA-06512: at "HAMZA.LIVRAISONFINIE", line 10
ORA-04088: error during execution of trigger 'HAMZA.LIVRAISONFINIE'
And I have used this update request but not sure if I have to use INSERT INTO or UPDATE and how corretly even after reading many manuals.
Here's the table
Expedition(Id_Expedition ,#id_chauffeur,#Immatriculation, #Id_Itineraire,Date_Deb_Expedition , Date_Livraison)
Commande (numero_commande,Date_commande,adresse_livraison,id_part,ville_livraison,code_postal_livraison,etat,id_expedition)
EDIT: I solved it by adding "where :NEW.numero_commande= Commande.numero_commande;" to my trigger.
Thanks
There is NOT NULL constraint on column NUMERO_COMMANDE in table COMMANDE.
More on this constraint you can find here:
http://www.w3schools.com/sql/sql_notnull.asp
By default, a table column can hold NULL values.
SQL NOT NULL Constraint
The NOT NULL constraint enforces a column to
NOT accept NULL values.
The NOT NULL constraint enforces a field to always contain a value.
This means that you cannot insert a new record, or update a record
without adding a value to this field.
Either provide a value for this field in your trigger:
INSERT INTO Commande (etat,NUMERO_COMMANDE)
VALUES ('livree', some-value-for-numero-commande-column);
or remove NOT NULL constraint on this column from the table.

date Not null , error ora_01758

why I am getting this error ?
In the table DDL I only have 2 columns , id (number) and name (varchar)
ALTER TABLE mytable ADD SUSPEND date NOT NULL
ORA-01758: table must be empty to add mandatory (NOT NULL) column
ORA-06512: at line 7
ORA-01758: table must be empty to add mandatory (NOT NULL) column ORA-06512: at line 7
And is your table empty? I think not.
There's probably a way around this involving adding the column as nullable, then populating every row with a non-NULL value, the altering the column to be not null.
Alternatively, since the problem is that these current rows will be given NULL as a default value, and the column is not allowed to be NULL, you can also get around it with a default value. From the Oracle docs:
However, a column with a NOT NULL constraint can be added to an existing table if you give a default value; otherwise, an exception is thrown when the ALTER TABLE statement is executed.
Here is a fiddle, how you could do it
Would a date in the future be acceptable as a temporary default? If so, this would work:
ALTER TABLE MYTABLE ADD (SUSPEND_DATE DATE DEFAULT(TO_DATE('21000101', 'YYYYMMDD'))
CONSTRAINT SUSPEND_DATE_NOT_NULL NOT NULL);
If table already contain the records then table won't allowes to add "Not null" column.
If you need same then set default value for the column or truncate the table then try.

What do references to OLD evaluate to in the WHEN cause of an Oracle insert trigger?

When writing a row-level trigger in Oracle, I know that you can use the OLD and NEW pseudo-records to reference the old and new state of the row that fired the trigger. I know that in an INSERT trigger OLD doesn't contain any data, but I'm not sure how this affects the evaluation of a WHEN clause for that trigger. For example, if I have the following trigger:
CREATE OR REPLACE TRIGGER mung_row
BEFORE INSERT OR UPDATE ON some_table
FOR EACH ROW
BEGIN
:NEW.foo = 'some val';
END;
and I want to modify this trigger to only run on an update when foo was previously null, but always run on an insert, I could satisfy the update part of the change by adding a WHERE clause:
CREATE OR REPLACE TRIGGER mung_row
BEFORE INSERT OR UPDATE ON some_table
FOR EACH ROW
WHEN (OLD.foo IS NULL)
BEGIN
:NEW.foo = 'some val';
END;
Will this cause problems in the insert case? What will OLD.foo evaluate to in the INSERT?
I'm aware that I could split the INSERT and UPDATE triggers or use INSERTING/UPDATING/DELETING in the trigger body, but I'd rather not in the case that inspired this question.
When a record is being inserted, every field of OLD will be NULL, including the fields marked as NOT NULL in the table's definition.
For example, suppose your table has a non-nullable column named id:
CREATE TABLE some_table (
id NUMBER NOT NULL,
foo VARCHAR2(100)
)
When a record is inserted into this table, OLD.id will be NULL. However, when a record is updated in this table, OLD.id will not be NULL. Because you only want to change :NEW.foo if a record is being updated, you just have to check to see if OLD.id has a non-null value.
CREATE OR REPLACE TRIGGER mung_row
BEFORE INSERT OR UPDATE ON some_table
FOR EACH ROW
WHEN (OLD.id IS NOT NULL AND OLD.foo IS NULL)
BEGIN
:NEW.foo = 'some val';
END;

Resources