Error 1111: mysql on trigger from insert - mysql

I am trying to understand why this trigger keeps giving me an error about invalid use of grouped function when i try to run a basin insert statement to test this out.
I have tried working with this to figure out what i am doing wrong but the error just remains the same. Error 1111
DROP TRIGGER a_num;
DELIMITER //
CREATE TRIGGER a_num BEFORE INSERT ON test_a
FOR EACH ROW BEGIN
DECLARE last INT DEFAULT 0;
INSERT INTO test_b SET full_name = CONCAT_WS(' ', NEW.f_name, NEW.l_name);
SET last = COUNT(id);
UPDATE test_b SET number = CONCAT_WS('-', last, LEFT(NEW.f_name, 2), LEFT(NEW.f_name, 2)) WHERE id = last;
END;
//
Please don't mind the use or poor construction I quite a newb.
Thanks.

I think it should be -
DROP TRIGGER a_num;
DELIMITER //
CREATE TRIGGER a_num BEFORE INSERT ON test_a
FOR EACH ROW BEGIN
DECLARE last INT DEFAULT 0;
INSERT INTO test_b SET full_name = CONCAT_WS(' ', NEW.f_name, NEW.l_name);
SET last = LAST_INSERT_ID();
UPDATE test_b SET number = CONCAT_WS('-', last, LEFT(NEW.f_name, 2), LEFT(NEW.f_name, 2)) WHERE id = last;
END;
//

Can you provide the CREATE statement for test_a and the INSERT statement you're using?
In MySQL Workbench if you right click on test_a go to Copy to Clipboard..Create Statement, will send the table definition.
Is there a reason you're inserting and then updating the same record? Could you combine this into one insert?

Related

Create sql procedure but it's not appeared in the table

there is no error but also doesn't show success
at first, it shows on only table registrations and not the registration_details, and now doesn't appear in both table.
set foreign_key_checks = 0;
drop procedure if exists createRegist;
delimiter //
create procedure createRegist()
begin
declare total_credit float;
declare registration_id INT;
declare credit float;
-- create first registration for student 1
set total_credit = 0;
insert into `student_regist`.`registrations` (`registration_id`, `student_id`,`total_credit`)
values (1, 1, total_credit);
SELECT LAST_INSERT_ID() INTO registration_id;
-- create registration detail 1
SELECT
`student_regist`.`courses`.`credit`
INTO credit FROM
`student_regist`.`courses`
WHERE
`student_regist`.`courses`.`course_id` = 1
LIMIT 1;
set total_credit = total_credit + credit;
insert into `student_regist`.`registration_details` (`registration_details_id`, `registration_id`, `course_id`, `semester`)
values (1, 1, 1, 1);
SELECT 'Success';
end//
delimiter ;
You have not provided nearly enough detail for us to provide any concrete answers. Adding the DDL for your tables to your question is the minimum required for a real answer.
That said, here are some suggestions.
We know nothing of the values you need to store in credit (and total_credit) but it seems likely that it should be DECIMAL, and not FLOAT. Searching decimal vs float on here returns Float vs Decimal in ActiveRecord as the first result.
If you are using MySQL Workbench the errors/warnings should be displayed in the Output Area (View -> Panels -> Show Output Area). Or you could run SHOW WARNINGS; after calling your SP.
CALL createRegist();
SHOW WARNINGS;
Your first insert into registrations uses a hardcoded value of 1 for registration_id, which is presumably the primary key (PK) for the table. The second time you execute the SP and it tries to insert 1 into your PK, it will fail with a duplicate key error -
Error Code: 1062. Duplicate entry '1' for key 'registrations.PRIMARY'
You then follow up with the call for LAST_INSERT_ID() which will not work as you are expecting. From the MySQL docs -LAST_INSERT_ID()
The value of LAST_INSERT_ID() is not changed if you set the AUTO_INCREMENT column of a row to a non-“magic” value (that is, a value that is not NULL and not 0).
Changing the value passed in the insert statement to NULL or 0 (or removing completely) will resolve this -
/* Passing in value of NULL */
set total_credit = 0;
insert into `student_regist`.`registrations` (`registration_id`, `student_id`,`total_credit`)
values (NULL, 1, total_credit);
/* or removing completely */
set total_credit = 0;
insert into `student_regist`.`registrations` (`student_id`,`total_credit`)
values (1, total_credit);

mysql procedure with if condition

