I have a varchar2 datatype column in a table. User only can insert number to that column and I don't want to change as number. Sometimes while inserting data this column as manual, user can space in column. I create a trigger to avoid it. Trigger i wrote is as below.
CREATE OR REPLACE trigger_name
BEFORE INSERT ON table
FOR EACH ROW
BEGIN
IF :new.column != TRIM(:new.column) THEN
:new.column := TRIM(:new.column);
ELSE
dbms_output.put_line(:new.column || ' is suitable for jobid');
END IF;
END;
I got error like below while compiling above code.
"ORA-00922: missing or invalid option"
Thanks in advance.
The error ORA-00922 is caused by the missing keyword TRIGGER, as pointed out by Barbaros Özhan. Just add it, assuming you got the table name and column name correct, then it would do fine.
But going further your inquiry, it seems you wanted to replace all the spaces entered by the user for that column. If so, this trigger could do it:
CREATE OR REPLACE TRIGGER trigger_name
BEFORE INSERT ON table_name
FOR EACH ROW
BEGIN
IF :new.column_name != REPLACE(:new.column_name,' ','') THEN
:new.column_name := REPLACE(:new.column_name,' ','');
ELSE
dbms_output.put_line(:new.column_name|| ' is suitable for jobid');
END IF;
END;
I added the missing keyword trigger.
Just replace the table_name and column_name to their correct names and it should work.
Related
I'm trying add a new field in a redshift table. But I want to add only if this field doesn't exists.
I tried wrapping it with IF NOT EXISTS. But I got following error:
Amazon](500310) Invalid operation: syntax error at or near "IF" Position: 5;
BEGIN
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = 'schema_name' and table_name='table_name' and column_name='new_field') THEN
ALTER TABLE schema_name.table_name
ADD new_field INT;
END IF;
COMMIT;
I'm not sure if I'm correctly using "IF NOT EXISTS" statement inside the BEGIN block.
Can someone please help me?
Thanks in advance!
It could be better to handle it using EXCEPTION
BEGIN
ALTER TABLE
<table_name> ADD COLUMN <column_name> <column_type>;
EXCEPTION
WHEN duplicate_column
THEN RAISE NOTICE 'column <column_name> already exists in <table_name>.';
END;
The Answer by Yauheni Khvainitski is not completely wrong. But you do have to use a SP and the only option Redshit has (at this point is to have "EXCEPTION WHEN OTHER"). An example:
CREATE OR REPLACE PROCEDURE change_column_to_big_int_TABLE_NAME_X(column_name varchar(200)) AS
$$
DECLARE
new_column_name VARCHAR;
BEGIN
SELECT INTO new_column_name (table_name)||'_new';
-- RAISE INFO 'new_table_name = % table_name = %',new_column_name, table_name;
ALTER TABLE TABLE_NAME_X ADD COLUMN "(new_column_name)" bigint;
EXCEPTION WHEN OTHERS
THEN RAISE NOTICE 'column already exists on table';
END;
$$
LANGUAGE plpgsql;
CALL change_column_to_big_int_TABLE_NAME_X('COLUMN_Y');
Some links from AWS on:
trapping errors: https://docs.aws.amazon.com/redshift/latest/dg/stored-procedure-trapping-errors.html
CREATE PROCEDURE: https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_PROCEDURE.html
Also please notice that this is valid at this point in time. Redshift seems to be always evolving.
The issue I think is that AWS Redshift does not support the IF statement, but instead uses CASE statements. The CASE statements are very similar to IF the way they implement them. But I admit, I prefer the IF statements.
th request is to assure that in the city we have only one branch,
Banch (idBranch(PK), city) for update and insert
the idea I got is to create a temporary table having all the data of the first one so i can escape the ora errors this is the code I wrote, i'm facing the error PL/SQL: ORA-00903 and I'm not so sure if one trigger can do he job in this case since it should be working for inserting and updating. I need your advice please, thank you.
` CREATE TABLE TEMP_BRANCH AS SELECT NumBranch, CITY FROM BRANCH;
CREATE OR REPLACE TRIGGER checkUniqueBranchPerCity
BEFORE INSERT OR UPDATE ON BRANCH
REFERENCING
NEW AS nextLine
FOR EACH ROW
BEGIN
LOCK TABLE TEMP_BRANCH IN ROW SHARE MODE;
FOR line IN (SELECT * FROM TEMP_BRANCH) LOOP
IF :nextLine.City = line.City THEN
RAISE_APPLICATION_ERROR;
END IF;
END LOOP;
DELETE * FROM TEMP_BRANCH;
END;
/ `
ORA-00903 is "Invalid table name". I suspect it's caused because you put a colon in front of nextLine, i.e. you wrote
IF :nextLine.City = line.City THEN
when it should be
IF nextLine.City = line.City THEN
But I suggest getting rid of the REFERENCING clause and just using :NEW and :OLD in triggers as it reduces confusion. So use
CREATE TABLE TEMP_BRANCH AS SELECT NumBranch, CITY FROM BRANCH;
CREATE OR REPLACE TRIGGER checkUniqueBranchPerCity
BEFORE INSERT OR UPDATE ON BRANCH
FOR EACH ROW
BEGIN
LOCK TABLE TEMP_BRANCH IN ROW SHARE MODE;
FOR line IN (SELECT * FROM TEMP_BRANCH) LOOP
IF :NEW.City = line.City THEN
RAISE_APPLICATION_ERROR;
END IF;
END LOOP;
END;
/
I also suggest you get rid of the DELETE statement in the trigger as it will delete the contents of TEMP_BRANCH the first time the trigger fires.
I am trying to create a trigger to check the month before inserting to the database. the followingg code was triedbut showing a complationng error as Warning: Trigger created with compilation errors.
this is the code
CREATE OR REPLACE TRIGGER tr_july
BEFORE INSERT
ON TBL_EVENT
BEGIN
SELECT EXTRACT(month FROM EVN_DATE) FROM TBL_EVENT;
IF EXTRACT (month from EVN_DATE) == 7 THEN
RAISE_APPLICATION_ERROR(-20110, 'NOT ALLOWED TO INSERT RECORDS DURING JULY');
END IF;
END;
/
I think you are looking for something like this:
CREATE OR REPLACE TRIGGER tr_july
BEFORE INSERT ON TBL_EVENT
BEGIN
IF EXTRACT (month from :new.EVN_DATE) = 7 THEN
RAISE_APPLICATION_ERROR(-20110, 'NOT ALLOWED TO INSERT RECORDS DURING JULY');
END IF;
END; /
Study the documentation, a section "Accessing Column Values in Row Triggers"
https://docs.oracle.com/cd/B19306_01/appdev.102/b14251/adfns_triggers.htm
to learn how to access columns of the current row within the trigger body.
In short: You need to use "correlation names" named NEW and OLD
Tip: run SET DEFINE OFF; before compiling the trigger to avoid bind variable substitution (variables prepended by a colon :).
Use it as:
CREATE OR REPLACE TRIGGER tr_july
BEFORE INSERT
ON TBL_EVENT
Declare
E_date date;
BEGIN
SELECT EVN_DATE into E_date FROM TBL_EVENT;
IF EXTRACT (month from E_date) = 7 THEN
RAISE_APPLICATION_ERROR(-20110, 'NOT ALLOWED TO INSERT RECORDS DURING JULY');
END IF;
END;
Note: Oracle if clause require = only once
There are multiple isues with this code.
First it is a before insert trigger, so the value you want to check is not yet in the table. You can't find it with a select.
Triggers are pl/sql code. Any value you select within a pl/sql procedure you have to 'select aaa INTO bbb from xxx; and bbb must be declared before your BEGIN.
In Oracle the equal comparison operator is a single = (not ==).
Within a trigger you have the special qualifiers :new and :old to reference the column values you are working on.
In update triggers only the :new qualifier is usable.
CREATE OR REPLACE TRIGGER tr_july
BEFORE INSERT
ON TBL_EVENT
BEGIN
IF EXTRACT (month from :new.EVN_DATE) = 7 THEN
RAISE_APPLICATION_ERROR(-20110, 'NOT ALLOWED TO INSERT RECORDS DURING JULY');
END IF;
END;
I'm trying to make a time trigger in the dubbing database. I want to check that character can't be dubbed in the dubbing of the movie in which the character doesn't appear. Here's the PDM:
and CDM
I'm the begginer with SQL but I know that there should be some trigger in the table 'DUBBES'. I tried to make something like this, but i got a message that trigger is invalid:
CREATE OR REPLACE TRIGGER x_character
BEFORE INSERT OR UPDATE ON dubbes FOR EACH ROW
DECLARE
IF ( :NEW.CHAR_id_character NOT IN ( SELECT CHAR_id_CHARACTER
FROM APPEARS
WHERE APPEARS.MOV_id_movie = (SELECT dubbing.Mov_id_movie
FROM DUBBING
WHERE dubbing.id_dubbing = :NEW.dab_id_dubing)))
THEN
RAISE_APPLICATION_ERROR(-20000, 'Character is not in this movie.');
END IF;
END;
/
I would really appreciate any help.
Many thanks in advance!
I think that your code should be like this:
create or replace trigger X_character BEFORE INSERT OR UPDATE ON dubbes
FOR EACH ROW
DECLARE
haveit number;
idmovie number;
begin
select dubbing.Mov_id_movie into idmovie from DUBBING where dubbing.id_dubbing = :new.dab_id_dubing;
select count(*) into haveit from APPEARS
where
APPEARS.MOV_id_movie = idmovie and
APPEARS.CHAR_id_CHARACTER = :new.CHAR_id_character;
IF( haveit = 0 ) then
RAISE_APPLICATION_ERROR(-20000, 'Character is not in this movie.');
END IF;
END;
/
From your diagram, you don't need a trigger for this. If you redefine your FK_DUBBES_DUBBES3_CHARACTE foreign key to refer to APPEARS.CHAR_ID instead of directly against CHARACTER.ID_CHARACTER then the requirement will be enforced for you, without the additional overhead of a trigger.
(As an aside, you might find it easier to have more consistent column names, and simpler key names...)
Begin keyword is missing after DECLARE
I'm currently having an issue with a trigger I'm writing. I want to do a simple trigger in which after an update to table STATEMENT with the status field set to 'Sent', it would create a new row in the table NOTICE with fields such as id, date, user and the last field being a message which takes certain field values to create a "notice".
If it will help, my STATEMENT table contains the following fields:
id
List item
Title
Others not needed to know
So, with the last field of the NOTICE to be inserted, I want to create like a message, perhaps saying "The statement, (id) - (title), issued on (date) has been sent."
I currently have at the moment:
create trigger send_notice
after update on STATEMENT
for each row
when (new.status = 'Sent')
begin
insert into NOTICE values (notice_seq.nextval, SYSDATE, '10001', 'the notice
im having trouble constructing');
end send_notice;
I have tested this trigger in a database and everything seems to work fine. Another thing I was just wondering is if the formatting or if there is anything missing that might help with this trigger? And also, I would I go about creating that notice, which takes field values from STATEMENT?
Any help is appreciated
You can refer to new STATEMENT column values in the trigger using :new., and concatenate them into your text:
create trigger send_notice
after update on STATEMENT
for each row
when (new.status = 'Sent')
begin
insert into NOTICE values (notice_seq.nextval, SYSDATE, '10001',
'The statement, ' || :new.id || ' - ' || :new.title || ', issued on '
|| :new.issue_date || ' has been sent');
end send_notice;
Sometimes concatenating a lot of text and values can get confusing, and you may find it easier to use this "template" approach:
create trigger send_notice
after update on STATEMENT
for each row
when (new.status = 'Sent')
declare
l_text varchar2(500);
begin
l_text := 'The statement, #ID# - #TITLE#, issued on #DATE# has been sent';
l_text := replace (l_text, '#ID#', :new.id);
l_text := replace (l_text, '#TITLE#', :new.title);
l_text := replace (l_text, '#DATE#', :new.issue_date);
insert into NOTICE values (notice_seq.nextval, SYSDATE, '10001', l_text);
end send_notice;