MySQL Triggers, drop query inside trigger - mysql

I am trying to write a trigger to not allow an update of a relation if a statement is true, and I am running into some trouble
CREATE TRIGGER noPriceLowerSpeed
BEFORE UPDATE
ON pc
FOR EACH ROW
BEGIN
IF(new.speed IS IN (SELECT speed FROM pc AS pc1) AND pc1.price < new.price)
THEN DROP new
END IF;
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 'IN (SELECT speed FROM pc AS pc1) AND pc1.price <
new.price) THEN DROP new
I am trying to not allow a pc into my pc relation if it has a higher price than a pc with the same speed.
How might I write this trigger to just not allow the update?

IS is superfluous. You should just use the following syntax:
new.speed IN( ... )
Also, I think you missed a ; after THEN DROP new.

To make the statement fail, use the SIGNAL statement in the trigger, to raise an error.
http://dev.mysql.com/doc/refman/5.5/en/signal.html

Related

My SQL Syntax error for multiple commands in one query, working for each command running separately

I'm trying to run the following MySQL command:
USE database_name;
DROP TEMPORARY TABLE IF EXISTS only_with_balance;
DROP TEMPORARY TABLE IF EXISTS keys_to_match;
CREATE TEMPORARY TABLE only_with_balance as (
SELECT
*
FROM
transactions t
WHERE
t.balance is not NULL
and (t.transaction_status_id = 4 or t.transaction_status_id = 5)
and (t.date between "2022-05-01" and "2022-08-24" )
);
But I'm getting a syntax error while trying to run the all the commands at once.
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 'DROP TEMPORARY TABLE IF EXISTS only_with_balance;
DROP TEMPORARY TABLE IF EXIST' at line 2
When I run each command separately, the result is the expected.
Can someone help me here?
What am I forgetting?
In MySQL, by default the query interface only allows one SQL statement per call.
There's an option to enable multi-query per call, but it must be set at connect time. Some MySQL connectors do this by default, or allow it as an option, but some do not. You didn't say if you're writing code or if you're submitting this set of queries through a client (though you tag the question 'dbeaver' you don't say anything else about that). So I can't guess what interface you're using for these queries.
Anyway, there's no advantage to using multi-query. The default mode is one SQL statement per call. That's what I do.
Using the default mode of a single SQL statement per call has some advantages:
Supports prepared statements and bound parameters (you can't run multiple statements in a single prepare call, even if you enable multi-query).
Simplifies processing errors and warnings.
Simplifies processing result sets.

MySQL Not Reading Full Line

I'm using the following SQL Script in my IDE DBeaver, MySQL 8.0.21 Linux (Docker Container). Database is in utf8mb4 / utf8mb4_general_ci encodings.
DELIMITER //
CREATE OR REPLACE TRIGGER trg_line_total
BEFORE INSERT ON LINE
FOR EACH ROW
BEGIN
SET NEW.LINE_TOTAL = NEW.LINE_UNITS * NEW.LINE_PRICE;
END //
DELIMITER ;
It seems to be valid SQL, but it is returning the following error, as if it wasn't reading the full line. I can remove tabs, line returns and it will read more or less characters.
Error occurred during SQL script execution
Reason:
SQL 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 'TRIGGER trg_line_total
BEFORE INSERT ON LINE
FOR EACH ROW
BEGIN
SET NEW.LINE_TO' at line 1
I already seemingly fixed this error once today by deleting everything I had in my editor and typing it out from scratch, as if there was some invisible line ending that was messing things up or getting interpreted. I looked in vim and used the :set list command and I see are regular line return carriages. What could it be?
Unfortunately, there's no ALTER TRIGGER or CREATE OR REPLACE TRIGGER in Oracle's MySQL. It supports only Create Trigger format.
For MariaDB, in version 10.1.4, added support CREATE OR REPLACE TRIGGER to their drop-in replacement for MySQL.
If you are sure that trigger doesn't exists
Use CREATE instead of CREATE OR REPLACE.
If you are modifying existing trigger
I would suggest that the best practice is to lock the table where the trigger lives, so no rows are impacted with the trigger absent. Dropping and adding triggers while a table is locked is allowed.
mysql> LOCK TABLES t1 WRITE; -- the next prompt appears once you've obtained the lock
mysql> DROP TRIGGER t1_bi;
mysql> DELIMITER $$
mysql> CREATE TRIGGER ti_bi BEFORE INSERT ON t1 FOR EACH ROW
BEGIN
...
END $$
mysql> DELIMITER ;
mysql> UNLOCK TABLES;
Reference: Modify Existing Trigger Definition in MySQL

Update else INSERT in mysql

I tested this code:
UPDATE books SET price='20000' WHERE user_id='2'
IF ROW_COUNT()=0
INSERT INTO store_books(name,user_id) VALUES ('test1','2')
I encountered the following error.
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 'IF ROW_COUNT()=0 INSERT INTO store_books(name,user_id) VALUES
('test1','2')' at line 2
Is there any solution to solve this problem?
I don't want to use INSERT INTO ... ON DUPLICATE KEY UPDATE (because i have multi keys in my main table).
Above example is trial for finding new way.
Pattern that i want:
Update(if exists) ELSE Insert.
Two things:
INSERT ... ON DUPLICATE KEY UPDATE ... is by far the best way to do what you want to do. If you don't do this, you'll have to use a database transaction to make sure you maintain integrity for the operation you want.
MySQL (unlike, say, MS SQL server) doesn't allow conditional execution of queries except in stored procedures. Read this. If conditional in SQL Script for Mysql

MySQL Truncate Table Before Insert

I am creating a table in MySQL for which I only ever want it to contain one tuple at a time. To enforce this, I am trying to create a trigger which will truncate the table each time an INSERT occurs. However, I am running into problems.
SQL:
CREATE TRIGGER `tbl_hire_truncate`
BEFORE INSERT ON `tbl_hire`
FOR EACH ROW
BEGIN
TRUNCATE TABLE `tbl_hire`;
END
Error:
#1064 - 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 '' at line 5
Every example of a trigger that I've seen uses a FOR EACH loop, but it certainly doesn't make much sense with what I am trying to achieve.
How can I rewrite my SQL to achieve my goal?

error 1064 in trigger mysql

This is my first time using mysql and I am tying to learn how to use trigger.
Im using navicat, i go to table design and then go triggers tab. I create a trigger named testing and in definition I typed:
delimiter |
CREATE TRIGGER lpr.mytesting AFTER INSERT ON lpr.lpr_opt_upload
FOR EACH ROW BEGIN
set new.lpr_text := reverse(new.lpr_text);
END;
| delimiter ;
All im tying to do is whenever something new is inserted, I reverse the text in lpr_text field. However, i get "1064 - you have an error in your SQL; check the manual that corresponds o your MySql server version for the right syntax to yse 'ON lpr_opt_upload' FOR EACH ROW create trigger testing before insert on lpr_op' at line 1." I dont understand what Im doing wrong, I am just copying an trigger example.
//-------------------------------------------------------------------------//
I figured out the problem. I am using navicat and in navicat trigger tab, you only type the body into the definition, Not the header (ex: CREATE TRIGGER lpr.mytesting AFTER INSERT ON lpr.lpr_opt_upload). There are check box next to the name of your trigger and you use those instead of writing your own header.
The DELIMITER command is a client command, which not all clients support (it doesn't get sent to the server at all, it just instructs the client how to tell statements apart in order that they get sent to the server correctly). References to it in the MySQL manual assume that you are using the 'official' MySQL clients, such as the mysql command-line tool or MySQL Workbench (both of which support the DELIMITER command).
I don't know how to change the statement delimiter in Navicat, but that is the root of your problem.