ORACLE -1401 error - oracle

I have a stored procedure in Oracle 9i which inserts records in a table. The table has a primary key built to ensure duplicte rows doesnot exists.
I am trying to insert a record by calling this stored procedure and it works first time properly. I am again trying to insert a duplicate record and expecting unique constraint violation error. But I am getting
ORA-01401 inserted value too large for column
I knew its meaning but my query is , if the value inserted is really large then how it got successful in the first attempt.
Table is
CREATE TABLE KEY
(
ID VARCHAR2(25 BYTE),
KEY NUMBER(4) NOT NULL,
INSERT_DATE DATE,
WORK_KEY VARCHAR2(128 BYTE)
)
CREATE UNIQUE INDEX SACHINIDX ON KEY
(ID, KEY)
Call is
EXEC SQL EXECUTE
BEGIN
keyadd(:id, :key, :wkey);
END;
END-EXEC;
Stored Procedure is
PROCEDURE keyadd(id IN VARCHAR2, key IN NUMBER, wkey IN VARCHAR2)
{
BEGIN
INSERT INTO KEY
( ID,
KEY,
INSERT_DATE,
WORK_KEY)
VALUES
(
id,
key,
SYSDATE,
wkey
);
EXCEPTION
ROLLBACK;
COMMIT;
RETURN;
END;
}
First insert sqlca.sqlcode is [0]
Second insert sqlca.sqlcode is [-1401]

CREATE TABLE KEY
(
ID VARCHAR2(25 BYTE),
KEY NUMBER(4) NOT NULL,
INSERT_DATE DATE,
WORK_KEY VARCHAR2(128 BYTE)
);
CREATE UNIQUE INDEX SACHINIDX ON KEY
(ID, KEY);
create or replace PROCEDURE keyadd(id IN VARCHAR2, key IN NUMBER, wkey IN VARCHAR2)
is
BEGIN
INSERT INTO KEY
( ID,
KEY,
INSERT_DATE,
WORK_KEY)
VALUES
(
id,
key,
SYSDATE,
wkey
);
COMMIT;
-- EXCEPTION when others then
-- ROLLBACK;
end keyadd;
/
begin
keyadd('one', 1, '59FC9AD0FA5A8932836824B0489B73252C120301A2205154C096B4EB213FA983D5E500B62A469439');
keyadd('one', 1, '905BD61AAEC986ACF887DBA7C04D650B61A8818ABEBE1720D810B4A426EB9220558B530D5119315F');
end;
/
gives me the expected ORA-00001: Unique Constraint... error, not an ORA-01401. So, without further information its impossible to help.

I don't know the language the procedure was written in, but this part:
EXCEPTION
ROLLBACK;
COMMIT;
RETURN;
raises my eyebrows. Two questions:
What is this supposed to do?
Is your issue solved when you remove those lines?

My best guess is on your second try, you are providing a value for one of the other columns that is too large. Looks like this error will supersede the primary key violation.

Related

Bad bind variable in procedure in oracle

