How to use NEW value in cursor (after insert trigger Mysql) - mysql

I have one table to use after insert trigger.i want to use cursor for looping perpose logic.I have try this to simple declare cursor
DECLARE demo_cursor CURSOR FOR SELECT * FROM tbl_demo WHERE id=NEW.id;
However its not working but its working fine when use static insted of NEW.id like this
DECLARE demo_cursor CURSOR FOR SELECT * FROM tbl_demo WHERE id=5;
What going wrong.
Thanks in advance

I can't reproduce the problem.
mysql> DROP TABLE IF EXISTS `tbl_demo`, `result_demo`;
Query OK, 0 rows affected (0.01 sec)
mysql> CREATE TABLE IF NOT EXISTS `tbl_demo` (
-> `id` INT,
-> `value` VARCHAR(50)
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE IF NOT EXISTS `result_demo` (
-> `id` INT,
-> `value` VARCHAR(50)
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> DELIMITER //
mysql> CREATE TRIGGER `trg_after_insert` AFTER INSERT ON `tbl_demo`
-> FOR EACH ROW
-> BEGIN
-> DECLARE `done` BOOL DEFAULT FALSE;
-> DECLARE `_id` INT;
-> DECLARE `_value` VARCHAR(50);
->
-> DECLARE `demo_cursor` CURSOR FOR
-> SELECT * -- <- SELECT `id`, `value` Recommendation for use
-> FROM `tbl_demo`
-> WHERE `id` = NEW.`id`;
-> DECLARE CONTINUE HANDLER FOR NOT FOUND SET `done` := TRUE;
->
-> OPEN `demo_cursor`;
->
-> `read_loop`: LOOP
-> FETCH `demo_cursor` INTO `_id`, `_value`;
->
-> IF `done` THEN
-> CLOSE `demo_cursor`;
-> LEAVE `read_loop`;
-> END IF;
->
-> INSERT INTO `result_demo`
-> (`id`, `value`)
-> VALUES
-> (`_id`, `_value`);
-> END LOOP;
-> END//
Query OK, 0 rows affected (0.00 sec)
mysql> DELIMITER ;
mysql> INSERT INTO `tbl_demo`
-> (`id`, `value`)
-> VALUES
-> (1, 'Value 1'),
-> (1, 'Value 2'),
-> (1, 'Value 3');
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> SELECT
-> `id`,
-> `value`
-> FROM
-> `tbl_demo`;
+------+---------+
| id | value |
+------+---------+
| 1 | Value 1 |
| 1 | Value 2 |
| 1 | Value 3 |
+------+---------+
3 rows in set (0.00 sec)
mysql> SELECT
-> `id`,
-> `value`
-> FROM
-> `result_demo`;
+------+---------+
| id | value |
+------+---------+
| 1 | Value 1 |
| 1 | Value 1 |
| 1 | Value 2 |
| 1 | Value 1 |
| 1 | Value 2 |
| 1 | Value 3 |
+------+---------+
6 rows in set (0.00 sec)

Related

how to concat null value with other value in same table same field

This is my table
jobs (
depaermentid,
empid,
department
)
I inserted empty value who belongs to the same department
I like to retrieve value instead of null other value who belong to the same department
1|1|
1|2|it
2|1|
2|2|cs
Results like to be
1|1|it
1|2|it
I tried this query
select gepartmentid,empId,department from from jobs group bt department;
Try:
mysql> DROP TABLE IF EXISTS `jobs`;
Query OK, 0 rows affected (0.01 sec)
mysql> CREATE TABLE IF NOT EXISTS `jobs` (
-> `depaermentid` TINYINT NOT NULL,
-> `empid` TINYINT NOT NULL,
-> `department` CHAR(2)
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO `jobs` (
-> `depaermentid`,
-> `empid`,
-> `department`
-> ) VALUES
-> (1, 1, NULL),
-> (1, 2, 'it'),
-> (2, 1, NULL),
-> (2, 2, 'cs');
Query OK, 4 rows affected (0.01 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> SELECT
-> `jobs`.`depaermentid`,
-> `jobs`.`empid`,
-> IFNULL(`jobs`.`department`, `der`.`department`) `department`
-> FROM
-> `jobs`
-> INNER JOIN (
-> SELECT
-> `depaermentid`,
-> `department`
-> FROM
-> `jobs`
-> WHERE
-> `department` IS NOT NULL
-> ) `der` ON `jobs`.`depaermentid` = `der`.`depaermentid`;
+--------------+-------+------------+
| depaermentid | empid | department |
+--------------+-------+------------+
| 1 | 1 | it |
| 1 | 2 | it |
| 2 | 1 | cs |
| 2 | 2 | cs |
+--------------+-------+------------+
4 rows in set (0.00 sec)
See db-fiddle.

how to update records of two different table present in two different database through single procedure in mysql?

CREATE PROCEDURE p_samp(
IN p_id INT,IN p_table_choice VARCHAR(10)
)
BEGIN
CASE p_table_choice
WHEN p_table_choice = 'A' THEN
USE database1;
update sample1
SET name = 'sam'
WHERE id = p_id;
WHEN p_table_choice = 'B' THEN
USE database2;
update sample2
SET name = 'sam'
WHERE id = p_id;
ELSE
BEGIN
END;
END CASE ;
END;
You can try:
CREATE PROCEDURE p_samp(
IN p_id INT,IN p_table_choice VARCHAR(10)
)
BEGIN
CASE p_table_choice
WHEN p_table_choice = 'A' THEN
update database1.sample1
SET name = 'sam'
WHERE id = p_id;
WHEN p_table_choice = 'B' THEN
update database2.sample2
SET name = 'sam'
WHERE id = p_id;
ELSE
BEGIN
END;
END CASE ;
END;
I tried a sample procedure and it worked.
Here's a sample procedure I tried to perform a similar update between two databases learning and pricing >>
CREATE PROCEDURE `xxxx`(A int(1))
begin
case A
when 1 then update learning.GAUL set user='OBELIX' where id=1;
when 0 then update pricing.K1 set amntIN='500' where account=1;
else
select 'DUMMY';
END CASE;
END
So basically the first update shall result in one affected row and the 2nd one shall result in 2 affected rows.
I call them:
mysql> call xxxx(1);
Query OK, 1 row affected (0.05 sec)
mysql> call xxxx(0);
Query OK, 3 rows affected (0.12 sec)
mysql> call xxxx(3);
+-------+
| DUMMY |
+-------+
| DUMMY |
+-------+
1 row in set (0.00 sec)
The following script works as expect:
mysql> DROP PROCEDURE IF EXISTS `p_samp`;
Query OK, 0 rows affected (0.00 sec)
mysql> DROP TABLE IF EXISTS `database2`.`sample2`,
-> `database1`.`sample1`;
Query OK, 0 rows affected (0.00 sec)
mysql> DROP DATABASE IF EXISTS `database2`;
Query OK, 0 rows affected (0.00 sec)
mysql> DROP DATABASE IF EXISTS `database1`;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE DATABASE IF NOT EXISTS `database1`;
Query OK, 1 row affected (0.00 sec)
mysql> CREATE DATABASE IF NOT EXISTS `database2`;
Query OK, 1 row affected (0.00 sec)
mysql> CREATE TABLE IF NOT EXISTS `database1`.`sample1` (
-> `id` SERIAL,
-> `name` VARCHAR(255)
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE IF NOT EXISTS `database2`.`sample2` (
-> `id` SERIAL,
-> `name` VARCHAR(255)
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO `database1`.`sample1`
-> (`name`)
-> VALUES
-> ('sam in db1');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO `database2`.`sample2`
-> (`name`)
-> VALUES
-> ('sam in db2');
Query OK, 1 row affected (0.00 sec)
mysql> DELIMITER //
mysql> CREATE PROCEDURE `p_samp` (
-> `p_id` BIGINT UNSIGNED,
-> `p_table_choice` CHAR(1)
-> )
-> BEGIN
-> CASE `p_table_choice`
-> WHEN 'A' THEN
-> UPDATE `database1`.`sample1`
-> SET `name` = 'sam'
-> WHERE `id` = `p_id`;
-> WHEN 'B' THEN
-> UPDATE `database2`.`sample2`
-> SET `name` = 'sam'
-> WHERE `id` = `p_id`;
-> END CASE;
-> END//
Query OK, 0 rows affected (0.00 sec)
mysql> DELIMITER ;
mysql> SELECT
-> `id`,
-> `name`
-> FROM
-> `database1`.`sample1`;
+----+------------+
| id | name |
+----+------------+
| 1 | sam in db1 |
+----+------------+
1 row in set (0.00 sec)
mysql> SELECT
-> `id`,
-> `name`
-> FROM
-> `database2`.`sample2`;
+----+------------+
| id | name |
+----+------------+
| 1 | sam in db2 |
+----+------------+
1 row in set (0.00 sec)
mysql> CALL `p_samp`(1, 'A');
Query OK, 1 row affected (0.00 sec)
mysql> SELECT
-> `id`,
-> `name`
-> FROM
-> `database1`.`sample1`;
+----+------+
| id | name |
+----+------+
| 1 | sam |
+----+------+
1 row in set (0.00 sec)
mysql> SELECT
-> `id`,
-> `name`
-> FROM
-> `database2`.`sample2`;
+----+------------+
| id | name |
+----+------------+
| 1 | sam in db2 |
+----+------------+
1 row in set (0.00 sec)
mysql> CALL `p_samp`(1, 'B');
Query OK, 1 row affected (0.00 sec)
mysql> SELECT
-> `id`,
-> `name`
-> FROM
-> `database1`.`sample1`;
+----+------+
| id | name |
+----+------+
| 1 | sam |
+----+------+
1 row in set (0.00 sec)
mysql> SELECT
-> `id`,
-> `name`
-> FROM
-> `database2`.`sample2`;
+----+------+
| id | name |
+----+------+
| 1 | sam |
+----+------+
1 row in set (0.00 sec)

mysql trigger before insert multiple

i have a table like this:
my_table_name
id | name |tipo
1 | hello |0
2 | world |0
3 | hello3 |0
CREATE TRIGGER first_trigger BEFORE INSERT ON my_table_name
FOR EACH ROW
BEGIN
IF (NEW.`tipo` <> 100 )
THEN
SET NEW.tipo = 0;
ELSE
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Error';
END IF;
END
i want to insert this sql statement where i inserts multiple rows me the first is wrong and the second is right
INSERT INTO my_table_name(id, name, tipo) VALUES (4, 'hello1', 100), (5, 'hello5', 50);
resut table :
id | name |tipo
1 | hello |0
2 | world |0
3 | hello3 |0
5 | hello5 |0
In the scenario presented by you it is relatively simple to accomplish what you need.
The problem occurs when the table is empty.
mysql> DELIMITER //
mysql> DROP TABLE IF EXISTS `my_table_name`//
Query OK, 0 rows affected (0,00 sec)
mysql> CREATE TABLE IF NOT EXISTS `my_table_name` (
-> `id` INT UNSIGNED NOT NULL PRIMARY KEY,
-> `name` VARCHAR(25),
-> `tipo` INT UNSIGNED NOT NULL
-> )//
Query OK, 0 rows affected (0,00 sec)
mysql> CREATE TRIGGER `first_trigger` BEFORE INSERT ON `my_table_name`
-> FOR EACH ROW
-> BEGIN
-> IF NEW.`tipo` != 100 THEN
-> SET NEW.`tipo` := 0;
-> ELSE
-> SET NEW.`id` := (SELECT `id` FROM `my_table_name` LIMIT 1);
-> END IF;
-> END//
Query OK, 0 rows affected (0,00 sec)
mysql> DELIMITER ;
mysql> INSERT INTO `my_table_name`
-> (`id`, `name`, `tipo`)
-> VALUES
-> (1, 'hello', 0), (2, 'world', 0), (3, 'hello3', 0);
Query OK, 3 rows affected (0,01 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> SELECT
-> `id`,
-> `name`,
-> `tipo`
-> FROM
-> `my_table_name`;
+----+--------+------+
| id | name | tipo |
+----+--------+------+
| 1 | hello | 0 |
| 2 | world | 0 |
| 3 | hello3 | 0 |
+----+--------+------+
3 rows in set (0,00 sec)
mysql> INSERT IGNORE `my_table_name`
-> (`id`, `name`, `tipo`)
-> VALUES
-> (4, 'hello1', 100), (5, 'hello5', 50);
Query OK, 1 row affected, 1 warning (0,00 sec)
Records: 2 Duplicates: 1 Warnings: 1
mysql> SHOW WARNINGS;
+---------+------+---------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------+
| Warning | 1062 | Duplicate entry '1' for key 'PRIMARY' |
+---------+------+---------------------------------------+
1 row in set (0,00 sec)
mysql> SELECT
-> `id`,
-> `name`,
-> `tipo`
-> FROM
-> `my_table_name`;
+----+--------+------+
| id | name | tipo |
+----+--------+------+
| 1 | hello | 0 |
| 2 | world | 0 |
| 3 | hello3 | 0 |
| 5 | hello5 | 0 |
+----+--------+------+
4 rows in set (0,00 sec)
UPDATE
Another option (no matter if the table is empty) is to use an updatable view with clause WITH CHECK OPTION.
mysql> DELIMITER //
mysql> DROP VIEW IF EXISTS `view_my_table_name`//
Query OK, 0 rows affected (0,00 sec)
mysql> DROP TABLE IF EXISTS `my_table_name`//
Query OK, 0 rows affected (0,00 sec)
mysql> CREATE TABLE IF NOT EXISTS `my_table_name` (
-> `id` INT UNSIGNED NOT NULL PRIMARY KEY,
-> `name` VARCHAR(25),
-> `tipo` INT UNSIGNED NOT NULL
-> )//
Query OK, 0 rows affected (0,00 sec)
mysql> CREATE VIEW `view_my_table_name` AS
-> SELECT `id`, `name`, `tipo`
-> FROM `my_table_name`
-> WHERE `tipo` != 100
-> WITH LOCAL CHECK OPTION//
Query OK, 0 rows affected (0,01 sec)
mysql> CREATE TRIGGER `first_trigger` BEFORE INSERT ON `my_table_name`
-> FOR EACH ROW
-> BEGIN
-> IF NEW.`tipo` != 100 THEN
-> SET NEW.`tipo` := 0;
-> END IF;
-> END//
Query OK, 0 rows affected (0,00 sec)
mysql> DELIMITER ;
mysql> INSERT INTO `my_table_name`
-> (`id`, `name`, `tipo`)
-> VALUES
-> (1, 'hello', 0), (2, 'world', 0), (3, 'hello3', 0);
Query OK, 3 rows affected (0,00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> SELECT
-> `id`,
-> `name`,
-> `tipo`
-> FROM
-> `my_table_name`;
+----+--------+------+
| id | name | tipo |
+----+--------+------+
| 1 | hello | 0 |
| 2 | world | 0 |
| 3 | hello3 | 0 |
+----+--------+------+
3 rows in set (0,00 sec)
mysql> INSERT IGNORE `view_my_table_name`
-> (`id`, `name`, `tipo`)
-> VALUES
-> (4, 'hello4', 100), (5, 'hello5', 50);
Query OK, 1 row affected, 1 warning (0,00 sec)
Records: 1 Duplicates: 0 Warnings: 1
mysql> SHOW WARNINGS;
+---------+------+--------------------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------------------+
| Warning | 1369 | CHECK OPTION failed '_.view_my_table_name' |
+---------+------+--------------------------------------------+
1 row in set (0,00 sec)
mysql> SELECT
-> `id`,
-> `name`,
-> `tipo`
-> FROM
-> `my_table_name`;
+----+--------+------+
| id | name | tipo |
+----+--------+------+
| 1 | hello | 0 |
| 2 | world | 0 |
| 3 | hello3 | 0 |
| 5 | hello5 | 0 |
+----+--------+------+
4 rows in set (0,00 sec)

Set column value of this/next auto_increment value

Is there any way to accomplish below sql result as a one liner.
create table test( id int not null primary key auto_increment, name char(10));
insert into test (name) values ('voda'+ this_value_of_id);
// so select would return
MariaDB [testdb]> select * from test;
+----+------+
| id | name |
+----+------+
| 1 | foo1 |
+----+------+
Yes, I know the other way is
begin transaction;
insert into test (name) values ('voda');
update test set name = concat('voda', id) where id = 1;
commit;
An option or approach can be via a Virtual (Computed) Columns.
Example:
MariaDB [testdb]> DROP TABLE IF EXISTS `test`;
Query OK, 0 rows affected (0.00 sec)
MariaDB [testdb]> CREATE TABLE `test` (
-> `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> `name` CHAR(10),
-> `nameid` VARCHAR(20) AS (CONCAT(`name`, `id`)) VIRTUAL
-> );
Query OK, 0 rows affected (0.00 sec)
MariaDB [testdb]> INSERT INTO `test`
-> (`name`)
-> VALUES
-> ('foo'), ('voda');
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
MariaDB [testdb]> SELECT
-> `id`,
-> `nameid` `name`
-> FROM
-> `test`;
+----+-------+
| id | name |
+----+-------+
| 1 | foo1 |
| 2 | voda2 |
+----+-------+
2 rows in set (0.00 sec)

Can not fetch datetime column when use curor in store procedure

I use a curor to fetch two values, int and datetime, but I find the return value is null instead of a datetime value.
mysql> select * from test1|
+-------+---------------------+
| id | qdtime |
+-------+---------------------+
| 10001 | 2015-03-05 12:15:36 |
| 10004 | 2015-03-05 12:15:36 |
+-------+---------------------+
2 rows in set (0.00 sec)
mysql> delimiter |
mysql> drop procedure if exists demo |
Query OK, 0 rows affected (0.00 sec)
mysql> create procedure demo()
-> BEGIN
-> DECLARE TARGETID INT;
-> DECLARE QDTIME DATETIME;
-> DECLARE done INT DEFAULT FALSE;
-> DECLARE CUR1 CURSOR FOR SELECT id,qdtime FROM test1;
-> DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
-> OPEN CUR1;
-> judge_loop: LOOP
-> FETCH CUR1 INTO TARGETID, QDTIME;
-> IF done THEN
-> LEAVE judge_loop;
-> END IF;
->
-> SELECT TARGETID, QDTIME;
-> END LOOP;
-> CLOSE CUR1;
-> END;| Query OK, 0 rows affected (0.00 sec)
mysql> call demo()|
+----------+--------+
| TARGETID | QDTIME |
+----------+--------+
| 10001 | NULL |
+----------+--------+
1 row in set (0.00 sec)
+----------+--------+
| TARGETID | QDTIME |
+----------+--------+
| 10004 | NULL |
+----------+--------+
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Never name a variable like columns or anything. To avoid unclear names use prefixes. For example, let every variable start with v_ and every parameter with p_. This also greatly improves code readability.
Your cursor
DECLARE CUR1 CURSOR FOR SELECT id,qdtime FROM test1;
selects here the variable, not the column. Since your variable has the value NULL at this moment, so has your result.