I'm in my first databases class and I'm trying to write a conditional block for a mysql procedure.
This is the procedure:
delimiter //
CREATE PROCEDURE add_ascent(IN cid INT, IN pid INT)
BEGIN
DECLARE count_ascents INT;
SET count_ascents = 0;
SELECT COUNT(`cid`) INTO count_ascents FROM ascents WHERE `cid`=cid AND `pid`=pid;
IF count_ascents < 1 THEN
INSERT INTO ascents (`cid`, `pid`) VALUES (cid, pid);
UPDATE climbers SET climbers.ascents = climbers.ascents + 1 WHERE climbers.id=cid;
UPDATE problems SET problems.ascents = problems.ascents + 1 WHERE problems.id=pid;
END IF;
END;
//
delimiter ;
The goal of the procedure is to only perform the insert and updates if the (cid, pid) pair is not in the the ascents database. After testing, the program doesn't seem to go into the if block at all.
FYI, you might want to consider using an UPSERT, instead of "select/if/insert". For example, mySQL offers INSERT ON DUPLICATE KEY UPDATE.
Here, I suggest:
giving your parameters a DIFFERENT name than the column name, for example iCid and iPid, then
Typing SELECT COUNT(cid) INTO count_ascents FROM ascents WHERE cid=iCid AND pid=iPid and checking the result.

user defined function in insert command

I created a function:
DELIMITER $$
DROP FUNCTION IF EXISTS `heena`.`customer_id`$$
CREATE DEFINER=`root`#`localhost` FUNCTION `heena`.`customer_id`(
a varchar(20),
b varchar(20)
) RETURNS varchar(50) CHARSET latin1
DETERMINISTIC
BEGIN
RETURN CONCAT(
(select ((id), 0) + 1
from heenaj),
substring(a,1,2),
substring(b,1,2));
END;$$
DELIMITER ;
The code executed fine, but when I'm inserting a value using:
insert into heenaj
(c_id,name,number)
values
(customer_id121("abcd",9868275817),"abcd",9868275817);
It shows an error:
Column 'c_id' cannot be null
There's something wrong with your RETURN.
Maybe you are meaning to do this, although I am only guessing:
RETURN CONCAT(
(select ifnull(max(id), 0) + 1
from heenaj),
substring(a,1,2),
substring(b,1,2));
sqlfiddle
Then, you're calling customerid121() not customer_id(). Could this be typo?
Also, in looking at what you're trying to do: do you want your id as auto_increment and just want to have c_id as the id, concatenated with first 2 characters of name and concatenated with first 2 characters of number?
I suggest another solution. It might be nicer to drop your function and create a TRIGGER for before INSERT, like this:
CREATE TRIGGER set_customer_id BEFORE INSERT on heenaj
FOR EACH ROW
BEGIN
SET NEW.c_id = CONCAT((SELECT IFNULL(MAX(id),0)+1 FROM heenaj),SUBSTRING(NEW.name,1,2),SUBSTRING(NEW.number,1,2));
END/
This way, when you insert you can just ignore c_id and insert like this:
insert into heenaj(name,number)
values ("abcd",9868);
The trigger will handle the setting of c_id for you.
sqlfiddle for TRIGGER
P.S. To create the trigger (in the sqlfiddle), I selected / as my delimiter. You might change that / to $$, since you're setting delimiter as $$.

How to transform/migrate a mysql trigger to a Sql Server Trigger

