Issue happening when creating a trigger in Oracle SQL (Online) - sql

I'm facing a problem while creating a trigger in Oracle SQL (Online). Please find the issue(s) with the code.
These are my codes.
customers table code:
CREATE TABLE customers(
cusid INT PRIMARY KEY,
cusnm VARCHAR(10),
cusadd VARCHAR(10)
)
audits table code:
CREATE TABLE audits(
table_name VARCHAR2(255),
transaction_name VARCHAR2(10),
by_user VARCHAR2(30),
transaction_date DATE
)
Trigger code:
CREATE OR REPLACE TRIGGER customers_audit_trg
AFTER
UPDATE OR DELETE
ON customers
FOR EACH ROW
DECLARE
tx VARCHAR2(10);
BEGIN
--determine the transaction type
tx := CASE
WHEN UPDATING THEN 'UPDATE'
WHEN DELETING THEN 'DELETE'
END;
--insert a row into the audit table
INSERT INTO audits(table_name, transaction_name, by_user, transaction_date)
VALUES('customers', tx, USER, SYSDATE)
END;
/
Errors:
Errors: TRIGGER CUSTOMERS_AUDIT_TRG
Line/Col: 2/8 PLS-00103: Encountered the symbol "=" when expecting one of the following:
constant exception <an identifier>
<a double-quoted delimited-identifier> table columns long
double ref char time timestamp interval date binary national
character nchar

It was just a semicolon missing issue.
--insert a row into the audit table
INSERT INTO audits(table_name, transaction_name, by_user, transaction_date)
VALUES('customers', tx, USER, SYSDATE);

Related

How to access value of column from one table in trigger of another table

