SQL Statement Ignored missing expression in Oracle trigger - oracle

I am writing the below trigger where i am getting the error while to trying to insert the value for this field FIELD_OLD_VALUE,FIELD_NEW_VALUE. I have to insert the value for this fields based on Select query but i am getting the error as SQL Statement Ignored ORA-000936 missing expression in Oracle trigger. I dont want to use variable for field FIELD_OLD_VALUE,FIELD_NEW_VALUE because i have written the insert statement only for ENV_ID field in this question and i have many other fields to add in this trigger. So its difficult to decalre variable and maintain for each and every field.
create or replace TRIGGER RATOR_MONITORING_CONFIGURATION."TRG_TRK_KPI_DEFINITION" AFTER UPDATE ON RATOR_MONITORING_CONFIGURATION.KPI_DEFINITION
FOR EACH ROW
BEGIN
--NEU
IF NOT :old.ENV_ID=:new.ENV_ID THEN
INSERT INTO RATOR_MONITORING_CONFIGURATION.FIELD_TRACKING (FIELD_TRACKING_ID,TABLE_NAME,TABLE_ID, FIELD_NAME,FIELD_OLD_VALUE,FIELD_NEW_VALUE,USER_ID, TIMESTAMP)
VALUES (FIELD_TRACKING_SEQ.NEXTVAL,'KPI_DEFINITION',:new.KPI_DEF_ID,'Environment',to_char(Select NAME FROM ENVIRONMENT WHERE ENV_ID =:old.ENV_ID),to_char(Select NAME FROM ENVIRONMENT WHERE ENV_ID =:new.ENV_ID),:new.LAST_UPDATED_BY,:new.LAST_UPDATED_DATE );
END IF;
END;

If you use subqueries as parameters you need to wrap them in extra parentheses:
to_char((Select NAME FROM ENVIRONMENT WHERE ENV_ID =:old.ENV_ID))

Related

PL/SQL Trigger: Facing bad bind variable error

