How to allow oracle table column to have multiple rows in column but sames values only. Using Constraints - sql

How to allow oracle table column to have multiple rows in column but same value only.
Create Table test ( col int);
case - I
insert into test values (1);
--should work
insert into test values (1);
--should work
insert into test values (2);
--Should throw error !!!!
case - II
truncate table test;
insert into test values (2);
--should work
insert into test values (2);
--Should work
insert into test values (1);
--Should throw error !!!!!!

If I have understood your requirement correctly, you can use before insert trigger. Check the value present in table, if new value matches with table value or table is having no data then only allow insert.
Here's the link about trigger
http://docs.oracle.com/cd/B19306_01/appdev.102/b14251/adfns_triggers.htm

UPDATE
Based on OP's two cases, I think a BEFORE INSERT TRIGGER would do the job:
Test case:
SQL> DROP TABLE TEST PURGE;
Table dropped.
SQL>
SQL> CREATE TABLE test
2 ( col INT
3 );
Table created.
SQL>
SQL> CREATE OR REPLACE TRIGGER trg BEFORE
2 INSERT ON TEST FOR EACH ROW DECLARE ID NUMBER;
3 BEGIN
4 BEGIN
5 SELECT DISTINCT col INTO ID FROM TEST;
6 EXCEPTION
7 WHEN no_data_found THEN
8 NULL;
9 END;
10 IF :NEW.col <> id THEN
11 RAISE_APPLICATION_ERROR(-20001, 'Cannot Insert different value in the table');
12 END IF;
13 END;
14 /
Trigger created.
SQL>
The NO_DATA_FOUND exception is to ignore the first insert, since there would be no rows before that.
Now, let's test the INSERT statements:
CASE 1
SQL> INSERT INTO TEST VALUES (1);
1 row created.
SQL>
SQL> INSERT INTO TEST VALUES (1);
1 row created.
SQL>
SQL> INSERT INTO TEST VALUES (2);
INSERT INTO TEST VALUES (2)
*
ERROR at line 1:
ORA-20001: Cannot Insert different value in the table
ORA-06512: at "LALIT.TRG", line 10
ORA-04088: error during execution of trigger 'LALIT.TRG'
SQL>
CASE 2
SQL> TRUNCATE TABLE TEST;
Table truncated.
SQL>
SQL> INSERT INTO TEST VALUES (2);
1 row created.
SQL>
SQL> INSERT INTO TEST VALUES (2);
1 row created.
SQL>
SQL> INSERT INTO TEST VALUES (1);
INSERT INTO TEST VALUES (1)
*
ERROR at line 1:
ORA-20001: Cannot Insert different value in the table
ORA-06512: at "LALIT.TRG", line 10
ORA-04088: error during execution of trigger 'LALIT.TRG'
SQL>

Related

Sql trigger not functioning