Created Star Schema where Sales is a fact table and Product_Dimension is one of the dimension tables.
Created Product_Dimension table
Create Table Product_Dimension
(Product_ID char(6),
Product_Name varchar(20),
Product_Category varchar(10),
Unit_Price decimal(6,2));
alter table Product_Dimension add constraint pk_Product_Dimension
Primary key(Product_ID);
Created Fact table-sales
Create table Sales(
Product_ID char(5),Order_ID char(5),Customer_ID char(6),Employer_ID
char(5),total int, Quantity int, Discount decimal(5,2),
foreign key (Product_ID) references Product_Dimension(Product_ID),
foreign key (Order_ID) references Time_Dimension(Order_id),
foreign key (Customer_ID) references Customer_Dimension(Customer_ID),
foreign key (Employer_ID) references Emp_Dimension(Emp_ID)
);
I want to create a trigger which calculates value of Total from values of Quantity and Discount from Sales table and Unit_Price from Product_Dimension table.
So every time we insert value in Sales, it should take Quantity(taken from insert query we trying to replace) multiply it with Unit_Price from Product_Dimension table where Product_IDs are matching and subtract Discount(taken from insert query)
Sales_view is a view of Sales table
CREATE or replace TRIGGER Update_Total
instead of insert on Sales_view for each row
declare
y decimal(6,2);
x decimal(6,2);
begin
x:=select pd.Unit_Price from Product_Dimension where
pd.Product_ID=:NEW.Product_ID;
y:=(:NEW.Quantity*x)-:NEW.Discount
insert into
Sales_view(Product_ID,Order_ID,Customer_ID,Employer_ID,total,
Quantity,
Discount)
values(:NEW.Product_ID,:NEW.Order_ID,:NEW.Customer_ID,:NEW.Employer
y,:NEW.Quantity,:NEW.Discount);
end;
This gives following errors in oracle-live sql:
Errors: TRIGGER UPDATE_TOTAL
Line/Col: 6/4 PLS-00103: Encountered the symbol "SELECT" when
expecting one of the following:
( - + case mod new not null <an identifier>
<a double-quoted delimited-identifier> <a bind variable>
continue avg count current exists max min prior sql stddev
sum variance execute forall merge time timestamp interval
date <a string literal with character set specification>
<a number> <a single-quoted SQL string> pipe
<an alternatively-quoted string literal with character set
specification>
<an alternat
Line/Col: 7/1 PLS-00103: Encountered the symbol "Y"
Line/Col: 7/35 PLS-00103: Encountered the symbol ";" when expecting
one
of the following:
. ( ) , * # % & = - + < / > at in is mod remainder not rem
<an exponent (**)> <> or != or ~= >= <= <> and or like like2
like4 likec between || indicator member submultiset
Line/Col: 12/4 PLS-00103: Encountered the symbol "end-of-file" when
expecting one of the following:
end not pragma final instantiable persistable order
overriding static member constructor map
Your Trigger syntax is wrong. The correct syntax should look alike -
CREATE OR REPLACE TRIGGER Update_Total
INSTEAD OF INSERT ON Sales_view
FOR EACH ROW
DECLARE
y decimal(6,2);
x decimal(6,2);
BEGIN
SELECT pd.Unit_Price
INTO x
FROM Product_Dimension
WHERE pd.Product_ID=:NEW.Product_ID;
y := (:NEW.Quantity*x) - :NEW.Discount;
INSERT INTO Sales_view (Product_ID, Order_ID, Customer_ID, Employer_ID,
total, Quantity, Discount)
VALUES (:NEW.Product_ID, :NEW.Order_ID, :NEW.Customer_ID, :NEW.Employer,
y,:NEW.Quantity,:NEW.Discount);
END;

Making a trigger to not create an insurance policy for a driver that has been involved in an accident

Hello I am brand new to triggers in SQL and need some help with one. I am working with 3 tables involving drivers, car accidents, and insurance policy. What I am trying to do is create a trigger that will not allow insurance policies to be able to be made for drivers involved in an accident.
Here is what I have tried so far:
CREATE TABLE insurance_policy(
id INT,
ssn_driver INT,
expiration_date DATE,
PRIMARY KEY (id)
);
CREATE TABLE accident(
id INT,
ssn_driver INT,
accident_date DATE,
details VARCHAR2(64),
PRIMARY KEY (id),
FOREIGN KEY (id) REFERENCES insurance_policy,
FOREIGN KEY (ssn_driver) REFERENCES driver
);
CREATE TABLE driver(
ssn_driver INT,
name VARCHAR2(64),
age INT CHECK (age>15),
PRIMARY KEY(ssn_driver)
);
CREATE TRIGGER no_insurance_policy
AFTER INSERT OR UPDATE ON insurance_policy
FOR EACH ROW
BEGIN
IF EXISTS (select ssn_driver FROM Inserted INNER JOIN accident)
BEGIN
rollback transaction
raiserror ('some message', 16, 1)
END
END
This doesn't compile, but I'm just confused on how to proceed from here. Can anyone help me out with creating this trigger?
EDIT: Here is the error
Error starting at line : 31 in command -
BEGIN
IF EXISTS (select ssn_driver FROM Inserted INNER JOIN accident)
BEGIN
rollback transaction
raiserror ('some message', 16, 1)
END
END
Error report -
ORA-06550: line 2, column 58:
PLS-00103: Encountered the symbol "JOIN" when expecting one of the following:
) , with group having intersect minus start union where
connect
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
First, you need to do BEFORE not AFTER insert. Then, your syntax is not even Oracle. Here is approximately what you need to do. I have not tested it.
CREATE TRIGGER no_insurance_policy
BEFORE INSERT OR UPDATE ON insurance_policy
FOR EACH ROW
DECLARE
v_accidentCout NUMBER(10);
BEGIN
Select Count(*) Into v_accidentCout
From accident
Where ssn_driver = old.ssn_driver;
If v_accidentCout > 0 Then
raise_application_error(-12345, 'Driver has accidents');
End If;
END;
/
I would leave commit/rollback to the block that calls insert/update.

How to create SEQUENCE for GLOBAL TEMPORARY TABLE in oracle?

