Oracle syntax error trigger - oracle

I've been trying for over 2 hours to get the syntax right for this trigger, but it keeps giving me compilation errors, could someone please point me in the direction that I'm going wrong?
[Compilation errors: missing equal sign line 5, sql statement ignored, line 4]
film_actor has the following fields:
actor_id
film_id
film has the following fields:
film_id
rental_rate
CREATE OR REPLACE TRIGGER TRIGGER_ACTOR_STARRED
BEFORE INSERT ON film_actor FOR EACH ROW
BEGIN
IF :new.actor_id IN (SELECT *
FROM V_ACTORS_STARRED) THEN
UPDATE film
SET rental_rate := rental_rate * 1.10
WHERE :new.actor_id = film_actor.actor_id
AND film.film_id = film_actor.film_id;
END IF;
END;
/
The view I'm trying to select from is as follows:
CREATE OR REPLACE VIEW V_ACTORS_STARRED AS
SELECT actor_id
FROM actor
WHERE actor_id IN
(SELECT actor_id
FROM film_actor
WHERE film_actor.actor_id = actor.actor_id
AND film_id IN
(SELECT film.film_id
FROM film, film_category, category
WHERE category.name = 'Documentary'
AND film.film_id = film_category.film_id
AND film_category.category_id = category.category_id
AND rental_rate = (SELECT MAX(rental_rate)
FROM film, category, film_category
WHERE category.name = 'Documentary'
AND film.film_id = film_category.film_id
AND film_category.category_id = category.category_id)));

You're executing an SQL update - it should use the regular = SQL operator, not pl/SQL's := assignment operator:
UPDATE film
SET rental_rate = rental_rate * 1.10 -- Note ":=" was replaced with "="
WHERE :new.actor_id = film_actor.actor_id
AND film.film_id = film_actor.film_id;

Remove the colon in the SET part of UPDATE statement.
UPDATE film
SET rental_rate = rental_rate * 1.10
WHERE :new.actor_id = film_actor.actor_id
AND film.film_id = film_actor.film_id;

Related

I'm trying to update 2 fields in multiple tables in my database using a trigger after inserting a new row

i just created the trigger
here is the code:
CREATE OR REPLACE TRIGGER tr_update_solde_nbreserv
AFTER INSERT ON reservation
FOR EACH ROW
BEGIN
UPDATE CLIENTS
SET CLIENTS.NB_RESERV = NB_RESERV+1 , CLIENTS.SOLDE = SOLDE+1
FROM dbo.clients as c
INNER JOIN dbo.reservation as r
ON c.numc = r.numc
WHERE r.numr = :new.numr;
BEGIN
SELECT fillHist_station FROM DUAL;
END;
end tr_update_solde_nbreserv;
i'm getting these 2 errors:
Error(1,9): PL/SQL: SQL Statement ignored
Error(3,9): PL/SQL: ORA-00933: SQL command not properly ended
how can i fix them
There are several issues with your trigger code.
1) The purpose of this part of the code is unclear :
BEGIN
SELECT fillHist_station FROM DUAL;
END;
fillHist_station is not declared, hence this code would raise an invalid identifier error.
2) The syntax of the UPDATE query is invalid. Also, your intend is to select from the table that the trigger fired on, which is not allowed in Oracle. From looking at your code, it looks like you don't actually need to query RESERVATION to achieve your goal. As a row was just inserted in RESERVATION, you already know the corresponding client number.
3) You miss a / at the end
Here is an updated version of your code, that you can play around with in this db fiddle (you did not provide the structure of your tables so I just created the coulmns that are referenced in the query) :
CREATE OR REPLACE TRIGGER tr_update_solde_nbreserv
AFTER INSERT ON RESERVATION
FOR EACH ROW
BEGIN
UPDATE CLIENTS
SET NB_RESERV = NB_RESERV+1 , SOLDE = SOLDE+1
WHERE numc = :new.numc;
END tr_update_solde_nbreserv;
/
update CLIENTS
SET CLIENTS.NB_RESERV = NB_RESERV+1 , CLIENTS.SOLDE = SOLDE+1
FROM dbo.clients as c
inner join dbo.reservation as r
on c.numc = r.numc
where r.numr = :new.numr;
update with inner join is not supported in Oracle database in this way. furthermore dbo.clients and dbo.reservations look like Sql Server tables rather then oracle.
I believe that you are looking for something like this, but I am not sure about the relations. You may need to fix the query.
UPDATE
(
SELECT clients.nb_reserv, r.nb_reserv as r_nb_reserv, clients.solde, r.solde as r_solde
FROM clients
inner join reservation as r
on c.numc = r.numc
where r.numr = :new.numr
) t
SET CLIENTS.NB_RESERV = r_nb_reserv + 1, clients.solde = r_solde+1;
Simpler approach
UPDATE clients SET NB_RESERV = (SELECT nb_reserv +1
FROM reservations
WHERE c.numc = r.numc and r.numr = :new.numr),
SOLDE = (SELECT SOLDE +1
FROM reservations
WHERE c.numc = r.numc and r.numr = :new.numr)
WHERE EXISTS (SELECT 1 FROM reservations
WHERE c.numc = r.numc and r.numr = :new.numr);

