Oracle Script problem - create trigger not terminating - sql

I am trying to make some changes to an oracle database and have a script put together to do so. The problem is when it gets to a point in the script where I am creating a trigger it seems like the Create Trigger block does not properly terminate, when I look at the trigger afterwards it contains all of the remaining code in the script.
This is what I have:
CREATE OR REPLACE TRIGGER user_publish_log_trg
BEFORE INSERT ON USER_PUBLISH_LOG
FOR EACH ROW
BEGIN
SELECT user_publish_log_seq.NEXTVAL INTO :NEW.Id FROM dual;
END user_publish_log_trg;
CREATE TABLE USER_APPROVAL_LOG
(
Id number(10) NOT NULL ,
CommodityId number(10) NOT NULL,
QuarterEndDate DATE NOT NULL,
ActionId int NOT NULL ,
...
What am I doing wrong in ending the trigger?

You need to terminate the PL/SQL by using a slash on a new line, like this:
CREATE OR REPLACE TRIGGER user_publish_log_trg
BEFORE INSERT ON USER_PUBLISH_LOG
FOR EACH ROW
BEGIN
SELECT user_publish_log_seq.NEXTVAL INTO :NEW.Id FROM dual;
END user_publish_log_trg;
/
CREATE TABLE USER_APPROVAL_LOG
(
Id number(10) NOT NULL ,
CommodityId number(10) NOT NULL,
QuarterEndDate DATE NOT NULL,
ActionId int NOT NULL ,
...

Related

How to create date trigger?

How can I create a trigger to increase a date data from my table with each next row? I had an attempt, is below the table
What I want to do is to increase date from training_date_end by 1 week. But I don't know how to do it, just studying. Can anyone help?
CREATE TABLE training
(
coach_id int NOT NULL,
customer_id int NOT NULL,
training_date_start date NULL,
training_date_end date NULL,
training_place_id int NOT NULL,
CONSTRAINT training_pk PRIMARY KEY (training_place_id)
);
create or replace trigger lucky_week
before insert or update on training
for each row
begin
update training
set training_date_end = :new.training_date_end + 7
where training_date_end = :new.training_date_end;
end;
Most probably like this:
create or replace trigger lucky_week
before insert or update on training
for each row
begin
:new.training_date_end := :new.training_date_end + 7;
end;
Because, your trigger will suffer from the mutating table error (if you insert more than a single row), and - won't do anything in that case (because row you'd like to update doesn't exist yet).

Create Table / Sequence / Trigger in Apex Oracle SQL - ORA-00922 / ORA-00907 / ORA-00922

Using: Application Express 18.1.0.00.45
Please note: I am very new to Oracle Apex and SQL.
For a project I have to create an Application straight in Apex.
I was trying to create a table that works with a Primary Key that auto-increments itself.
Yesterday I created my first Application with a page for user input in a table, a page with table display and filter option and was playing around with forms, dashboard and authentication methods.
I removed the app after playing to start the "Real Work", but I my enthusiasm went quickly away when I realized that I am doing something very wrong but am not sure what.. :)
After lots of googling / reading etc, I am still not sure what is wrong..
See below the code:
-- Create Sequence
CREATE SEQUENCE seq_odm_for_pk
START WITH 1
INCREMENT BY 1
CACHE 100;
-- Create Table for User Input
CREATE TABLE ODM_Progress_v1 (
-- General Details:
ID int NOT NULL AUTO_INCREMENT,
TRAINEE varchar(50) NOT NULL, --1
COACH varchar(50) NOT NULL, --2
STATUS varchar(50) NOT NULL, --3
REGION varchar(5) NOT NULL, --4
-- Actions:
ACTION_TAKEN varchar(100) NOT NULL, --5
ACTION_DETAILS varchar(250), --6
ACTIONED_BY varchar(50) NOT NULL, --7
ACTIONED_DATE DATE NOT NULL, --8
-- Constraints that perform checks for each column:
CONSTRAINT CHK_GeneralDetails CHECK (TRAINEE!=COACH AND (STATUS IN('New', 'In Progress', 'Completed')) AND (REGION IN('EMEA', 'APAC', 'AMER'))),
-- Set Primary Key (Trainee+Coach):
CONSTRAINT PK_ODMProgress PRIMARY KEY (TRAINEE,REGION,ID)
);
-- Create Trigger
CREATE trigger_for_pk_odm_progress
BEFORE INSERT ON ODM_Progress_v1
FOR EACH ROW
WHEN (new.ID is null)
BEGIN
select seq_odm_for_pk.nextval into :new.ID from DUAL;
-- :new.PK_ODMProgress := seq_odm_for_pk.nextval;
END;
The script finishes running with 3 errors, see below:
CREATE OR REPLACE SEQUENCE seq_odm_for_pk START WITH 1
INCREMENT BY 1 CACHE 100
ORA-00922: missing or invalid option
CREATE TABLE ODM_Progress_v1 ( -- General Details: ID int NOT
NULL AUTO_INCREMENT, TRAINEE varchar(50) NOT NULL, --1 COACH
varchar(50) NOT NULL, --2 STATUS varchar(50) NOT NULL, --3
REGION varchar(5) NOT NULL, --4 -- Actions: ACTION_TAKEN
varchar(100) NOT NULL, --5 ACTION_DETAILS varchar(250), --6
ACTIONED_BY varchar(50) NOT NULL, --7 ACTIONED_DATE DATE NOT NULL,
--8 -- Constraints that perform checks for each column: CONSTRAINT CHK_GeneralDetails CHECK (TRAINEE!=COACH AND (STATUS
IN('New', 'In Progress', 'Completed')) AND (REGION IN('EMEA', 'APAC',
'AMER'))), -- Set Primary Key (Trainee+Coach): CONSTRAINT
PK_ODMProgress PRIMARY KEY (TRAINEE,REGION,ID) )
ORA-00907: missing right parenthesis
CREATE OR REPLACE trigger_for_pk_odm_progress BEFORE INSERT ON
ODM_Progress_v1 FOR EACH ROW WHEN (new.ID is null) BEGIN SELECT
seq_odm_for_pk.nextval INTO :new.ID FROM DUAL; --
:new.PK_ODMProgress := seq_odm_for_pk.nextval; END;
ORA-00922: missing or invalid option
Can you please help me unravel this (to me, complete) mystery?
The final application should at least contain 1 table with primary key and sequence (created from scratch, see above) and have at least 2 pages, one is for data input, the other is for data display with use tabs or navigation menu.
Thank you in advance!
That code looks OK, more or less. Here you go:
SQL> CREATE SEQUENCE seq_odm_for_pk
2 START WITH 1
3 INCREMENT BY 1
4 CACHE 100;
Sequence created.
Table: I'm on 11g which doesn't support auto-incremented columns, so I removed that clause:
SQL> CREATE TABLE ODM_Progress_v1 (
2 -- General Details:
3 ID int NOT NULL AUTO_INCREMENT,
4 TRAINEE varchar(50) NOT NULL, --1
5 COACH varchar(50) NOT NULL, --2
6 STATUS varchar(50) NOT NULL, --3
7 REGION varchar(5) NOT NULL, --4
8 -- Actions:
9 ACTION_TAKEN varchar(100) NOT NULL, --5
10 ACTION_DETAILS varchar(250), --6
11 ACTIONED_BY varchar(50) NOT NULL, --7
12 ACTIONED_DATE DATE NOT NULL, --8
13 -- Constraints that perform checks for each column:
14 CONSTRAINT CHK_GeneralDetails CHECK (TRAINEE!=COACH AND (STATUS IN('New', 'In Progress', 'Completed')) AND (REG
ION IN('EMEA', 'APAC', 'AMER'))),
15 -- Set Primary Key (Trainee+Coach):
16 CONSTRAINT PK_ODMProgress PRIMARY KEY (TRAINEE,REGION,ID)
17 );
ID int NOT NULL AUTO_INCREMENT,
*
ERROR at line 3:
ORA-00907: missing right parenthesis
SQL> l3
3* ID int NOT NULL AUTO_INCREMENT,
SQL> c/auto_increment//
3* ID int NOT NULL ,
SQL> /
Table created.
Trigger contains an error in line #1: it is not "trigger_for" but "trigger for" (no underscore):
SQL> CREATE trigger_for_pk_odm_progress
2 BEFORE INSERT ON ODM_Progress_v1
3 FOR EACH ROW
4 WHEN (new.ID is null)
5 BEGIN
6 select seq_odm_for_pk.nextval into :new.ID from DUAL;
7 -- :new.PK_ODMProgress := seq_odm_for_pk.nextval;
8 END;
9 /
CREATE trigger_for_pk_odm_progress
*
ERROR at line 1:
ORA-00901: invalid CREATE command
SQL> l1
1* CREATE trigger_for_pk_odm_progress
SQL> c/er_/er /
1* CREATE trigger for_pk_odm_progress
SQL> l
1 CREATE trigger for_pk_odm_progress
2 BEFORE INSERT ON ODM_Progress_v1
3 FOR EACH ROW
4 WHEN (new.ID is null)
5 BEGIN
6 select seq_odm_for_pk.nextval into :new.ID from DUAL;
7 -- :new.PK_ODMProgress := seq_odm_for_pk.nextval;
8* END;
SQL> /
Trigger created.
SQL>
So:
sequence is OK, but - for vast majority of cases - a simple create sequence seq_odm_for_pk; is enough
for CREATE TABLE remove AUTO_INCREMENT (if you aren't on 12c)
trigger: remove underscore
Now, depending on where you executed those commands, you might have got errors. If you ran them in Apex SQL Workshop, run them one-by-one (and keep only one command in the window). Doing so, it should be OK.
Also, I've noticed that you used VARCHAR datatype - switch to VARCHAR2.
Finally, there's no use in constraining primary key columns with the NOT NULL clause - primary key will enforce it by default.
As of Apex itself: the way you described it, you should create an Interactive Report; the Wizard will create a report (to view data), along with a form (to insert/modify/delete data).
The query you ran in your script is not the same as you posted in your code, as can be read in error text.
Code for creating your sequence as you wrote it in your code should be fine:
CREATE SEQUENCE seq_odm_for_pk
START WITH 1
INCREMENT BY 1
CACHE 100;
As of 11g you cannot use AUTO_INCREMENT in Oracle when creating table. It is not even necessary since you're having a trigger populating your :new.ID with nextval from sequence. So, in your CREATE TABLE remove AUTO_INCREMENT for your ID and everything should be fine.
While creating a trigger you omitted TRIGGER keyword (CREATE OR REPLACE TRIGGER trigger_for_pk_odm_progress).
Also, I'm not sure if you did or did not put END; at the end of your create trigger command. if not, put it.
I hope that helped :)

Trigger for generating IDs

I would like to create trigger for generating ID in table:
CREATE TABLE client (
clientID INT PRIMARY KEY NOT NULL,
name VARCHAR(16) NOT NULL,
surname VARCHAR(16) NOT NULL,
personalID VARCHAR(10) NOT NULL,
CONSTRAINT verifyPersonalID CHECK ((personalID BETWEEN 1000000000 and 9999999999) and (MOD(personalID, 11) = 0))
);
I tried to write it like this but it keeps returning errors and I dont know why. Can you, please, give me an advice what Im doing wrong?
CREATE OR REPLACE TRIGGER clientID
AFTER INSERT
ON client
FOR EACH ROW
BEGIN
UPDATE client
SET client.clientID = klientSeq.nextval
WHERE :new.personalID = client.personalID;
END;
/
You want a before insert trigger:
CREATE OR REPLACE TRIGGER klientID
BEFORE INSERT
ON klient
FOR EACH ROW
BEGIN
SELECT klientSeq.nextval INTO :new.cisloKlienta FROM dual;
END;
Maybe instead of creating a trigger, you could make the default value of the primary key the next value of the sequence.

How to use trigger in Postgres after Update?

Hi guys i need your help :D
I'm using the latest version of PostgreSQL
First of all, here is my database's tables:
CREATE TABLE colore (
idcolore INTEGER PRIMARY KEY,
nome VARCHAR(100),
note TEXT
);
CREATE TABLE Prodotto (
SKU varchar(50) PRIMARY KEY,
nome varchar(255) NOT NULL,
quantita INTEGER DEFAULT -1,
idColore INTEGER,
prezzo NUMERIC(10, 2),
FOREIGN KEY(idColore) REFERENCES Colore(idColore) ON UPDATE NO ACTION ON DELETE NO ACTION
);
CREATE TABLE Ordine (
idOrdine INTEGER PRIMARY KEY,
SKU varchar(50) NOT NULL,
quantita INTEGER NOT NULL,
CHECK (check_quantita(SKU, quantita)),
FOREIGN KEY(SKU) REFERENCES Prodotto(SKU) ON UPDATE NO ACTION ON DELETE NO ACTION
);
What I want is that when I insert a new Ordine, the quantita of the Prodotto references by SKU is the quantity available minus the quantity ordered.
For Example:
I have this Prodotto:
SKU : AAA
Nome: Prodotto1
Quantita: 11
And then I do the following:
INSERT INTO Ordine (idOrdine, SKU, quantita) VALUES (1, 'AAA', 10);
What I want is that after the last insert the quantity of the product AAA would be 1.
I've tried using this piece of code
CREATE OR REPLACE FUNCTION aggiorna_quantita() RETURNS trigger AS
$$
BEGIN
UPDATE Prodotto
SET quantita = (SELECT Quantita FROM Prodotto WHERE SKU = TG_ARGV[0]) - TV_ARGV[$1]
WHERE SKU = TV_ARGV[$0] ;
END
$$
LANGUAGE plpgsql;
CREATE TRIGGER trigger_aggiorna_quantita
AFTER INSERT ON Ordine
FOR EACH STATEMENT
EXECUTE PROCEDURE aggiorna_quantita(SKU, quantita);
But nothing happens :(
Thank you in advance and forgive me for my bad English :D
The arguments to a trigger can only be string literals. Simple names and numeric values are converted to strings at compile time. What you want cannot be done using these arguments. Luckily there is a much simpler method. Inside the trigger a variable called NEW is available which is the row that just got inserted.
Also you do not have to use a select to retrieve the current value of quantita.
Oh and don't use uppercase characters for object names in postgresql. It's handling of uppercase is very confusing because it converts them to lowercase unless you put the names between double quotes.
And you also want your trigger to be row level instead of statement level.
So your code would become:
CREATE OR REPLACE FUNCTION aggiorna_quantita() RETURNS trigger AS
$$
BEGIN
UPDATE prodotto
SET quantita = prodotto.quantita - NEW.quantita
WHERE sku = NEW.sku;
RETURN NEW;
END
$$
LANGUAGE plpgsql;
CREATE TRIGGER trigger_aggiorna_quantita
AFTER INSERT ON ordine
FOR EACH ROW
EXECUTE PROCEDURE aggiorna

SQLPLUS dont create row

I have unusual problem with SQLPLUS connected with OracleDB 10g. I have table with sequence and trigger to autoincrement id. I created script for inserting some data into that table. When I called it form SQLPLUS everything goes ok (without error), but that rows are not visible in object browser. When I call the same command from SQL command it show in table without any problems.
Any ideas?
Creating tables script:
-- Create table with drivers
CREATE TABLE drivers (
id NUMBER NOT NULL,
name VARCHAR2(30) NOT NULL,
forname VARCHAR2(30) NOT NULL,
plate_nr VARCHAR2(7) NOT NULL,
engine NUMBER(2,1) DEFAULT 1.4 NULL CHECK(engine > 0), -- check allow only values that meets statement
passanger_space NUMBER DEFAULT 3 NULL CHECK(passanger_space > 0),
luggage_space NUMBER DEFAULT 150 NULL CHECK(luggage_space > 0),
PRIMARY KEY (id) -- id is unique inside table and most important
);
CREATE SEQUENCE drivers_seq; -- create sequence for table
CREATE OR replace TRIGGER drivers_trg -- create trigger
BEFORE INSERT ON drivers -- if user want to add row into table
FOR EACH ROW
BEGIN
SELECT drivers_seq.nextval INTO :NEW.id FROM dual; -- get next value (autoincrement)
END;
/
Insert data script:
INSERT INTO drivers (name,forname,plate_nr,engine,passanger_space,luggage_space)
SELECT 'Paweł','Jakubowski','ABC1234',1.4,3,150 FROM dual
UNION ALL SELECT 'Piotr','Dobrzański','ABC4321',1.8,2,NULL FROM dual
UNION ALL SELECT 'Kamil','Nowak','77G0D77',2.2,15,500 FROM dual
UNION ALL SELECT 'Agnieszka','Kowalska','B3AU7Y6',1.4,3,175 FROM dual
;