For example
CREATE GLOBAL TEMPORARY TABLE GGT_temp_reversal
(
sessionid VARCHAR (50) NULL,
syspk NUMERIC (23)
)
ON COMMIT DELETE ROWS ;
CREATE SEQUENCE GGT_temp_reversal_seq;
CREATE OR REPLACE TRIGGER GGT_temp_reversal_bir
BEFORE INSERT ON GGT_temp_reversal
FOR EACH ROW
WHEN (new.id IS NULL)
BEGIN
:new.id := GGT_temp_reversal_seq.NEXTVAL;
END;
Getting error "%s: invalid identifier"
You are creating trigger for an ID column
:new.id := GGT_temp_reversal_seq.NEXTVAL;
But you haven't declared it in CREATE TABLE
CREATE GLOBAL TEMPORARY TABLE GGT_TEMP_REVERSAL (
SESSIONID VARCHAR(50) NULL,
SYSPK NUMERIC(23)
)
Add an ID column and it will be fine

Unable to fix SQL syntax error [duplicate]

It appears that there is no concept of AUTO_INCREMENT in Oracle, up until and including version 11g.
How can I create a column that behaves like auto increment in Oracle 11g?
There is no such thing as "auto_increment" or "identity" columns in Oracle as of Oracle 11g. However, you can model it easily with a sequence and a trigger:
Table definition:
CREATE TABLE departments (
ID NUMBER(10) NOT NULL,
DESCRIPTION VARCHAR2(50) NOT NULL);
ALTER TABLE departments ADD (
CONSTRAINT dept_pk PRIMARY KEY (ID));
CREATE SEQUENCE dept_seq START WITH 1;
Trigger definition:
CREATE OR REPLACE TRIGGER dept_bir
BEFORE INSERT ON departments
FOR EACH ROW
BEGIN
SELECT dept_seq.NEXTVAL
INTO :new.id
FROM dual;
END;
/
UPDATE:
IDENTITY column is now available on Oracle 12c:
create table t1 (
c1 NUMBER GENERATED by default on null as IDENTITY,
c2 VARCHAR2(10)
);
or specify starting and increment values, also preventing any insert into the identity column (GENERATED ALWAYS) (again, Oracle 12c+ only)
create table t1 (
c1 NUMBER GENERATED ALWAYS as IDENTITY(START with 1 INCREMENT by 1),
c2 VARCHAR2(10)
);
Alternatively, Oracle 12 also allows to use a sequence as a default value:
CREATE SEQUENCE dept_seq START WITH 1;
CREATE TABLE departments (
ID NUMBER(10) DEFAULT dept_seq.nextval NOT NULL,
DESCRIPTION VARCHAR2(50) NOT NULL);
ALTER TABLE departments ADD (
CONSTRAINT dept_pk PRIMARY KEY (ID));
SYS_GUID returns a GUID-- a globally unique ID. A SYS_GUID is a RAW(16). It does not generate an incrementing numeric value.
If you want to create an incrementing numeric key, you'll want to create a sequence.
CREATE SEQUENCE name_of_sequence
START WITH 1
INCREMENT BY 1
CACHE 100;
You would then either use that sequence in your INSERT statement
INSERT INTO name_of_table( primary_key_column, <<other columns>> )
VALUES( name_of_sequence.nextval, <<other values>> );
Or you can define a trigger that automatically populates the primary key value using the sequence
CREATE OR REPLACE TRIGGER trigger_name
BEFORE INSERT ON table_name
FOR EACH ROW
BEGIN
SELECT name_of_sequence.nextval
INTO :new.primary_key_column
FROM dual;
END;
If you are using Oracle 11.1 or later, you can simplify the trigger a bit
CREATE OR REPLACE TRIGGER trigger_name
BEFORE INSERT ON table_name
FOR EACH ROW
BEGIN
:new.primary_key_column := name_of_sequence.nextval;
END;
If you really want to use SYS_GUID
CREATE TABLE table_name (
primary_key_column raw(16) default sys_guid() primary key,
<<other columns>>
)
In Oracle 12c onward you could do something like,
CREATE TABLE MAPS
(
MAP_ID INTEGER GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1) NOT NULL,
MAP_NAME VARCHAR(24) NOT NULL,
UNIQUE (MAP_ID, MAP_NAME)
);
And in Oracle (Pre 12c).
-- create table
CREATE TABLE MAPS
(
MAP_ID INTEGER NOT NULL ,
MAP_NAME VARCHAR(24) NOT NULL,
UNIQUE (MAP_ID, MAP_NAME)
);
-- create sequence
CREATE SEQUENCE MAPS_SEQ;
-- create tigger using the sequence
CREATE OR REPLACE TRIGGER MAPS_TRG
BEFORE INSERT ON MAPS
FOR EACH ROW
WHEN (new.MAP_ID IS NULL)
BEGIN
SELECT MAPS_SEQ.NEXTVAL
INTO :new.MAP_ID
FROM dual;
END;
/
Here are three flavors:
numeric. Simple increasing numeric value, e.g. 1,2,3,....
GUID. globally univeral identifier, as a RAW datatype.
GUID (string). Same as above, but as a string which might be easier to handle in some languages.
x is the identity column. Substitute FOO with your table name in each of the examples.
-- numerical identity, e.g. 1,2,3...
create table FOO (
x number primary key
);
create sequence FOO_seq;
create or replace trigger FOO_trg
before insert on FOO
for each row
begin
select FOO_seq.nextval into :new.x from dual;
end;
/
-- GUID identity, e.g. 7CFF0C304187716EE040488AA1F9749A
-- use the commented out lines if you prefer RAW over VARCHAR2.
create table FOO (
x varchar(32) primary key -- string version
-- x raw(32) primary key -- raw version
);
create or replace trigger FOO_trg
before insert on FOO
for each row
begin
select cast(sys_guid() as varchar2(32)) into :new.x from dual; -- string version
-- select sys_guid() into :new.x from dual; -- raw version
end;
/
update:
Oracle 12c introduces these two variants that don't depend on triggers:
create table mytable(id number default mysequence.nextval);
create table mytable(id number generated as identity);
The first one uses a sequence in the traditional way; the second manages the value internally.
Oracle Database 12c introduced Identity, an auto-incremental (system-generated) column.
In the previous database versions (until 11g), you usually implement an Identity by creating a Sequence and a Trigger.
From 12c onward, you can create your own Table and define the column that has to be generated as an Identity.
Assuming you mean a column like the SQL Server identity column?
In Oracle, you use a SEQUENCE to achieve the same functionality. I'll see if I can find a good link and post it here.
Update: looks like you found it yourself. Here is the link anyway:
http://www.techonthenet.com/oracle/sequences.php
Trigger and Sequence can be used when you want serialized number that anyone can easily read/remember/understand. But if you don't want to manage ID Column (like emp_id) by this way, and value of this column is not much considerable, you can use SYS_GUID() at Table Creation to get Auto Increment like this.
CREATE TABLE <table_name>
(emp_id RAW(16) DEFAULT SYS_GUID() PRIMARY KEY,
name VARCHAR2(30));
Now your emp_id column will accept "globally unique identifier value".
you can insert value in table by ignoring emp_id column like this.
INSERT INTO <table_name> (name) VALUES ('name value');
So, it will insert unique value to your emp_id Column.
Starting with Oracle 12c there is support for Identity columns in one of two ways:
Sequence + Table - In this solution you still create a sequence as you normally would, then you use the following DDL:
CREATE TABLE MyTable
(ID NUMBER DEFAULT MyTable_Seq.NEXTVAL,
...)
Table Only - In this solution no sequence is explicitly specified. You would use the following DDL:
CREATE TABLE MyTable (ID NUMBER GENERATED AS IDENTITY, ...)
If you use the first way it is backward compatible with the existing way of doing things. The second is a little more straightforward and is more inline with the rest of the RDMS systems out there.
it is called Identity Columns and it is available only from oracle Oracle 12c
CREATE TABLE identity_test_tab
(
id NUMBER GENERATED ALWAYS AS IDENTITY,
description VARCHAR2 (30)
);
example of insert into Identity Columns as below
INSERT INTO identity_test_tab (description) VALUES ('Just DESCRIPTION');
1 row created.
you can NOT do insert like below
INSERT INTO identity_test_tab (id, description) VALUES (NULL, 'ID=NULL and DESCRIPTION');
ERROR at line 1: ORA-32795: cannot insert into a generated always
identity column
INSERT INTO identity_test_tab (id, description) VALUES (999, 'ID=999 and DESCRIPTION');
ERROR at line 1: ORA-32795: cannot insert into a generated always
identity column
useful link
Here is complete solution w.r.t exception/error handling for auto increment, this solution is backward compatible and will work on 11g & 12c, specifically if application is in production.
Please replace 'TABLE_NAME' with your appropriate table name
--checking if table already exisits
BEGIN
EXECUTE IMMEDIATE 'DROP TABLE TABLE_NAME';
EXCEPTION WHEN OTHERS THEN NULL;
END;
/
--creating table
CREATE TABLE TABLE_NAME (
ID NUMBER(10) PRIMARY KEY NOT NULL,
.
.
.
);
--checking if sequence already exists
BEGIN
EXECUTE IMMEDIATE 'DROP SEQUENCE TABLE_NAME_SEQ';
EXCEPTION WHEN OTHERS THEN NULL;
END;
--creating sequence
/
CREATE SEQUENCE TABLE_NAME_SEQ START WITH 1 INCREMENT BY 1 MINVALUE 1 NOMAXVALUE NOCYCLE CACHE 2;
--granting rights as per required user group
/
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLE_NAME TO USER_GROUP;
-- creating trigger
/
CREATE OR REPLACE TRIGGER TABLE_NAME_TS BEFORE INSERT OR UPDATE ON TABLE_NAME FOR EACH ROW
BEGIN
-- auto increment column
SELECT TABLE_NAME_SEQ.NextVal INTO :New.ID FROM dual;
-- You can also put some other required default data as per need of your columns, for example
SELECT SYS_CONTEXT('USERENV', 'SESSIONID') INTO :New.SessionID FROM dual;
SELECT SYS_CONTEXT('USERENV','SERVER_HOST') INTO :New.HostName FROM dual;
SELECT SYS_CONTEXT('USERENV','OS_USER') INTO :New.LoginID FROM dual;
.
.
.
END;
/
Query to create auto increment in oracle. In below query incrmnt column value will be auto incremented wheneever a new row is inserted
CREATE TABLE table1(
id RAW(16) NOT NULL ENABLE,
incrmnt NUMBER(10,0) GENERATED ALWAYS AS IDENTITY
MINVALUE 1 MAXVALUE 999999999999999999999999999 INCREMENT BY 1 START WITH 1 NOORDER NOCYCLE NOT NULL ENABLE,
CONSTRAINT PK_table1 PRIMARY KEY (id) ENABLE);
This is how I did this on an existing table and column (named id):
UPDATE table SET id=ROWNUM;
DECLARE
maxval NUMBER;
BEGIN
SELECT MAX(id) INTO maxval FROM table;
EXECUTE IMMEDIATE 'DROP SEQUENCE table_seq';
EXECUTE IMMEDIATE 'CREATE SEQUENCE table_seq START WITH '|| TO_CHAR(TO_NUMBER(maxval)+1) ||' INCREMENT BY 1 NOMAXVALUE';
END;
CREATE TRIGGER table_trigger
BEFORE INSERT ON table
FOR EACH ROW
BEGIN
:new.id := table_seq.NEXTVAL;
END;
FUNCTION GETUNIQUEID_2 RETURN VARCHAR2
AS
v_curr_id NUMBER;
v_inc NUMBER;
v_next_val NUMBER;
pragma autonomous_transaction;
begin
CREATE SEQUENCE sequnce
START WITH YYMMDD0000000001
INCREMENT BY 1
NOCACHE
select sequence.nextval into v_curr_id from dual;
if(substr(v_curr_id,0,6)= to_char(sysdate,'yymmdd')) then
v_next_val := to_number(to_char(SYSDATE+1, 'yymmdd') || '0000000000');
v_inc := v_next_val - v_curr_id;
execute immediate ' alter sequence sequence increment by ' || v_inc ;
select sequence.nextval into v_curr_id from dual;
execute immediate ' alter sequence sequence increment by 1';
else
dbms_output.put_line('exception : file not found');
end if;
RETURN 'ID'||v_curr_id;
END;
FUNCTION UNIQUE2(
seq IN NUMBER
) RETURN VARCHAR2
AS
i NUMBER := seq;
s VARCHAR2(9);
r NUMBER(2,0);
BEGIN
WHILE i > 0 LOOP
r := MOD( i, 36 );
i := ( i - r ) / 36;
IF ( r < 10 ) THEN
s := TO_CHAR(r) || s;
ELSE
s := CHR( 55 + r ) || s;
END IF;
END LOOP;
RETURN 'ID'||LPAD( s, 14, '0' );
END;
Creating a Sequence:
CREATE SEQUENCE SEQ_CM_LC_FINAL_STATUS
MINVALUE 1 MAXVALUE 999999999999999999999999999
INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE;
Adding a Trigger
CREATE OR REPLACE TRIGGER CM_LC_FINAL_STATUS_TRIGGER
BEFORE INSERT
ON CM_LC_FINAL_STATUS
FOR EACH ROW
BEGIN
:NEW.LC_FINAL_STATUS_NO := SEQ_CM_LC_FINAL_STATUS.NEXTVAL;
END;
The first step is to create a SEQUENCE in your database, which is a data object that multiple users can access to automatically generate incremented values. As discussed in the documentation, a sequence in Oracle prevents duplicate values from being created simultaneously because multiple users are effectively forced to “take turns” before each sequential item is generated. –
Finally, we’ll create our SEQUENCE that will be utilized later to actually generate the unique, auto incremented value. –
While we have our table created and ready to go, our sequence is thus far just sitting there but never being put to use. This is where TRIGGERS come in. Similar to an event in modern programming languages, a TRIGGER in Oracle is a stored procedure that is executed when a particular event occurs. Typically a TRIGGER will be configured to fire when a table is updated or a record is deleted, providing a bit of cleanup when necessary. –
In our case, we want to execute our TRIGGER prior to INSERT into our CM_LC_FINAL_STATUS table, ensuring our SEQUENCE is incremented and that new value is passed onto our primary key column.
create trigger t1_trigger
before insert on AUDITLOGS
for each row
begin
select t1_seq.nextval into :new.id from dual;
end;
only I have to just change the table name (AUDITLOGS) with your table name and new.id with new.column_name
oracle has sequences AND identity columns in 12c
http://www.oracle-base.com/articles/12c/identity-columns-in-oracle-12cr1.php#identity-columns
I found this but not sure what rdb 7 is
http://www.oracle.com/technetwork/products/rdb/0307-identity-columns-128126.pdf
Maybe just try this simple script:
http://www.hlavaj.sk/ai.php
Result is:
CREATE SEQUENCE TABLE_PK_SEQ;
CREATE OR REPLACE TRIGGER TR_SEQ_TABLE BEFORE INSERT ON TABLE FOR EACH ROW
BEGIN
SELECT TABLE_PK_SEQ.NEXTVAL
INTO :new.PK
FROM dual;
END;