I did a trigger in mysql to shoot alerts always an input value was less than the set value. But now I need it is done in SQL SERVER.
I would be grateful if someone could help me transform mysql trigger to a SQL Server trigger.
Thanks to all at once.
My trigger is:
DELIMITER $$
create TRIGGER alert
AFTER INSERT ON records
FOR EACH ROW
begin
Set #comp=0;
Set #tempmax=0;
Set #tempmin=0;
select lim_inf_temp into #tempmin from sensores where idSensor=NEW.idSensor;
Set #maxidAlarme=0;
if (CAST(NEW.Temperatura AS UNSIGNED)<#tempmin) then
SELECT MAX(idAlarme) into #maxidAlarme FROM alarmes;
SET #maxidAlarme=#maxidAlarme+1;
INSERT INTO alarmes(idAlarme,descricao_alarme, idRegisto) VALUES (#maxidAlarme,"inserted below the normal temperature",New.idRegisto);
INSERT INTO sensores_tem_alarmes(idSensor,idAlarme,dataAlarme) VALUES (NEW.idSensor,#maxidAlarme,NOW());
set #comp=+1;
end if;
set #id_sensores_em_alerta=1;
SELECT MAX(id_sensores_em_alerta) into #id_sensores_em_alerta FROM sensores_em_alerta;
INSERT INTO sensores_em_alerta(id_sensores_em_alerta, idSensor, idAlarme, data_registo, numerosensoresdisparados) VALUES (id_sensores_em_alerta,NEW.idSensor, #maxidAlarme, NOW(), #comp);
end $$;
DELIMITER ;
I've tried to make the trigger in SQL Server, but as the script is different and I'm getting many difficulties to do the right way.
My attempt that was not going at all well:
CREATE TRIGGER Alert ON registos AFTER INSERT AS
BEGIN
DECLARE #comp decimal= 0
DECLARE #tempmax decimal= 0
DECLARE #tempmin decimal= 0
DECLARE #current_max_idAlarme int = (SELECT MAX(IdAlarme) FROM alarmes)
-- Insert into alarmes from the inserted rows if temperature less than tempmin
INSERT alarmes (IdAlarme, descricao_alarme, idRegisto)
SELECT
ROW_NUMBER() OVER (ORDER BY i.idRegisto) + #current_max_idAlarme,
'temp Error',
i.idRegisto
FROM
inserted AS i
WHERE
i.Temperatura < #tempmin
END
But dont do anything.
Dont create data on table alarmes :S
Does anyone could help me please. I would be eternally grateful.
Many Greetings and thank you all.
First of all, MSSQL doesn't have the option FOR EACH ROW, so it treats multiple inserted rows at once as a set. You will therefore have to insert the values into a table variable.
Unfortunately I do not know much MySQL actually, but I believe this is a starting point?
CREATE TRIGGER ALERT
ON records
AFTER INSERT
AS
BEGIN
DECLARE #comp INT;
DECLARE #tempmax INT;
DECLARE TABLE #tempmin (tempmin INT);
INSERT INTO #tempmin
SELECT s.lim_inf_temp FROM sensores s WHERE s.idSensor IN (inserted.idSensor);
--rest of the code
I'm going to post this code against my better judgement - redesign the tables is better than this hack.
This uses a ROW_number() to virtualise a surrogate identity key for the alarmes table. This is a 'bad plan' (tm).
Also the answer is partial - it doesn't do everything your question asked for -- I hope it gets your further along the road. Use it as a guide for how to interact with the virtual INSERTED table. Good luck
CREATE TRIGGER Alert ON records AFTER INSERT AS
BEGIN
DECLARE #comp INT = 0
DECLARE #tempmax INT = 0
DECLARE #tempmin INT = 0
-- get the max current id.
-- note that this is EXTREMELY unsafe as if two pieces of code are executing
-- at the same time then you *will* end up with key conflicts.
-- you could use SERIALIZABLE.... but better would be to redisn the schema
DECLARE #current_max_idAlarme = (SELECT MAX(IdAlarme) FROM alarmes)
-- Insert into alarmes from the inserted rows if temperature less than tempmin
INSERT alarmes (IdAlarme, descricao_alarme, idRegisto)
SELECT
ROW_NUMBER() OVER (ORDER BY i.idRegisto) + #current_max_idAlarme,
'temp Error',
i.idRegisto
FROM
inserted AS i
WHERE
i.Temperatura < #tempmin
END

IF NOT EXISTS in mysql showing syntax error

I am trying to convert this tsql to mysql but showing error need help
CREATE PROCEDURE FormAdd
#formName varchar(MAX)
AS
IF NOT EXISTS(SELECT * FROM tbl_Form WHERE formName=#formName)
BEGIN
INSERT INTO tbl_Form
(formName)
VALUES
(#formName)
SELECT ##identity
END
ELSE
BEGIN
SELECT '-1'
END
mysql
CREATE PROCEDURE FormAdd
(p_formName varchar(500) )
begin
INSERT INTO tbl_Form (formName)
VALUES (p_formName)
where NOT EXISTS(SELECT * FROM tbl_Form WHERE formName=p_formName) ;
SELECT Last_insert_id() as returnvalue ;
SELECT '-1' ;
end
Your attempt was syntactically invalid because logically, an INSERT statement cannot contain a WHERE clause since it does not act on existing rows.
If the purpose is to insert only if the value for p_formname is not already present, then an appropriate step would be to define a unique index on that column first. Then, construct your procedure to attempt the insert and inspect the ROW_COUNT() value to see if one was inserted and act accordingly, returning -1 if not to adapt your existing T-SQL procedure.
First create the unique index on p_formname:
ALTER TABLE tbl_Form ADD UNIQUE KEY `idx_formName` (`formName`);
Then your procedure should use INSERT INTO...ON DUPLICATE KEY UPDATE to attempt to insert the row. Per the documentation, the value of ROW_COUNT() will be 0 if a new row was not inserted or 1 if it was.
CREATE PROCEDURE FormAdd (p_formName varchar(500))
BEGIN
/* Attempt the insert, overwrite with the same value if necessary */
INSERT INTO tbl_Form (formName) VALUES (p_formName) ON DUPLICATE KEY UPDATE formName = p_formName;
/* Return the LAST_INSERT_ID() for a new row and -1 otherwise */
SELECT
CASE
WHEN ROW_COUNT() = 1 THEN LAST_INSERT_ID()
ELSE -1
END AS returnValue;
END