got error in SQL in my oracle when i call my trigger to update total in my STUDENT table - oracle

I have to call a trigger which updates fields of total and percentage after query is inserted
heres the code
create table bhrugus1 (
student_name varchar2(100),
dbms number,
dsa number,
mco number,
total number,
percentage number,
roll_no number primary key
);
CREATE OR REPLACE TRIGGER trial1
AFTER INSERT on bhrugus1
REFERENCING new AS new
FOR EACH ROW
BEGIN
:new.total := :new.dbms + :new.dsa + :new.mco;
:new.percentage := (:new.dbms + :new.dsa + :new.mco) / 3 ;
END;
insert into bhrugus1 values ('bhrugu',90,90,90,1,1,2);
SELECT * from bhrugus1;
the table and while running trigger i get error
the new error

Please modify your trigger:
CREATE OR REPLACE TRIGGER trial1
before INSERT on bhrugus1
REFERENCING new AS new
FOR EACH ROW
BEGIN
:new.total := :new.dbms + :new.dsa + :new.mco;
:new.percentage := (:new.dbms + :new.dsa + :new.mco) / 3 ;
END;
You shouldn't run an update statement in your trigger, use the :new... instead of update.
The other important thing is:
before insert

You are missing a component, what happens when someone UPDATEs any or all of dbms,dsa,mco. There is no update trigger to recalculate total or percentage. You could of course just include 'OR UPDATE' on the trigger. A better way however would be defining them a virtual columns.
create table bhrugus1 (
student_name varchar2(100),
dbms number,
dsa number,
mco number,
total number generated always as (dbms+dsa+mco) virtual,
percentage number generated always as ((dbms+dsa+mco)/3) virtual,
roll_no number primary key
);
With that both total and percentage (bad name it is the average - but that is another issue) will always calculated properly. And drop the trigger it is no longer needed.

Related

Inserting values into newly created table from a pre-existing table using a cursor and for loop - Snowflake SQL (classic web interface)

I'm trying to insert values into a new table in the classic Snowflake SQL web interface using data from a table that was already created, a cursor, and a for loop. My goal is to insert new information and information from the original table into the new table, but when I try and run my code, there is an error where I am referring to the column of my original table. (See code below)
-- Creation and inserting values into table invoice_original
create temporary table invoice_original (id integer, price number(12,2));
insert into invoice_original (id, price) values
(1, 11.11),
(2, 22.22);
-- Creates final empty table invoice_final
create temporary table invoice_final (
study_number varchar,
price varchar,
price_type varchar);
execute immediate $$
declare
c1 cursor for select price from invoice_original;
begin
for record in c1 do
insert into invoice_final(study_number, price, price_type)
values('1', record.price, 'Dollars');
end for;
end;
$$;
My end goal is to have the resulting table invoice_final with 3 columns - study_number, price, and price_type where the price value comes from the invoice_original table. The error I'm currently getting is:
Uncaught exception of type 'STATEMENT_ERROR' on line 6 at position 8 : SQL compilation error: error line 2 at position 20 invalid identifier 'RECORD.PRICE'.
Does anyone know why the record.price is not capturing the price value from the invoice_original table?
there are a number of type of dynamic SQL that do not handle the cursor name, and thus give this error if you push it into a single name temp value it will work:
for record in c1 do
let temp_price number := record.price;
insert into invoice_final(study_number, price, price_type)
values('1', temp_price, 'Dollars');
end for;
this sql has not been run, and could be the wrong format, but it is the base issue.
Also this really looks like an INSERT would work, but I also assume this is the nature of simplify the question down.
See the following for details on working with variables:
https://docs.snowflake.com/en/developer-guide/snowflake-scripting/variables.html#working-with-variables
The revised code below functions as desired:
-- Creation and inserting values into table invoice_original
create
or replace temporary table invoice_original (id integer, price number(12, 2));
insert into
invoice_original (id, price)
values
(1, 11.11),
(2, 22.22);
-- Creates final empty table invoice_final
create
or replace temporary table invoice_final (
study_number varchar,
price number(12, 2),
price_type varchar
);
execute immediate $$
declare
new_price number(12,2);
c1 cursor for select price from invoice_original;
begin
for record in c1 do
new_price := record.price;
insert into invoice_final(study_number, price, price_type) values('1',:new_price, 'Dollars');
end for;
end;
$$;
Note that I changed the target table definition for price to NUMBER (12,2) instead of VARCHAR, and assigned the record.price to a local variable that was passed to the insert statement as :new_price.
That all said ... I would strongly recommend against this approach for loading tables for performance reasons. You can replace all of this with an INSERT .. AS ... SELECT.
Always opt for set based processing over cursor / loop / row based processing with Snowflake.
https://docs.snowflake.com/en/sql-reference/sql/insert.html

How to increment the value of the unique constraint column value in ORACLE

How to increment the value of the unique constraint column value in ORACLE, in the select statement.
For example, in a table 'BILLING_TABLE' - column BLNG_Sk is the unique key (Autoincremented).
So while inserting a new record into the BILLING_TABLE, for the column BLNG_SK we need to give the value (Which is the increment by 1 from the present max value.)
For example, if BLNG_SK max value is 12321.
new record should be 12322.
how to achieve this in Oracle?
Oracle has a SEQUENCE object which provides the functionality you require.
You create one using the CREATE SEQUENCE SQL statement.
The Oracle documentation provides all the required information and the documentation is available via Oracle's Web site.
Assuming you are on Oracle 12.1 or later, define it as an identity column and do not pass any value when inserting:
create table testtable
( test_id number generated always as identity
constraint testtable_pk primary key
, othercol varchar2(10) );
insert into testtable (othercol) values ('Demo');
select * from testtable;
TEST_ID OTHERCOL
---------- ----------
1 Demo
insert into testtable (othercol) values ('Demo #2');
select * from testtable;
TEST_ID OTHERCOL
---------- ----------
1 Demo
2 Demo #2
Try creating a sequence and a trigger. This is the case when you provide the value manually.
CREATE SEQUENCE dept_seq START WITH 12322;
Trigger definition:
CREATE OR REPLACE TRIGGER dept_bir
BEFORE INSERT ON BILLING_TABLE
FOR EACH ROW
BEGIN
SELECT dept_seq.NEXTVAL
INTO :new.id
FROM dual;
END;
/

