HSQLDB Trigger update for LibreOffice Base - hsqldb

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.

Related

How to rewrite a trigger causing an update deadlock error

I have the following trigger. It is executed after an update statement from a REST API request. My issue is that when it is sent two API calls concurrently, the trigger is executed twice, therefore a deadlock error comes up because the transaction is not finished. Is there any SQL trickery I can try? Can I check in table B if it already has B_NEEDSRECALCULATION set to '+' and bypass the update, or maybe create a trigger on tableb?
CREATE OR ALTER TRIGGER TR_TESTTRIGGER_AU FOR TABLEA
ACTIVE AFTER UPDATE POSITION 0
AS
begin
if (rdb$get_context('USER_TRANSACTION', 'WISASCRIPT') = '1') then exit;
if ((new.A_FiledB IS NULL) and
(old.A_FieldA <> new.A_FieldB) )THEN
begin
UPDATE TableB
SET B_NEEDSRECALCULATION = '+'
WHERE (B_TESTID = new.A_TESTIDFK);
end
end

I have an error in sql trigger on update query

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.

ORA-04091 Error on "after update" trigger, how to get around?

I have a trigger set to fire after an update of a specific column. I want to update the value of a specific column after a specific value from another column changes to another specific value.
I'm getting the errors:
ORA-04091: table tableName is mutating, trigger/function may not see it
ORA-06512: at "triggerName", line 14
ORA-04088: error during execution of trigger 'triggerName'
I've rewritten this as a before update and after update, as well as tried storing the logic in a function, and using "pragma autonomous_transaction", but the error still gets thrown.
BEFORE update of columnName1 ON tableName
FOR EACH ROW
BEGIN
if :new.columnName1 = 3 AND :old.columnName1 = 1 then
update tablename
set columnName2= MOD(sequenceName.NextVal, 5) + 1
where tableName.columnName2 = :old.columnName2;
end if;
END;
/
I don't understand why the entire table is labelled as "mutating" when I am not updating the column affected by the update the trigger is responding to. Surely, you should be able to update the value of a column in a table if another value in the table changes, or am I crazy here?
Note: Only one entry would be affected at a time. In my application logic, I update the status of some person in the database. I want the database to do some logic only on a specific status change, and I want to avoid using API calls for the logic here, as you can see, it is simply one line of logic in PLSQL.
Thanks
Perhaps you don't really want to update the table but just change a value in the specific row being updated.
If so, eschew the update and just set the value:
BEFORE update of columnName1 ON tableName
FOR EACH ROW
BEGIN
if :new.columnName1 = 3 AND :old.columnName1 = 1 then
:new.columnName2 := MOD(sequenceName.NextVal, 5) + 1 ;
end if;
END;

Error 1064 when i creating my Procedure Statement in mySQL workbench

This is my code for the Procedure statement that i think is working correctly but i can not run it because i keep getting this error: Error Code: 1064. 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 '); -- issue the new loan. INSERT INTO loan (code, no, taken, due) VA' at line 70
I try to find ways to fix it but i didn't find anything. Can anyone else see if i wrote something wrong or i have made any mistakes in my code somewhere that i can not see? The error is sending me to the line 70 but also the FETCH NEXT FROM copy_c INTO copy_code; is telling me that the FROM is not at the correct position. Also i include my comments for more easier way of reading this code.
DELIMITER $$
CREATE PROCEDURE `new_loan` (IN book_isbn CHAR(17), IN student_no INT)
BEGIN
-- search for the copy of the book and test for loan record in loan table.
DECLARE copy_code, loan_test INT;
-- test for successful loan and for end of cursor.
DECLARE inserted, complete BOOLEAN;
-- the duration date and current date for new loan issue and number of days for the new loan.
DECLARE due, cur DATE;
DECLARE copy_dur TINYINT;
-- test if students can loan books.
DECLARE embargo_status BIT(1) DEFAULT b'1';
-- cursor for copy codes based on isbn.
DECLARE copy_c CURSOR FOR
SELECT `code`
FROM copy
WHERE isbn = book_isbn;
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET complete = TRUE;
OPEN copy_c;
-- get student embargo status.
SET embargo_status = (SELECT embargo
FROM student
WHERE `no` = student_no);
SELECT embargo_status;
-- check if the student is valid or embargo is no, if not report a message.
IF (embargo_status IS NULL OR embargo_status = b'1') THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'The student is not valid or has embargo!';
END IF;
SET inserted = FALSE;
SET copy_code = 0;
-- loop through copies to see when that is available.
copy_codes: LOOP
FETCH NEXT FROM copy_c INTO copy_code;
IF complete THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'We looped to end and found nothing!';
END IF;
-- if a copy is available then loan_test will be null.
-- if return is null the book is out on loan and a non null value will be returned to loan_test.
SET loan_test = (SELECT `code` FROM loan
WHERE (`code` = copy_code) AND (`return` IS NULL));
-- if a copy is available loan_test will be null.
-- A null value implies that the copy had a one or many records in loan with a non null return or the copy was never out on loan.
IF (loan_test IS NULL) THEN
SET cur = CURRENT_DATE();
SET copy_dur = (SELECT duration
FROM copy
WHERE `code` = copy_code);
-- calculate due date.
SET due = DATE_ADD (cur, INTERVAL copy_dur DAY);
-- issue the new loan.
INSERT INTO loan (`code`, `no`, taken, due)
VALUES (copy_code, student_no, cur, due);
SET inserted = TRUE;
LEAVE copy_codes;
END IF;
END LOOP;
CLOSE copy_c;
-- inform users of a failed loan.
IF (inserted = FALSE) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'No currently available copies or book does not exist! ';
END IF;
END$$
DELIMITER ;
MySQL Workbench gives you an error message with details. Didn't you see that? Actually, it gives you 2 errors, but the first one (about FETCH NEXT) is a bug in the WB syntax checker and will be fixed in the next release.
The second one says:
"DATE_ADD" is not valid at this position, expecting a complete function call or other expression.
Which much better describes what is wrong than those ugly error messages from MySQL (or MariaDB for that matter). When you look at that call you see there's a space before the opening parenthesis, which changes the meaning due to SQL mode IGNORE_SPACE. Remove the space char and your SP will be accepted.

Trigger which check the current Date with the Date in the table

I do not know how to compare 2 Dates in a trigger (one in the table and the current Date)
Here is my draft of the trigger:
CREATE trigger check_update
BEFORE DELETE ON customer_contract
For each row
Begin
If(date_to_cancel_contract > (<date>))
Signal sqlstate ‘45000’
Set message_text = ‘Error, not allowed to cancel contract.’
END IF
What’s wrong? How can I fix the problem?
The condition should be (provided it is SQL Server)
If(date_to_cancel_contract > dateadd(day,datediff(day,0,getdate()),0))