when i run the procedure i get this error [Err] ORA-24344: success with compilation error missing keyword

CREATE OR REPLACE
PROCEDURE "UNASSIGN_CUSTOMER_FEATURES"
(CustomerID_Param IN NUMBER, FeatureID_Param IN NUMBER, WalletID_Param IN NUMBER)
AS
BEGIN
DELETE FROM CUSTOMER_EXTRA_FEATURES WHERE FEATURES_ID = FeatureID_Param
AND CUSTOMER_ID = CustomerID_Param;
MERGE INTO CUSTOMER_SERVICE_CONFIG c
USING
(SELECT BUSINESS_SERVICE_CONFIG.ID from BUSINESS_SERVICE_CONFIG join SERVICE_CONFIG_MAP
ON BUSINESS_SERVICE_CONFIG.Business_SERVICE_TYPE = SERVICE_CONFIG_MAP.Service_type_ID
and BUSINESS_SERVICE_CONFIG.ORGANIZATION_ID = WalletID_Param
and BUSINESS_SERVICE_CONFIG.BUSINESSSERVICECATEGORY = 0
and SERVICE_CONFIG_MAP.FEATURES_ID = FeatureID_Param ) ids
ON (c.SERVICE_CONFIG_ID = ids.ID and c.CUSTOMER_ID = CustomerID_Param )
WHEN MATCHED THEN
DELETE WHERE CUSTOMER_ID = CustomerID_Param AND SERVICE_CONFIG_ID = ids.ID;
END;
You are missing an UPDATE statement prior to doing a DELETE
something like
WHEN MATCHED THEN
UPDATE SET <some field> with <some value>
DELETE WHERE CUSTOMER_ID = CustomerID_Param AND SERVICE_CONFIG_ID =ids.ID;
END;
Refer the following url:
Oracle sql merge to insert and delete but not update
Hope that helps!
The syntax diagram for the merge statement shows that you the delete clause is an optional part of the update, not standalone:
You're getting the "ORA-00905: missing keyword" error because you don't have an update. You could put in a dummy update, but it looks like you really want to delete all rows that match, with no updates to other rows or inserts of new rows; which would be simpler as a plain delete, something like:
DELETE FROM CUSTOMER_SERVICE_CONFIG c
WHERE CUSTOMER_ID = CustomerID_Param
AND SERVICE_CONFIG_ID IN (
SELECT BUSINESS_SERVICE_CONFIG.ID from BUSINESS_SERVICE_CONFIG join SERVICE_CONFIG_MAP
ON BUSINESS_SERVICE_CONFIG.Business_SERVICE_TYPE = SERVICE_CONFIG_MAP.Service_type_ID
and BUSINESS_SERVICE_CONFIG.ORGANIZATION_ID = WalletID_Param
and BUSINESS_SERVICE_CONFIG.BUSINESSSERVICECATEGORY = 0
and SERVICE_CONFIG_MAP.FEATURES_ID = FeatureID_Param );
or
DELETE FROM CUSTOMER_SERVICE_CONFIG c
WHERE CUSTOMER_ID = CustomerID_Param
AND EXISTS (
SELECT null from BUSINESS_SERVICE_CONFIG join SERVICE_CONFIG_MAP
ON BUSINESS_SERVICE_CONFIG.Business_SERVICE_TYPE = SERVICE_CONFIG_MAP.Service_type_ID
and BUSINESS_SERVICE_CONFIG.ORGANIZATION_ID = WalletID_Param
and BUSINESS_SERVICE_CONFIG.BUSINESSSERVICECATEGORY = 0
and SERVICE_CONFIG_MAP.FEATURES_ID = FeatureID_Param
WHERE BUSINESS_SERVICE_CONFIG.ID = c.SERVICE_CONFIG_ID );

Oracle Merge statement error in procedure package body