CREATE OR REPLACE TRIGGER STUDENT
BEFORE INSERT
ON STUDENT
FOR EACH ROW
BEGIN
IF :NEW.ENO =NULL THEN
RAISE_APPLICATION_ERROR(-21900, 'ENROLL_NO IS MISSING');
END IF;
END;
So this was my trigger definition
But when I try to NUll values its accepted
I'm learning
It is not = null, but is null:
SQL> CREATE OR REPLACE TRIGGER trg_bi_student
2 BEFORE INSERT ON STUDENT
3 FOR EACH ROW
4 BEGIN
5 IF :NEW.ENO is NULL THEN
6 RAISE_APPLICATION_ERROR(-21900, 'ENROLL_NO IS MISSING');
7 END IF;
8 END;
9 /
Trigger created.
SQL> insert into student (eno, name) values (1, 'Little');
1 row created.
SQL> insert into student (eno, name) values (null, 'Foot');
insert into student (eno, name) values (null, 'Foot')
*
ERROR at line 1:
ORA-21000: error number argument to raise_application_error of -21900 is out of
range
ORA-06512: at "SCOTT.TRG_BI_STUDENT", line 3
ORA-04088: error during execution of trigger 'SCOTT.TRG_BI_STUDENT'
SQL>
Though, why trigger? That's a not null constraint (most probably a primary key):
SQL> drop table student;
Table dropped.
SQL> create table student (eno number constraint pk_student primary key,
2 name varchar2(10));
Table created.
SQL> insert into student (eno, name) values (1, 'Little');
1 row created.
SQL> insert into student (eno, name) values (null, 'Foot');
insert into student (eno, name) values (null, 'Foot')
*
ERROR at line 1:
ORA-01400: cannot insert NULL into ("SCOTT"."STUDENT"."ENO")
SQL>
As of your second trigger (posted in a comment): if you show errors, then:
SQL> CREATE OR REPLACE TRIGGER TOTALMARKS
2 BEFORE INSERT ON STUDENT
3 FOR EACH ROW
4 BEGIN
5 :NEW.TOTAL: =:NEW.S1+:NEW.S2+:NEW.S3;
6 DBMS_OUTPUT.PUT_LINE('TOTAL="| | :NEW. TOTAL) ;
7 END;
8 /
Warning: Trigger created with compilation errors.
SQL> show err
Errors for TRIGGER TOTALMARKS:
LINE/COL ERROR
-------- -----------------------------------------------------------------
2/11 PLS-00103: Encountered the symbol " " when expecting one of the
following:
:= . ( # % ; indicator
SQL>
This is the 2nd line in excecutable part of the trigger:
:NEW.TOTAL: =:NEW.S1+:NEW.S2+:NEW.S3;
1234567890123456
^
|
11th character
It says that you should've used := and not : = (i.e. no space in between), but then you get another error:
SQL> CREATE OR REPLACE TRIGGER TOTALMARKS
2 BEFORE INSERT ON STUDENT
3 FOR EACH ROW
4 BEGIN
5 :NEW.TOTAL :=:NEW.S1+:NEW.S2+:NEW.S3;
6 DBMS_OUTPUT.PUT_LINE('TOTAL="| | :NEW. TOTAL) ;
7 END;
8 /
Warning: Trigger created with compilation errors.
SQL> show err
Errors for TRIGGER TOTALMARKS:
LINE/COL ERROR
-------- -----------------------------------------------------------------
3/22 PLS-00103: Encountered the symbol "TOTAL="| | :NEW. TOTAL) ;
END;" when expecting one of the following: (...)
You can't enclose strings into double quotes - use single ones. But, there's another error (consecutive pipe sign for concatenation), and yet another (no space between :new and .total), until finally it compiles:
SQL> CREATE OR REPLACE TRIGGER TOTALMARKS
2 BEFORE INSERT ON STUDENT
3 FOR EACH ROW
4 BEGIN
5 :NEW.TOTAL :=:NEW.S1+:NEW.S2+:NEW.S3;
6 DBMS_OUTPUT.PUT_LINE('TOTAL='|| :NEW.TOTAL) ;
7 END;
8 /
Trigger created.
SQL>

Trying to insert multiple rows in my table in SQL.Always showing SQL Command not ended properly [duplicate]

This question already has answers here:
Best way to do multi-row insert in Oracle?
(9 answers)
Closed 1 year ago.
I am trying to insert multiple rows into my table using the below query : INSERT INTO TABLE2(ID) VALUES(1),(2) .It is showing SQL Command Not Ended.
Is it some syntacital error?I have rechecked but still not clear what's going wrong.
Invalid syntax, of course. But, here are 3 options that work.
SQL> create table table2(id number);
Table created.
SQL>
SQL> insert into table2(id) values(1);
1 row created.
SQL> insert into table2(id) values(2);
1 row created.
SQL>
SQL> insert all
2 into table2(id) values (1)
3 into table2(id) values (2)
4 select * from dual;
2 rows created.
SQL>
SQL> insert into table2(id)
2 select 1 from dual
3 union all
4 select 2 from dual;
2 rows created.
SQL>

trigger in oracle that ensures that the value of ExpDate from the table ExpIt is less than or equal to the ERSubDate from the ExpReport

I am trying to create a trigger in oracle that ensures that the value of ExpDate from the table ExpIt is less than or equal to the ERSubDate from the ExpReport on INSERT and UPDATE statements that change the ExpDate in the ExpIt table.
When ran in the command prompt, the following comes up
warning: Trigger created with compilation errors.
Here is what I have tried so far, where am I going wrong?
Thank you in advance.
CREATE OR REPLACE TRIGGER Expense_Date
BEFORE INSERT OR UPDATE OF ExpDate
ON ExpIt
FOR EACH ROW
DECLARE
anExpDate ExpIts.ExpDate%TYPE;
anERSubDate ExpReport.ERSubDate%TYPE;
DateError EXCEPTION;
ExMessage VARCHAR(200);
BEGIN
SELECT ExpDate, ERSubDate
INTO anExpDate, anERSubDate
FROM ExpIt, ExpReport
WHERE ExpIt.ExpDate = :NEW.ExpDate;
IF anExpDate <= anERSubDate THEN
RAISE DateError;
END IF;
EXCEPTION
WHEN DateError THEN
ExMessage := ExMessage || 'Expense Date is Incorrect as it is after the Expense Report Submition date' ||
to_date(anExpDate);
raise_application_error(-20001, ExMessage);
END;
/
Before you go too far down this track - be aware that you generally cannot access the table you are triggering on from within the trigger itself.
In your case, your trigger is on EXPIT and you want to query EXPIT. That won't work.
Here's a trivial example of that:
SQL> create table t (x int );
Table created.
SQL> insert into t values (1);
1 row created.
SQL> commit;
Commit complete.
SQL>
SQL> create or replace
2 trigger TRG
3 before insert on T
4 for each row
5 declare
6 blah int;
7 begin
8 select count(*) into blah from t;
9 end;
10 /
Trigger created.
SQL>
SQL> insert into t values (2);
1 row created.
It looks fine, but in reality, there are plenty of cases where it will NOT work
SQL> insert into t
2 select rownum from dual
3 connect by level <= 5;
insert into t
*
ERROR at line 1:
ORA-04091: table MCDONAC.T is mutating, trigger/function may not see it
ORA-06512: at "MCDONAC.TRG", line 4
ORA-04088: error during execution of trigger 'MCDONAC.TRG'
This is a big topic, and more details on the issue and how to work around it are here
https://asktom.oracle.com/pls/apex/asktom.search?file=MutatingTable.html#presentation-downloads-reg

Insert All with Sequence.nextVal Generates Unique Constraint violation [duplicate]

This question already has answers here:
Inserting multiple rows with sequence in Oracle
(5 answers)
Closed 4 years ago.
Why does this query throw an error:
Error report -
ORA-00001: unique constraint (ON24MASTER.LANGUAGE_CODE_PK) violated
Query
INSERT ALL
INTO LANGUAGE_CODE(language_code_id,label,language_cd,country_cd,is_elite)
VALUES(SEQ_LANGUAGE_CODE_ID.NEXTVAL,'Abkhazian','ab',NULL,'N')
INTO LANGUAGE_CODE(language_code_id,label,language_cd,country_cd,is_elite)
VALUES(SEQ_LANGUAGE_CODE_ID.NEXTVAL,'Afar','aa',NULL,'N')
INTO LANGUAGE_CODE(language_code_id,label,language_cd,country_cd,is_elite)
VALUES(SEQ_LANGUAGE_CODE_ID.NEXTVAL,'Afrikaans','af',NULL,'N')
INTO LANGUAGE_CODE(language_code_id,label,language_cd,country_cd,is_elite)
VALUES(SEQ_LANGUAGE_CODE_ID.NEXTVAL,'Akan','ak',NULL,'N')
SELECT 1 FROM DUAL;
Considering select seq_language_code_id.nextval from dual; = 198 and the latest id in db is 180;
What is wrong ? can I not use insert all with .nextVal ?
Nope, you can't do it with INSERT ALL. Have a look at what's going on:
SQL> create sequence seqa;
Sequence created.
SQL> create table test (id number);
Table created.
SQL> insert all
2 into test values (seqa.nextval)
3 into test values (seqa.nextval)
4 into test values (seqa.nextval)
5 into test values (seqa.nextval)
6 select * from dual;
4 rows created.
SQL> select * From test;
ID
----------
1
1
1
1
SQL>
See? All NEXTVALs are just the same, which - in your case - leads to a primary key violation, which means that you'll have to run separate INSERT INTO statements:
SQL> insert into test values (seqa.nextval);
1 row created.
SQL> insert into test values (seqa.nextval);
1 row created.
SQL> insert into test values (seqa.nextval);
1 row created.
SQL> select * From test;
ID
----------
1
1
1
1
2
3
4
7 rows selected.
SQL>

Multi line comment in oracle sqlplus

I have ran the below statements in sqlplus. It inserts duplicate of row 2. In log I have found that i row created after the comment line as well.
So, here I am asking the multi line comment should have a space between /* and comment and */ ?
insert into table values (1);
insert into table values (2);
/*comments here*/
insert into table values (3);
commit;
Log:
SQL> insert into table values (1);
1 row created.
SQL> insert into table values (2);
1 row created.
**SQL> /*comments here*/
1 row created.**
SQL> insert into table values (3);
1 row created.
select A from table;
A
------------
1
2
2
3
All,
I have tried in sqlplus. We need to give the space or new line between /* and following characters. So it treated as multi line comment.
correct syntax:
/* comments here */
or
/*
comments here
*/
Wrong syntax:
/*comments here*/
I presume that your code contains an extra forward slash. Have a look:
SQL> create table test (id number);
Table created.
SQL> insert into test values (1);
1 row created.
SQL> insert into test values (2);
1 row created.
SQL> /* comments
SQL> here
SQL> */
SQL> / --> this one; it executes the last command in buffer ...
1 row created. --> ... and results with yet another "2" begin inserted
SQL> insert into test values (3);
1 row created.
SQL> select * from test;
ID
----------
1
2
2
3
SQL>
Without it, everything is OK:
SQL> truncate table test;
Table truncated.
SQL> insert into test values (1);
1 row created.
SQL> insert into test values (2);
1 row created.
SQL> /* comments
SQL> here
SQL> */
SQL> insert into test values (3);
1 row created.
SQL> select * from test;
ID
----------
1
2
3
SQL>