I have an error in sql trigger on update query - sql

The follows sql trigger is not working. I got an error
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 7'
CREATE TRIGGER m_check BEFORE UPDATE ON deposition
FOR EACH ROW
BEGIN
IF((new.balance-old.balance)<0 AND(new.balance-old.balance)>=-2000) THEN
SIGNAL SQLSTATE "40000"
SET MESSAGE_TEXT='Not okay';
ELSE
UPDATE deposition SET balance=new.balance WHERE acc_no = new.acc_no;
END IF;
END
I don't understand where the problem is.Help me solve this error

I'm not sure what line 7 is. However, the update is not appropriate. Instead:
DELIMITER $$
CREATE TRIGGER m_check BEFORE UPDATE ON deposition
FOR EACH ROW
BEGIN
IF((new.balance - old.balance) < 0 AND (new.balance-old.balance) >= -2000) THEN
SIGNAL SQLSTATE "40000" SET MESSAGE_TEXT = 'Not okay';
END IF;
END$$
DELIMITER ;
This is a before update trigger. If no signal is raised and no error occurs, then the update takes place. There is no need to explicitly update.

Related

Issue with trigger for archiving

Trying to make a trigger that puts data into an archive table when a column called COMPLETION_STATUS goes from incomplete to complete, the dbms is a placeholder for the insert but I'm getting the following errors in the if statement
Error(6,1): PLS-00103: Encountered the symbol enter code here"SELECT" when expecting one of the following: begin function pragma procedure subtype type current cursor delete exists prior The symbol "begin" was substituted for "SELECT" to continue.
Error(9,1): PLS-00103: Encountered the symbol "IF" when expecting one of the following: * & - + ; / at for mod remainder rem and or group having intersect minus order start union where connect || multiset The symbol ";" was substituted for "IF" to continue.
Error(13,4): PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: ( begin case declare end exception exit for goto if loop mod null pragma raise return select update while with << continue close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe purge
Code:
create or replace TRIGGER ARCHIVING_TRIG
BEFORE UPDATE OF COMPLETION_STATUS ON PROJECT_DATA
BEGIN
DECLARE COMPLETION_STATUS1 VARCHAR2(9);
SELECT COMPLETION_STATUS into COMPLETION_STATUS1
FROM PROJECT_DATA WHERE COMPLETION_STATUS = 'complete'
IF COMPLETION_STATUS1 = 'complete'
THEN
DBMS.output('123');
END IF;
END;
The DECLARE block should be before the BEGIN block.
The SELECT ... statement needs to be terminated with a semicolon (;).
It's dbms_output.put_line() not dbms.output();
You're trying to assign the result of a query that potentially can return more than one row to a scalar variable.
The rows selected from project_data have no relation to the one(s) that triggered the trigger.
I suggest you use something like:
CREATE TRIGGER archiving_trig
AFTER UPDATE
ON project_data
FOR EACH ROW
WHEN (old.completion_status <> 'complete'
AND new.completion_status = 'complete')
BEGIN
dbms_output.put_line('Trigger fired for ID ' || :new.id);
END;
db<>fiddle
I think maybe AFTER is the better time, because you want to archive the row after the status was successfully changed.
Because of the WHEN the trigger will only fire if completion_status has been changed from something other than 'complete' to 'complete'. But you maybe also need to have a method of removing entries from the archive when the status changes from 'complete' to something else. That isn't covered here.
Declaring it as FOR EACH ROW let's you access the values of the updated row via :new. That way you don't need a query to select that nor a variable to select into.
I guess you need this:
create table PROJECT_DATA_NEW as select * from PROJECT_DATA where 1=2;
CREATE OR REPLACE TRIGGER ARCHIVING_TRIG
AFTER UPDATE
ON PROJECT_DATA
FOR EACH ROW
DECLARE
status number;
BEGIN
status:=0;
select 1 into status from PROJECT_DATA where
:new.COMPLETION_STATUS='complete' and
:old.COMPLETION_STATUS='incomplete'
if (status=1) then
insert into PROJECT_DATA_NEW values(:old.column1,
:old.column2,
:old.column3,
:old.column4,
:old.column5,....etc);
end if;
END;
/

HSQLDB Trigger update for LibreOffice Base

I am trying to create a BEFORE UPDATE trigger to stop the HSQLDB update and throw an exception, if the user enters date left input earlier than date in.
I followed the example given in the link
http://hsqldb.org/doc/guide/triggers-chapt.html
But the error shows:
15: Unexpected end of command: REFERENCING in statement [CREATE TRIGGER checkValidDate BEFORE UPDATE ON "tblVehicles"
REFERENCING]
This is my trigger statement:
CREATE TRIGGER checkValidDate BEFORE UPDATE ON "tblVehicles"
REFERENCING NEW AS newrow
FOR EACH ROW
BEGIN ATOMIC
IF ((newrow.Hidden IS NOT NULL) AND (newrow.Date_Left < newrow.Date_In)) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'INVALID DATE ENTERED';
END IF;
END
How do I modify this statement? So is MESSAGE_TEXT a field in tblVehicles database table or just the syntax for SQLSTATE?
FYI date in and date left do not have underscores in the actual table.
UPDATE 18 March 2018:
I have installed the latest version of HSQLDB as suggested. This is the modified trigger statement:
CREATE TRIGGER "checkValidDateTime" BEFORE UPDATE ON "tblVehicles"
REFERENCING NEW AS newrow OLD AS oldrow
FOR EACH ROW
BEGIN ATOMIC
IF (newrow."Date Left" IS NULL) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'DATE LEFT NOT ENTERED';
ELSEIF (newrow."Time Left" IS NULL) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'TIME LEFT NOT ENTERED';
ELSEIF ((newrow."Hidden" IS NOT NULL) AND (newrow."Date Left" < newrow."Date In")) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'INVALID DATE ENTERED';
ELSEIF ((newrow."Hidden" IS NOT NULL) AND (newrow."Date Left" = newrow."Date In") AND (newrow."Time Left" < newrow."Time In")) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'INVALID TIME ENTERED';
ELSE
UPDATE "tblVehicles" set oldrow."Hidden"='' WHERE oldrow."Id"=newrow."Id";
END IF;
END
I am not sure how to write the UPDATE command for the ELSE section. (Trigger works fine without the ELSE statement). How to pass values from LibreOffice Base front end to this trigger, such as passing the unique Id value?
Error code:
java.sql.SQLSyntaxErrorException: wrong or missing data impact clause in declaration: MODIFIES SQL / Error Code: -5608 / State: 42608
That guide is for version 2.4.
Base comes with 1.8 built-in. If that is what you are using, then follow the documentation for 1.8. It looks like 1.8 does not have the REFERENCING clause.
Note that the embedded setup is not recommended except for testing. So the preferred solution to your problem is to install version 2.4 and then Connect to an existing database when creating a new Base file.
Follow Jim's advice and the instructions in the linked FAQ under How do I setup support for 'split' HSQL databases in Base?.
Then check your column names and if they are mixed-case in the database, use double quotes as you have done with the table name. The names must be exactly the same as in the actual table. Your TRIGGER statement should work OK with the correct names.
The MESSAGE_TEXT is the message that is returned when the exception is thrown.

oracle sql developer missing on keyword

I keep getting the "missing on keyword" message on the following query and I'm not sure why:
CREATE OR REPLACE TRIGGER TRG_LINE_PRODUCT AFTER INSERT UPDATE OR DELETE ON
TBL_CH08_LINE FOR EACH ROW
BEGIN
IF INSERTING THEN UPDATE TBL_CH08_PRODUCT P SET P_QOH = P_QOH-:NEW.LINE.UNITS
WHERE P.P_CODE = :NEW.P.P_CODE;
END IF;
END;
/
You are missing an OR, in fact:
CREATE OR REPLACE TRIGGER TRG_LINE_PRODUCT
AFTER INSERT OR UPDATE OR DELETE ON TBL_CH08_LINE
-----------------^
FOR EACH ROW
Oracle is expecting ON after the INSERT, which is why you get that particular error.

How to create trigger on update with condition based on old and new data?

I want to update field server_prev_level_xp when
NEW.server_xp > OLD.server_prev_level_xp
I use MariaDb and his documentation.
I try this but it doesn't work :
CREATE TRIGGER Level_Update
AFTER UPDATE OF server_xp ON servers
FOR EACH ROW
WHEN (NEW.server_xp > OLD.server_prev_level_xp)
BEGIN
SET NEW.server_prev_level_xp = OLD.server_prev_level_xp + OLD.server_prev_level_xp >> 1;
SET NEW.server_level = OLD.server_level + 1;
END;
Have an error on line 4:
WHEN (NEW.server_xp > OLD.server_prev_level_xp)
What am I doing wrong?
The syntax used to create the trigger doesn't apply to MariaBD ([OF <trigger Column list>] and FOR EACH ROW [WHEN (search condition)]). See CREATE TRIGGER.
One option is to use IF Statement.
Remember: Such a SET statement has no effect in an AFTER trigger because the row change will have already occurred..
DELIMITER //
CREATE TRIGGER `Level_Update` /*AFTER*/ BEFORE UPDATE ON `servers`
FOR EACH ROW
BEGIN
IF NEW.`server_xp` > OLD.`server_prev_level_xp` THEN
.
.
.
END IF;
END//
DELIMITER ;
Use this :
DELIMITER //
CREATE TRIGGER `Level_Update` BEFORE UPDATE ON shp_servers
FOR EACH ROW
BEGIN
IF NEW.`server_xp` > OLD.`server_level_xp` THEN
SET NEW.`server_level_xp` = OLD.`server_level_xp` + OLD.`server_level_xp` >> 1;
END IF;
END//
DELIMITER ;
Have :
1419 - You do not have the SUPER privilege and binary logging is enabled (you might want to use the less safe log_bin_trust_function_creators variable)
And try :
CREATE TRIGGER `Level_Update` BEFORE UPDATE ON shp_servers
FOR EACH ROW
BEGIN
IF NEW.`server_xp` > OLD.`server_level_xp` THEN
SET NEW.`server_level_xp` = OLD.`server_level_xp` + OLD.`server_level_xp` >> 1;
END IF;
END
Have :
1064 - You have an error in your SQL syntax; at line 5

MySQL Syntax Error

When executing:
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
SELECT 1;
END;
DECLARE EXIT HANDLER FOR SQLWARNING
BEGIN
ROLLBACK;
SELECT 1;
END;
-- delete all users in the main profile table that are in the MaineU18 by email address
DELETE FROM ap_form_1 WHERE element_5 IN (SELECT email FROM MaineU18);
-- delete all users from the MaineU18 table
DELETE from MaineU18;
COMMIT;
END;
I get:
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'e1:
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK' at line 2
Any ideas? Thanks.
UPDATE 2:
I have tried putting the script into a PROCEDURE:
DELIMITER |
DROP PROCEDURE IF EXISTS temp_clapro|
CREATE PROCEDURE temp_clapro()
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION, SQLWARNING ROLLBACK;
SET AUTOCOMMIT=0;
-- delete all users in the main profile table that are in the MaineU18 by email address
DELETE FROM ap_form_1 WHERE element_5 IN (SELECT email FROM MaineU18);
-- delete all users from the MaineU18 table
DELETE from MaineU18;
COMMIT;
SET AUTOCOMMIT=1;
END
|
DELIMITER ;
CALL temp_clapro();
I am still having issues:
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (2.40 sec)
Query OK, 0 rows affected (2.40 sec)
Query OK, 0 rows affected (2.40 sec)
Query OK, 0 rows affected (2.40 sec)
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'END;
|
DELIMITER ;
CALL temp_clapro()' at line 1
UPDATE 3:
It seems that many of my problems are coming from the fact that I am running the script from a file using the "SOURCE" command. If I only have the DROP and CREATE commands in the file and run the DELIMITER and CALL commands outside the file, everything works without error.
Is there away to run this from a single script file?
You seem to be using BEGIN as the opening of a block of ad hoc statements, as one would do in SQL Server.
MySQL doesn't support this. You can DECLARE only in the body of a stored procedure or stored function or trigger.
http://dev.mysql.com/doc/refman/en/declare.html:
DECLARE is allowed only inside a BEGIN ... END compound statement and must be
at its start, before any other
statements.
http://dev.mysql.com/doc/refman/en/begin-end.html:
BEGIN ... END syntax is used for
writing compound statements, which can
appear within stored programs.
Re your comments and updated question: I don't know why it's failing. I just tried it myself and it worked fine. What version of MySQL are you using?
you're using semicolons with the procedure for statement delimiters, so you have to change the delimiter in your client. see http://dev.mysql.com/doc/refman/5.1/en/stored-programs-defining.html