I'm struggling trying to make this procedure to work, I have the following code inside my package body:
PACKAGE BODY PKG_DM_TRANS_DIMENSIONES AS
PROCEDURE SP_DM_TRANS_DIM_CUENTA AS
vNumRegistrosDimCuentas NUMBER;
BEGIN
SELECT COUNT(*) INTO vNumRegistrosDimCuentas
FROM DIM_CUENTAS;
IF (vNumRegistrosDimCuentas <> 0) THEN
MERGE INTO DIM_CUENTAS DIMC
USING (
SELECT * FROM (
SELECT
DIM.FNT_CUENTA_ID AS DIM_CUENTA_ID,
C.CUE_ID AS FNT_CUENTA_ID,
R.REG_REGION AS REGION,
P.PAI_PAIS AS PAIS,
E.EDI_NOMBRE_EDIFICIO AS EDIFICIO,
C.CUE_CUENTA,
TIC.TIC_TIPO_CONTACTO,
C.CUE_STATUS,
CASE
WHEN DIM.FNT_CUENTA_ID IS NULL THEN 1
WHEN
R.REG_REGION <> DIM.REGION OR
P.PAI_PAIS <> DIM.PAIS OR
E.EDI_NOMBRE_EDIFICIO <> DIM.EDIFICIO OR
C.CUE_CUENTA <> DIM.CUENTA OR
TIC.TIC_TIPO_CONTACTO <> DIM.TIPO_CONTACTO
THEN 2
ELSE 0
END AS TIPO_FILA
FROM STA_EDIFICIOS_EXTRACCION E
LEFT JOIN
STA_PAISES_EXTRACCION P ON E.EDI_PAI_ID = P.PAI_ID
LEFT JOIN
STA_REGIONES_EXTRACCION R ON P.PAI_REG_ID = R.REG_ID
LEFT JOIN
EUB_EDIFICIO_UBICACION EUB ON EUB.EUB_EDI_ID = E.EDI_ID
LEFT JOIN
STA_CUENTAS_EXTRACCION C ON C.CUE_EUB_ID = EUB.EUB_ID
LEFT JOIN
STA_TIPOS_CONTACTO_EXTRACCION TIC ON TIC.TIC_ID = C.CUE_TIC_ID
LEFT JOIN
DIM_CUENTAS DIM ON
(C.CUE_ID = DIM.FNT_CUENTA_ID AND DIM.CUENTA_STATUS = 1)
)
) Q
ON (DIMC.FNT_CUENTA_ID = Q.TIPO_FILA)
WHEN MATCHED THEN
INSERT (DIMC.REGION, DIMC.PAIS, DIMC.EDIFICIO, DIMC.CUENTA, DIMC.TIPO_CONTACTO, DIMC.CUENTA_FECHA_CREACION, DIMC.FNT_CUENTA_ID)
VALUES (Q.REGION, Q.PAIS, Q.EDIFICIO, Q.CUE_CUENTA, Q.TIC_TIPO_CONTACTO, TO_TIMESTAMP(sysdate, 'MM/DD/YYYY HH24:MI:SS'), Q.FNT_CUENTA_ID)
WHEN NOT MATCHED THEN
UPDATE SET DIMC.CUENTA_STATUS = 0 WHERE DIMC.CUENTA_STATUS = 1 -- <- dummy update stmt
ELSE ..... -- else statement code working fine...
END IF;
END SP_DM_TRANS_DIM_CUENTA;
END PKG_DM_TRANS_DIMENSIONES;
I'm getting erros at the line
MERGE INTO DIM_CUENTAS DIMC
Saying "Statement ignored"
and then, another error at:
INSERT (DIMC.REGION, DIMC.PAIS, DIMC.EDIFICIO, DIMC.CUENTA, DIMC.TIPO_CONTACTO, DIMC.CUENTA_FECHA_CREACION, DIMC.FNT_CUENTA_ID)
VALUES (Q.REGION, Q.PAIS, Q.EDIFICIO, Q.CUE_CUENTA, Q.TIC_TIPO_CONTACTO, TO_TIMESTAMP(sysdate, 'MM/DD/YYYY HH24:MI:SS'), Q.FNT_CUENTA_ID)
saying "missing keyword". Is it possible to use the merge statement in a SP? I'm new to Oracle so I really don't know if what I'm trying to do is possible or if there's something wrong with my code.
Thanks for any help, I would really appreaciate it.
I think that you swapped commands - after when matched you should put update statement and after not matched - insert.
Similar example worked for me, but after swapping statements I got ORA-00905 missing keyword. So correct version is:
merge into t1
using (select * from t2) t2 on (t1.id = t2.id)
when matched then update set t1.name = t2.name
when not matched then insert (id, name) values (t2.id, t2.name)

How to use not exists with insert?