Trigger to update a table based on data in other table

Need to create a trigger, when Items.Status is updated to 20 from any of the value which are less than 20, not values greater than 20.
The trigger should update the Status table for the corresponding Item_Id with Status.Status_Desc = "Packed"
So far I have been able to create a trigger like below which compiles fine but isn't giving me the intended result . Please help
create or replace trigger test_trg
after update on items
referencing old as old new as new
for each row
--select item_id into
begin
if (:old.status < 20 and :new.status=20) then
update status
set status_desc='packed'
where Item_Id =1 /*Justfor testing purpose, this need to be matched with item_id in ITEMS table */
end if;
end;
The script for creating the tables
CREATE TABLE "ITEMS" ("ITEM_ID" NUMBER, "ITEM_NAME" VARCHAR2(100), "STATUS" NUMBER)
REM INSERTING into ITEMS
SET DEFINE OFF;
Insert into ITEMS (ITEM_ID,ITEM_NAME,STATUS) values (1,'Test',10);
Insert into ITEMS (ITEM_ID,ITEM_NAME,STATUS) values (2,'Test1',30);
CREATE TABLE "STATUS" ("ITEM_ID" NUMBER, "STATUS_DESC" VARCHAR2(100))
REM INSERTING into STATUS
SET DEFINE OFF;
Insert into STATUS (ITEM_ID,STATUS_DESC) values (1,'testing');
Insert into STATUS (ITEM_ID,STATUS_DESC) values (2,'testing');

adding and subtracting columns in oracle

I have table Inventory
"INVENTORY_CODE" VARCHAR2(20) NOT NULL ENABLE
"ITEM_CODE" VARCHAR2(20) NOT NULL ENABLE
"WAREHOUSE_CODE" VARCHAR2(20)
"CON_TON" NUMBER(38,5)
"IN_Q_TON" NUMBER(38,5)
"OR_Q_TON" NUMBER(38,5)
"RES_TON" NUMBER(38,5)
"RET_TON" NUMBER(38,5)
"ST_INV" NUMBER(38,5)
and another table Inventory_warehouse
"CODE" VARCHAR2(20) NOT NULL ENABLE
"ITEM_CODE" VARCHAR2(20) NOT NULL ENABLE
"QUANTITY_AV_TON" NUMBER(38,5)
"QUANTITY_AV_REAM" NUMBER(38,5)
"QUANTITY_AV_SHEET" NUMBER(38,5)
I want to make a trigger to calculate QUANTITY_AV_TON
as
QUANTITY_AV_TON = IN_Q_TON + RES_TON + RET_TON + ST_INV - CON_TON - OR_Q_TON
I created this trigger but it didn't work
create or replace trigger QUANTITY_TON
AFTER insert or update or delete on INVENTORY
for each row
begin
UPDATE INVENTORY_WAREHOUSE
SET QUANTITY_AV_TON =
select (IN_Q_TON + RES_TON + RET_TON + ST_INV - CON_TON -OR_Q_TON)
from inventory
where INVENTORY.item_code = INVENTORY_WAREHOUSE.item_code;
end;
the values of IN_Q_TON , RES_TON , RET_TON , ST_INV , CON_TON ,OR_Q_TON are calculated from other tables using triggers
If you want to perform the calculation from the context values of the row in the trigger that is being processed. This is normally done by using the ":NEW" variable. I have edited the trigger, but cannot run it, so please try it out. Please read the Oracle Trigger Docs
CREATE OR REPLACE TRIGGER QUANTITY_TON
AFTER INSERT OR UPDATE OR DELETE
ON INVENTORY
FOR EACH ROW
BEGIN
UPDATE INVENTORY_WAREHOUSE
SET QUANTITY_AV_TON = :new.IN_Q_TON
+ :new.RES_TON
+ :new.RET_TON
+ :new.ST_INV
- :new.CON_TON
- :new.OR_Q_TON
WHERE INVENTORY_WAREHOUSE.ITEM_CODE = :new.ITEM_CODE;
END;

Truncate data and if insert new row column increment from 1

I have table with two rows which one ID with auto increment and there are much row last number ID is 89. And then I truncate data/row in the table. And then I insert row again.
But number ID from 90 not from 1 (one). If in mysql if I truncate data in table auto increment start from 1 (one) again. So how in oracle I want to ID autoincrement from one again. Thanx.
Below step when I create table:
// create table;
CREATE TABLE tes (
id NUMBER NULL,
ip_address varchar2(25) NOT NULL
PRIMARY KEY (id)
);
// and create increment;
CREATE SEQUENCE tes_sequence START WITH 1 INCREMENT BY 1;
// and create trigger;
CREATE OR REPLACE TRIGGER tes_trigger
BEFORE INSERT
ON tes
REFERENCING NEW AS NEW
FOR EACH ROW
BEGIN
SELECT tes_sequence.nextval INTO :NEW.ID FROM dual;
END;
Oracle sequence is a separate object and is not connected with table. If you need to start sequence after truncating a table you need to alter the sequence. Have a look here: How do I reset a sequence in Oracle?

Resources