I have tried everything but nothing can solve this.PLS-00049: bad bind variable 'NEW.BLOODBANKID' keep appearing. Please help me.
CREATE OR REPLACE TRIGGER count_stock
AFTER INSERT OR UPDATE ON blood
FOR EACH ROW
DECLARE
v_countblood NUMBER;
BEGIN
SELECT COUNT(bloodid) INTO v_countblood
FROM blood
WHERE bloodbankid = :NEW.bloodbankid
AND bloodtype = :NEW.bloodtype;
IF v_countblood < 0 THEN
RAISE_APPLICATION_ERROR(-20201,'There is no blood');
END IF;
END;
The error indicates that there is no column "BLOODBANKID" in the table "BLOOD".
Either it doesn't exist at all in the table or you used double quotes on the column in your CREATE TABLE statement, thus making the column case sensitive.
If for instance your CREATE TABLE statement looks like this:
create table blood("bloodbankid" number(18), ...);
Then there is a column "bloodbankid" in the table, but no column "BLOODBANKID".
When we access a row without quotes as in
select BLOODBANKID from blood where BloodBankId = 123;
then Oracle converts this internally into "BLOODBANKID". As the same applies to CREATE TABLE, the column names usually match. If you used quotes in the CREATE TABLE statement, however, then you must use the same upper/lower case with quotes in every statement:
select "bloodbankid" from blood where "bloodbankid" = 123;
So, if this is the case, I'd recommend you re-create the table with case insensitive columns.
(Apart from this your trigger doesn't make sense anyway, as has already been mentioned in the request comments.)

Why do I keep getting this error when creating a trigger?

I am creating a trigger that checks if the Majorcode column is null BEFORE INSERT OR UPDATE and if it is it enters the default value "100"
My code:
CREATE TRIGGER MUmajorcode_changes
BEFORE INSERT OR UPDATE ON M_Students
FOR EACH ROW
BEGIN
IF NEW.Majorcode = null THEN
SET NEW.Majorcode = '100';
END IF;
I get the following message after running it
Warning: Trigger created with compilation errors.
Then when I actually insert a new value with blank major code.
I receive the following message/error:
ERROR at line 1:
ORA-04098: trigger 'SCOTT.MUMAJORCODE_CHANGES' is invalid and failed re-validation.
This is how I setup the table initially:
CREATE TABLE M_Students
(
ID CHAR(3) PRIMARY KEY,
FName VARCHAR2(25),
LName VARCHAR2(25),
Status VARCHAR2(25),
Majorcode CHAR(3) REFERENCES Departments(DeptCode),
GPA NUMBER (4,2),
AdmittedDate DATE
);
Cannot figure out where I am going wrong?
When you get the message "created with compilation errors" it means your script is invalid, it has compile time errors. If your IDE does not show them you to you then if you are using sqlplus then run "show errors" if you are using an IDE run the query "select * from user_errors" (and get a new IDE). Either will show the errors in the script, they must be corrected; your script will not run until they are.
The suggestions of setting a DEFAULT value in the table definition has merit but will fail on a couple conditions. When Inserting the default will be taken when the column name is not mentioned in column list. (Note Omitting the column list is implicitly mentioning all columns so the default would not be set.) Nor would it handle update condition.
Your trigger itself can be reduced to a single statement with the coalesce function:
create or replace trigger mumajorcode_changes
before insert or update of mumajorcode
on m_students
for each row
begin
:new.majorcode := coalesce(:new.majorcode, '100');
end;
You have some syntax errors:
CREATE OR REPLACE TRIGGER MUmajorcode_changes /* better use REPLACE to avoid dropping the trigger */
BEFORE INSERT OR UPDATE
ON M_Students
FOR EACH ROW
BEGIN
IF :new.Majorcode IS NULL /* :new, with the colon (:) */
THEN
:new.Majorcode := '100'; /* :new, and no SET */
END IF;
END; /* a missing END */
Also, never check null values with =, but always use is [not] null.
There are some obvious syntax errors such as wrong assignment, missing or superfluous keywords, but you don't need to create a database trigger to handle this operation. Just modify the related columns property by
ALTER TABLE M_Students
MODIFY Majorcode DEFAULT '100' NOT NULL
Through this property, Majorcode column is already populated by the value '100' during the insertion automatically, and updating that column to NULL won't be possible because of the NOT NULL constraint.
Demo

How to create TRIGGER with a reference to the triggered table?

Can I create an AFTER TRIGGER on a table and using that table in my SELECT query without getting mutating table error?
Example to a query I want to use.
This query will update number of times a certain status name is showing up in alert life cycle:
CREATE OR REPLACE TRIGGER COUNT_STEP
AFTER INSERT
ON STEPS
FOR EACH ROW
DECLARE
V_COUNT_SETP VARCHAR (10000);
BEGIN
SELECT COUNT (STATUS_NAME)
INTO V_COUNT_SETP
FROM (SELECT A.ALERT_ID, S.STATUS_NAME
FROM ALERTS A, ALERT_STATUSES S, STEPS ST
WHERE :NEW.ALERT_INTERNAL_ID = A.ALERT_INTERNAL_ID
AND ST.ALERT_STATUS_INTERNAL_ID = S.STATUS_INTERNAL_ID
AND S.STATUS_NAME IN ('Auto Escalate'))
GROUP BY ALERT_ID;
UPDATE ALERTS A
SET A.COUNT = V_COUNT_ESC
WHERE A.ALERT_INTERNAL_ID = :NEW.ALERT_INTERNAL_ID;
END;
/
The table I'm inserting a record to is also needed for counting the number of step occurrences since it's stores the alert id and all the steps id it had.
You need to be a bit more clearer in your questions. But, from what i understood, you need to create a trigger on a table, and perform a select for that same table. That gives you a mutanting table error. To bypass that, you need to perform a compound trigger on that table. Something like this:
create or replace trigger emp_ct
for insert on employees compound trigger
v_count number; -- Add variable here
before statement is
begin
-- PERFORM YOUR SELECT AND SEND TO A VARIABLE
end before statement;
after each row is
begin
-- DO WANT YOU WANTED TO DO. USE THE VARIABLE
end after each row;
end;
basically, with a compound trigger, you can capture every trigger event. By doing that, allows to query the table you're capturing.

Insert in Merge not working in Oracle

I am new to Oracle. I have a table in Oracle which has 4 columns Period, Open_Flag,Creation_Dt,Updated_By.
The Period column is the Primary key of the table. I have created a proc which will check the value of period from input parameter in the table, if its existing, the value of Open_flag has to be updated else a new record shall be inserted.
create or replace
PROCEDURE PROC_REF_SAP_PERIOD(
V_PERIOD IN NUMBER,V_OPEN_FLAG IN VARCHAR2,V_CREATION_DT IN DATE,V_UPDATED_BY IN VARCHAR2)
AS
BEGIN
MERGE INTO REF_SAP_PERIOD T
USING (SELECT * FROM REF_SAP_PERIOD WHERE PERIOD=V_PERIOD )S
ON (T.PERIOD=S.PERIOD )
WHEN MATCHED THEN UPDATE SET OPEN_FLAG = V_OPEN_FLAG --WHERE PERIOD=V_PERIOD AND CREATION_DT=V_CREATION_DT AND UPDATED_BY=V_UPDATED_BY
WHEN NOT MATCHED THEN INSERT (PERIOD,OPEN_FLAG,CREATION_DT,UPDATED_BY) VALUES (V_PERIOD,V_OPEN_FLAG,V_CREATION_DT,V_UPDATED_BY);
END;
The issue is that the Update is working well in this case, however, the insert is not working. Please help.
You are merging table with itself, filtered by period. Obviously, it will never see your non-existent values in itself.
Try this line instead of your USING line:
using (select V_PERIOD "period" from dual)S

DDL - can't use delimiter?

I'm trying to create some database triggers post database created, by adding them to a sql file that is called from sqldb.map.
However, to create triggers, I need to use the delimiter command to change the delimiter to something besides the semi-colon. This fails, and the result trigger creation fails, both with the standard, you have a syntax error message.. I can run a simple sql statement this way, but it doesn't like delimiter.
Any thoughts?
delimiter //
CREATE TRIGGER `SHOW_ADD_NEWS_ITEM`
AFTER INSERT ON `show`
FOR EACH ROW
BEGIN
declare username varchar(255);
IF NEW.privacy_key IS NOT NULL AND NEW.privacy_key <> 'PRIVATE' and (NOT EXISTS (select id from feed_friend_activity
where location_identifier = NEW.uuid and user_id = NEW.user_id and event_type = 'published show')) THEN
select concat(user.first_name,user.last_name) into username from user where user.id = NEW.user_id;
insert into feed_friend_activity
(location_identifier,user_id,event_type,user_name,item_name,created_on)
values (NEW.uuid,NEW.user_id,'published show',username,NEW.name,NEW.created_on);
END IF;
END
//
Propel 1.6.7 now supports DELIMITER. See this Pull Request for more information. If your SQL is valid, then it will work fine with 1.6.7 or upper.

Resources