I'm trying to create a procedure that inserts a new row in a table deposit/uttag, throws an exception if you are not authorized to do this transaction. I'm supposed to create a function that checks if someone is authorized or not, and then use that function in this procedure.
I keep getting this error which I don't get:
Errors: PROCEDURE DO_UTTAG
Line/Col: 18/22 PLS-00049: bad bind variable 'NEW.PNR'
Line/Col: 18/31 PLS-00049: bad bind variable 'NEW.KNR'
Quick translations:
Saldo=balance
konto= account
pnr= personal number
knr= customer number
belopp= amount
These are the main tables:
CREATE TABLE bankkund(
PNR VARCHAR2(11) PRIMARY KEY,
FNAMN VARCHAR2(25) NOT NULL,
ENAMN VARCHAR2(25) NOT NULL ,
PASSWD VARCHAR2(16) NOT NULL,
UNIQUE(PASSWD));
CREATE TABLE kontotyp(
KTNR NUMBER(6)PRIMARY KEY,
KTNAMN VARCHAR2(20)NOT NULL,
RÄNTA NUMBER(5,2) NOT NULL);
CREATE TABLE konto(
KNR NUMBER(8)PRIMARY KEY,
KTNR NUMBER(6)NOT NULL,
REGDATUM DATE NOT NULL,
SALDO NUMBER(10,2),
FOREIGN KEY(ktnr) REFERENCES kontotyp(ktnr));
CREATE TABLE uttag(
RADNR NUMBER(9) PRIMARY KEY,
PNR VARCHAR2(11)NOT NULL,
KNR NUMBER(8)NOT NULL,
BELOPP NUMBER(10,2),
DATUM DATE NOT NULL,
FOREIGN KEY(pnr) REFERENCES bankkund(pnr),
FOREIGN KEY(knr) REFERENCES konto(knr));
This is the procedure:
create or replace procedure do_uttag (
p_radnr kontoägare.radnr%TYPE,
p_pnr bankkund.pnr%TYPE,
p_knr konto.knr%TYPE,
p_belopp uttag.belopp%TYPE)
as
v_saldo konto.saldo%type;
begin
select saldo
into v_saldo
from konto;
insert into uttag(
radnr, pnr, knr, belopp, datum
) values (
p_radnr, p_pnr, p_knr, p_belopp, SYSDATE
);
if get_behörighet(:NEW.PNR,:NEW.KNR) = 0
then
raise_application_error(-20101, 'Du har inte behörigheten!');
else
update konto
set saldo = v_saldo - p_belopp;
dbms_output.put_line('Saldot är nu = ' ||(v_saldo - p_belopp));
end if;
end;
/
This is the function that I created for authorization:
create or replace function get_behörighet (
p_pnr in bankkund.pnr%type,
p_knr in konto.knr%type)
return number
is
v_pnr bankkund.pnr%type;
v_knr konto.knr%type;
begin
select bankkund.pnr, konto.knr
into v_pnr, v_knr
from bankkund, konto
where bankkund.pnr = p_pnr
and konto.knr = p_knr;
return 1;
exception
when others then
return 0;
end;
/
Would really appreciate the help!!
get_behörighet(:NEW.PNR,:NEW.KNR)
this is a form of addressing fields allowed in triggers

encountering "Warning: Trigger created with compilation errors." while creating multiple triggers

I was trying to create multiple triggers in an sql file. And the code is as follows:
CREATE OR REPLACE TRIGGER trigger_selling_price_change
AFTER INSERT OR UPDATE ON SellingPrice
FOR EACH ROW
BEGIN
dbms_output.put_line('price of phone updated');
INSERT INTO LogSellingPriceChange
VALUES(sysdate, phone_id, :old.price, :new.price);
END;
/
CREATE OR REPLACE TRIGGER trigger_purchase_cost_change
AFTER INSERT OR UPDATE ON PurchaseCost
FOR EACH ROW
BEGIN
dbms_output.put_line('purchase cost updated');
INSERT INTO LogPurchaseCostChange
VALUES(sysdate, phone_id, :old.cost, :new.cost);
END;
/
CREATE OR REPLACE TRIGGER trigger_inventory_addition
AFTER INSERT ON Inventory
FOR EACH ROW
BEGIN
dbms_output.put_line('enlisted new phones in database');
INSERT INTO LogInventoryAddition
VALUES(sysdate, phone_id, :old.quantity, :new.quantity);
END;
/
But when I execute it in pl/sql I get Warning: Trigger created with compilation errors. three times.
Upon executing show_errors I get the following output:
Errors for TRIGGER TRIGGER_INVENTORY_ADDITION:
LINE/COL ERROR
-------- -----------------------------------------------------------------
3/2 PL/SQL: SQL Statement ignored
4/18 PL/SQL: ORA-00984: column not allowed here
Declaration of the tables included in the query are as follows:
CREATE TABLE Inventory(
id number,
phone_id number,
quantity number,
PRIMARY KEY (id),
FOREIGN KEY (phone_id) REFERENCES Phone(id)
);
CREATE TABLE PurchaseCost(
id number,
phone_id number,
cost number,
PRIMARY KEY(id),
FOREIGN KEY (phone_id) REFERENCES Phone(id)
);
CREATE TABLE SellingPrice(
id number,
phone_id number,
price number,
PRIMARY KEY(id),
FOREIGN KEY (phone_id) REFERENCES Phone(id)
);
CREATE TABLE LogSellingPriceChange(
change_date date,
phone_id number,
old_price number,
new_price number,
FOREIGN KEY(phone_id) REFERENCES Phone(id)
);
CREATE TABLE LogPurchaseCostChange(
change_date date,
phone_id number,
old_price number,
new_price number,
FOREIGN KEY(phone_id) REFERENCES Phone(id)
);
CREATE TABLE LogInventoryAddition(
addition_date date,
phone_id number,
old_quantity number,
new_quantity number,
FOREIGN KEY(phone_id) REFERENCES Phone(id)
);
I executed the file for creating triggers after successfully creating the tables. However, I did not insert any values.
Column not allowed error because you are trying to access the phone_id column directly without the psudo key :new or :old,
CREATE OR REPLACE TRIGGER trigger_selling_price_change
AFTER INSERT OR UPDATE ON SellingPrice
FOR EACH ROW
BEGIN
dbms_output.put_line('price of phone updated');
INSERT INTO LogSellingPriceChange
VALUES(sysdate, :new.phone_id, :old.price, :new.price);
END;
/
You need to change in other triggers as well.