I'm trying to frame the below query but it always gives me the error "SQL command not properly ended". How do i use it??
INSERT INTO PROGRAM_KPI (AMSPROGRAMID,MASTER_KPI_ID,LASTUPDATEDBYDATALOAD)
(SELECT 'PRG-026',MASTER_KPI_ID,to_char(sysdate,'dd-mon-yy hh.mi.ss') from kpi_master)
WHERE NOT EXISTS(select * from insight_master
where amsprogramid = V_PROGRAMID
and inamsscope = 1
and tickettype = 'INCIDENT'
and TICKETSUBMITDATE is not null);
Please try this..(Removing the brackets and formating the code)
INSERT INTO program_kpi
(amsprogramid, master_kpi_id, lastupdatedbydataload)
SELECT 'PRG-026', master_kpi_id, TO_CHAR (SYSDATE, 'dd-mon-yy hh.mi.ss')
FROM kpi_master
WHERE NOT EXISTS (
SELECT *
FROM insight_master
WHERE amsprogramid = v_programid AND inamsscope = 1
AND tickettype = 'INCIDENT'
AND ticketsubmitdate IS NOT NULL);
But What is the relation between table program_kpi and insight_master ?
There seems to be no join between the inner and outer subquery.

Trigger on one table field works for all table fields

I have a trigger which is for a few fields in a table. But for some reason, if another field is changed (which is not defined in trigger) then it still fires.
CREATE OR REPLACE TRIGGER INTEGRATION_EMPLOYMENT
AFTER UPDATE OF start_day_of_employment, end_of_employment ON hr_employment_data
FOR EACH ROW
DECLARE
BEGIN
IF UPDATING THEN
MERGE INTO ad_integration intg USING dual ON (intg.user_id = :NEW.user_id AND intg.integrated = 'NO')
WHEN MATCHED THEN
UPDATE SET
intg.start_day_of_employment = decode(:NEW.start_day_of_employment, NULL, ' ', :NEW.start_day_of_employment),
intg.end_of_employment = decode(:NEW.end_of_employment, NULL, ' ', :NEW.end_of_employment),
intg.manager_status = :NEW.manager_status,
intg.pid = (SELECT pid FROM arc.user_info WHERE user_id = :NEW.user_id),
intg.network_access_start_date = (SELECT network_access_start_date FROM hr_extension_data WHERE user_id = :NEW.user_id)
WHEN NOT MATCHED THEN
INSERT (intg.user_id, intg.start_day_of_employment, intg.end_of_employment, intg.manager_status, intg.pid, intg.network_access_start_date
VALUES (:NEW.user_id, :NEW.start_day_of_employment, :NEW.end_of_employment, :NEW.manager_status, (SELECT pid FROM arc.user_info WHERE user_id = :NEW.user_id), (SELECT network_access_start_date FROM hr_extension_data WHERE user_id = :NEW.user_id));
END IF;
END HR_ADINTEGRATION_EMPLOYMENT;
Is it because of using DUAL or something am I missing?
Cheers! :-)
If you want to leave the structure as is and only process the trigger when the specifc fields change, then just do a quick compare (new code lines 7 and 8):
CREATE OR REPLACE TRIGGER INTEGRATION_EMPLOYMENT
AFTER UPDATE OF start_day_of_employment, end_of_employment ON hr_employment_data
FOR EACH ROW
DECLARE
BEGIN
IF UPDATING
AND (:NEW.start_day_of_employment <> :OLD.start_day_of_employment
OR :NEW.end_of_employment <> :OLD.end_of_employment) THEN
MERGE INTO ad_integration intg USING dual ON (intg.user_id = :NEW.user_id AND intg.integrated = 'NO')
WHEN MATCHED THEN
UPDATE SET
intg.start_day_of_employment = decode(:NEW.start_day_of_employment, NULL, ' ', :NEW.start_day_of_employment),
intg.end_of_employment = decode(:NEW.end_of_employment, NULL, ' ', :NEW.end_of_employment),
intg.manager_status = :NEW.manager_status,
intg.pid = (SELECT pid FROM arc.user_info WHERE user_id = :NEW.user_id),
intg.network_access_start_date = (SELECT network_access_start_date FROM hr_extension_data WHERE user_id = :NEW.user_id)
WHEN NOT MATCHED THEN
INSERT (intg.user_id, intg.start_day_of_employment, intg.end_of_employment, intg.manager_status, intg.pid, intg.network_access_start_date
VALUES (:NEW.user_id, :NEW.start_day_of_employment, :NEW.end_of_employment, :NEW.manager_status, (SELECT pid FROM arc.user_info WHERE user_id = :NEW.user_id), (SELECT network_access_start_date FROM hr_extension_data WHERE user_id = :NEW.user_id));
END IF;
END HR_ADINTEGRATION_EMPLOYMENT;

Resources