Error: numeric or value errors

I know this error issue was been addressed before, but I can't seem to find any relevant solution so I'm posting this question.
create table subscribers(
num_s number(6,0) ,
name varchar2(30) constraint nameM not null,
surname varchar2(20),
town varchar2(30),
age number(3,0) ,
rate number(3,0) ,
reduc number(3,0) ,
CONSTRAINT subscriber_pk primary key (num_s),
constraint age_c check (age between 0 and 120)
);
create or replace type copy_bookT as object(
num number(6),
loancode varchar2 (10),
book_ref ref bookT
);
create table copy_books of copy_bookT(
constraint pk_cb primary key (num),
constraint chk_st check (loancode in('Loan', 'Not')),
loancode default 'Loan' not null
);
create table Lending(
cb_num number(6),
sb_num number(6),
date_L date,
constraint fk_cb foreign key (cb_num) references copy_books(num),
constraint fk_sb foreign key (sb_num) references Subscribers(num_s)
);
create or replace trigger chk_DateL
for insert or update on lending
COMPOUND TRIGGER
--declare
L_Date int;
avail varchar2(10);
subtype copy_booksRec is lending%ROWTYPE;
type copied_bks is table of copy_booksRec;
cbks copied_bks := copied_bks();
before each row is
begin
cbks.extend;
cbks(cbks.last).cb_num := :new.cb_num;
cbks(cbks.last).sb_num := :new.sb_num;
end before each row;
before statement is
begin
for i in cbks.first .. cbks.last loop
select loancode into avail from copy_books where num = cbks(i).cb_num;
select count(date_L) into L_Date from lending where sb_num = cbks(i).sb_num and date_L = cbks(i).date_L;
if (L_Date = 0 and avail = 'Loan') then
update copy_books set loancode = 'Not' where num = cbks(i).cb_num;
cbks.delete;
-- cbks(i).date_L := cbks(i).date_L;
else
dbms_output.put_line('You can only make ONE LOAN at a time! You have already loaned a book on ' || L_Date);
cbks.delete;
end if;
end loop;
-- FORALL i IN cbks.first .. cbks.last
-- insert into lending values cbks(i);
cbks.delete;
end before statement;
end chk_DateL;
/
show errors
It all compiles successfully, but when I try to insert a sample record like:
insert into lending values (2, 700, '10-MAR-14');
it raises a numeric error which comes from the trigger line 18. I don't know what needs fixing despite my efforts.
You should not count on Oracle's default date format to translate your string literal to a date value , you should define the format you're using explicitly:
insert into lending values (2, 700, to_date('10-MAR-14', 'DD-MON-YY'));
While the date format issue is a valid point, that isn't causing your error. It's coming from line 18, which is the for ... loop line:
before statement is
begin
for i in cbks.first .. cbks.last loop
You've got cbks being extended and populated from the before row part of the trigger. When the before statement part fires, cbks is empty, as the row-level trigger hasn't fired yet. It's the first and last references that are throwing the ORA-06502: PL/SQL: numeric or value error error.
You can demonstrate the same thing with a simple anonymous block:
declare
type my_type is table of dual%rowtype;
my_tab my_type := my_type();
begin
for i in my_tab.first .. my_tab.last loop
null;
end loop;
end;
/
ORA-06502: PL/SQL: numeric or value error
ORA-06512: at line 5
SQL Fiddle; you can see you can avoid it by adding an extend, but that doesn't really help you in your version, since you seem to want the row values. (You can eliminate the error in your code with an extend, but it's unlikely to do what you want still).
I'm really not sure what you're trying to achieve here, so I don't really have any advice on what you need to do differently.
as Mureinik already told, Oracle does not know about how to transform your varchar2 into date datatype and you should use date explicitly. But instead of making to_date use date literal - in my opinion it is more clear than using of to_date function
insert into lending values (2,700,date '2014-03-10');
by the way, you can simply change your NLS settings by altering the current session and installing the date format you need