Oracle trigger on varchar values not working

I have 2 tables 'label' and 'musician'
CREATE TABLE label
(labId varchar(10) NOT NULL PRIMARY KEY,
labName varchar(20) NOT NULL
);
CREATE TABLE musician
(musId varchar(10) NOT NULL PRIMARY KEY,
musName varchar(30) NOT NULL,
labId varchar(10) NOT NULL,
CONSTRAINT MusLabel FOREIGN KEY (labId) REFERENCES label(labId)
);
I created a trigger to limit the number of musicians a label can have within a
range of 1 to 5; so that for example a label x cannot have 6 musicians:
CREATE OR REPLACE TRIGGER before_musician_insert
BEFORE INSERT ON musician
FOR EACH ROW
DECLARE
total integer;
BEGIN
SELECT COUNT(*) INTO total
FROM musician, label
WHERE musician.labId=label.labId;
IF (total < 0 OR total > 5)
THEN
DBMS_OUTPUT.PUT_LINE('Invalid');
END IF;
END;
/
When I insert a 6th musician into the table with the same label ID, the insert statement does not 'trigger' the TRIGGER and the 6th value is added to the table.
I don't know how to fix this.
I tried a check constraint but with varchar values, it is not working either.
I appreciate your help.
Your code has multiple issues. For instance, it is not accessing :new. The trigger is on the wrong table. It has no error generation.
I might suggest something like this:
CREATE OR REPLACE TRIGGER before_labels_insert
BEFORE INSERT ON labels
FOR EACH ROW
DECLARE
v_total integer;
user_xcep EXCEPTION;
PRAGMA EXCEPTION_INIT( user_xcep, -20001 );
BEGIN
SELECT COUNT(*) INTO v_total
FROM labels l
WHERE l.labId = :new.labId;
IF (v_total >= 5) THEN
DBMS_OUTPUT.PUT_LINE('Invalid');
RAISE user_xcep
END IF;
END;
Your trigger fires BEFORE the insert, so the sixth entry doesn't exist when the query is executed.
If you want to error on the insert of the 6th entry, you can make it an AFTER trigger (and fire once per statement, rather than FOR EACH ROW).

Is it possible to insert a record with rowtype X into a table with rowtype Y?

I'm stuck with something really weird.
Yesterday I was able to produce a procedure like this:
create or replace PROCEDURE proc
IS
CURSOR CUR
IS
SELECT * FROM PROVA
WHERE STATUS = 'X';
BEGIN
FOR H IN CUR
LOOP
BEGIN
INSERT INTO PROVA2 VALUES H;
DELETE FROM PROVA WHERE ID = H.ID;
COMMIT;
END;
END LOOP;
END;
Where PROVA is defined as:
CREATE TABLE PROVA
( "ELEMENTO" VARCHAR2(20 BYTE),
"DATO" VARCHAR2(20 BYTE),
"NUMERO_TENTATIVI" NUMBER(8,0),
"STATUS" VARCHAR2(1000 BYTE),
"ID" NUMBER(*,0)
)
and PROVA2 is defined as:
CREATE TABLE PROVA
( "ELEMENTO" VARCHAR2(20 BYTE),
"DATO" VARCHAR2(20 BYTE),
"NUMERO_TENTATIVI" NUMBER(8,0),
"STATUS" VARCHAR2(1000 BYTE),
"ID" NUMBER(*,0)
"DATE_TIME" TIMESTAMP (6) DEFAULT CURRENT_TIMESTAMP
)
Unfortunately, my mistake, I didn't save and commit the correct procedure so now I'm stuck with the old one (where, when I do the insert, I have to specify every column...
INSERT INTO PROVA2(bla,bla,bla...)
VALUES (bla,bla,bla...);
I'd like the INSERT part to abstract from the table structure and I searched everywhere but I didn't find any evidence on the error that the first PROCEDURE I posted gives me, which is:
ORA-00947: not enough values
So my question is: is it possible to insert a complete record from a table X into a table Y, which has the same columns except DATE_TIME that has a default value (and I don't want to modify...).
I hope that this isn't messy and I searched everywhere on the internet about this with no luck.
Thanks.
EDIT:
To summarize:
given a table A that has foo,bar,foobar as columns, where foobar has a default value: can I insert a record 'x' from a table B that has foo,bar as columns by using:
insert into A values x
Thanks
You can use a view to do that:
create table tmp(
id number
);
create table tmp1(
id number,
dt date default sysdate
);
create view tmp1_vw as select id from tmp1;
insert into tmp1_vw values (1);
result:
table TMP created.
table TMP1 created.
view TMP1_VW created.
1 rows inserted.
Your procedure works as well:
declare
CURSOR CUR
IS
SELECT * FROM tmp;
BEGIN
FOR H IN CUR
LOOP
BEGIN
INSERT INTO tmp1_vw VALUES H;
END;
END LOOP;
END;
And don't do commit after every statement.
Follow up after 1st comment.
You have 2 tables with slightly different structure.
To solve the problem, you make a view on a second table to look exactly like first one. Then your "record types", that are derived from first table, will work on a view as well.

PL/SQL Error on trigger for auto_increment

I'm trying to auto_increment the cust_id field in the following table:
CREATE TABLE A113222813_CUSTOMERS (
CUST_ID NUMBER(10) PRIMARY KEY,
CUST_FNAME VARCHAR2(20),
CUST_SNAME VARCHAR2(20),
CUST_UNAME VARCHAR2(30) NOT NULL,
CUST_PASS VARCHAR2(40) NOT NULL
)
I create the following sequence and trigger to handle this:
CREATE SEQUENCE CUST_SEQ START WITH 1 INCREMENT BY 1 NOCYCLE;
CREATE OR REPLACE TRIGGER CUST_TRG
BEFORE INSERT ON A113222813_CUSTOMERS
FOR EACH ROW
BEGIN
:NEW.CUST_ID := CUST_SEQ.NEXTVAL;
END;
But it keeps throwing the following error:
Error(2,30): PLS-00357: Table,View Or Sequence reference 'CUST_SEQ.NEXTVAL' not allowed
in this context
Any idea what I am doing wrong?
This is not possible before 11g. You can use sequence_name.NEXTVAL in regular assignments from 11g not before that, and that by the following:
select CUST_SEQ.NEXTVAL into :NEW.CUST_ID from dual;

Resources