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)
Related
Let's say I have 2 tables - item_images and images.
When I run query
SELECT image_id FROM item_images WHERE item_id=1
I get image_id values 5, 6
When I run
DELETE FROM images WHERE id in (5, 6);
It also works and deletes these 2 rows.
But when I try to chain these 2 queries together, it fails with error 1175.
DELETE FROM images WHERE id in (SELECT image_id FROM item_images WHERE item_id=1);
Error Code:
1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column To disable safe mode, toggle the option in Preferences -> SQL Editor and reconnect. 0.000 sec
id field is set as private key, not null.
Why does this happen if if id in WHERE is clearly private key?
Is the only way to go around this is to disable safe mode, or is there another way?
Thanks!
Assuming id column (images table) is always greater than zero (0):
mysql> SET SESSION SQL_SAFE_UPDATES := 1;
Query OK, 0 rows affected (0.00 sec)
mysql> DROP TABLE IF EXISTS `item_images`, `images`;
Query OK, 0 rows affected (0.09 sec)
mysql> CREATE TABLE IF NOT EXISTS `images` (
-> `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE IF NOT EXISTS `item_images` (
-> `item_id` BIGINT UNSIGNED NOT NULL,
-> `image_id` BIGINT UNSIGNED NOT NULL
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO `images`
-> VALUES (NULL), (NULL), (NULL),
-> (NULL), (NULL), (NULL);
Query OK, 6 rows affected (0.00 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql> INSERT INTO `item_images`
-> (`item_id`, `image_id`)
-> VALUES (1, 5), (1, 6), (2, 1),
-> (2, 3), (3, 2), (4, 2);
Query OK, 6 rows affected (0.00 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql> SELECT `image_id`
-> FROM `item_images`
-> WHERE `item_id` = 1;
+----------+
| image_id |
+----------+
| 5 |
| 6 |
+----------+
2 rows in set (0.00 sec)
mysql> DELETE
-> FROM `images`
-> WHERE `id` IN (SELECT `image_id`
-> FROM `item_images`
-> WHERE `item_id` = 1);
ERROR 1175 (HY000): You are using safe update mode and you tried to update
a table without a WHERE that uses a KEY column
mysql> DELETE
-> FROM `images`
-> WHERE `id` > 0 AND
-> `id` IN (SELECT `image_id`
-> FROM `item_images`
-> WHERE `item_id` = 1);
Query OK, 2 rows affected (0.01 sec)
See db-fiddle.
UPDATE
In the first DELETE the index (key) is not reached.
mysql> SET SESSION SQL_SAFE_UPDATES := 0;
Query OK, 0 rows affected (0.00 sec)
mysql> EXPLAIN DELETE
-> FROM `images`
-> WHERE `id` IN (SELECT `image_id`
-> FROM `item_images`
-> WHERE `item_id` = 1);
+----+--------------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+--------------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | DELETE | images | NULL | ALL | NULL | NULL | NULL | NULL | 6 | 100.00 | Using where |
| 2 | DEPENDENT SUBQUERY | item_images | NULL | ALL | NULL | NULL | NULL | NULL | 6 | 16.67 | Using where |
+----+--------------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------------+
2 rows in set (0.00 sec)
mysql> EXPLAIN DELETE
-> FROM `images`
-> WHERE `id` > 0 AND
-> `id` IN (SELECT `image_id`
-> FROM `item_images`
-> WHERE `item_id` = 1);
+----+--------------------+-------------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+--------------------+-------------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
| 1 | DELETE | images | NULL | range | PRIMARY | PRIMARY | 8 | const | 6 | 100.00 | Using where |
| 2 | DEPENDENT SUBQUERY | item_images | NULL | ALL | NULL | NULL | NULL | NULL | 6 | 16.67 | Using where |
+----+--------------------+-------------+------------+-------+---------------+---------+---------+-------+------+----------+-------------+
2 rows in set (0.01 sec)
See db-fiddle.
CREATE FUNCTION `getSequenceNumber` (
company_id INTEGER, sequence_name varchar(255)) RETURNS INT(10)
BEGIN
INSERT INTO sequences (`company_id`, `name`, `value`)
VALUES (company_id, sequence_name, LAST_INSERT_ID(1))
ON DUPLICATE KEY UPDATE
`value` = LAST_INSERT_ID(value + 1);
RETURN LAST_INSERT_ID(); END
CREATE TABLE `sequences` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`company_id` int(10) unsigned NOT NULL,
`value` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `sequences_name_company_id_unique` (`name`,`company_id`),
KEY `sequences_company_id_index` (`company_id`),
KEY `sequences_value_index` (`value`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
//sample output
MariaDB [testdb]> select version();
+----------------+
| version() |
+----------------+
| 10.2.6-MariaDB |
+----------------+
1 row in set (0.00 sec)
MariaDB [testdb]> select `getSequenceNumber`(1,'sequence_021');
+---------------------------------------+
| `getSequenceNumber`(1,'sequence_021') |
+---------------------------------------+
| 2 |
+---------------------------------------+
1 row in set (0.03 sec)
MariaDB [testdb]> select `getSequenceNumber`(1,'sequence_0212');
+----------------------------------------+
| `getSequenceNumber`(1,'sequence_0212') |
+----------------------------------------+
| 5 |
+----------------------------------------+
1 row in set (0.03 sec)
MariaDB [testdb]> select `getSequenceNumber`(1,'new_sequence123');
+------------------------------------------+
| `getSequenceNumber`(1,'new_sequence123') |
+------------------------------------------+
| 6 |
+------------------------------------------+
1 row in set (0.03 sec)
i have this function my MariaDB and it works, but the problem is when inserting, the new ID it insert is <last_id> + <last value> is there a way to clear/refresh the LAST_INSERT_ID before inserting a record?
EDIT: added create sql statement and sample output
I can't reproduce the problem:
MariaDB [_]> SELECT VERSION();
+----------------+
| VERSION() |
+----------------+
| 10.2.6-MariaDB |
+----------------+
1 row in set (0.00 sec)
MariaDB [_]> DROP TABLE IF EXISTS `sequences`;
Query OK, 0 rows affected, 1 warning (0.00 sec)
MariaMariaDB [_]> CREATE TABLE IF NOT EXISTS `sequences` (
-> `name` VARCHAR(255) PRIMARY KEY,
-> `value` BIGINT UNSIGNED NOT NULL
-> );
Query OK, 0 rows affected (0.01 sec)
MariaDB [_]> DROP FUNCTION IF EXISTS `getSequenceNumber`;
Query OK, 0 rows affected, 1 warning (0.00 sec)
MariaDB [_]> DELIMITER //
MariaDB [_]> CREATE OR REPLACE FUNCTION `getSequenceNumber` (
-> `sequence_name` VARCHAR(255)
-> )
-> RETURNS BIGINT UNSIGNED
-> BEGIN
-> INSERT INTO `sequences` (`name`, `value`)
-> VALUES (`sequence_name`, LAST_INSERT_ID(1))
-> ON DUPLICATE KEY UPDATE `value` = LAST_INSERT_ID(`value` + 1);
-> RETURN LAST_INSERT_ID();
-> END//
Query OK, 0 rows affected (0.00 sec)
MariaDB [_]> DELIMITER ;
MariaDB [_]> SELECT `getSequenceNumber`('sequence_0'); -- 1
+-----------------------------------+
| `getSequenceNumber`('sequence_0') |
+-----------------------------------+
| 1 |
+-----------------------------------+
1 row in set (0.00 sec)
MariaDB [_]> SELECT `getSequenceNumber`('sequence_0'); -- 2
+-----------------------------------+
| `getSequenceNumber`('sequence_0') |
+-----------------------------------+
| 2 |
+-----------------------------------+
1 row in set (0.00 sec)
MariaDB [_]> SELECT `getSequenceNumber`('sequence_1'); -- 1
+-----------------------------------+
| `getSequenceNumber`('sequence_1') |
+-----------------------------------+
| 1 |
+-----------------------------------+
1 row in set (0.01 sec)
MariaDB [_]> SELECT `getSequenceNumber`('sequence_2'); -- 1
+-----------------------------------+
| `getSequenceNumber`('sequence_2') |
+-----------------------------------+
| 1 |
+-----------------------------------+
1 row in set (0.00 sec)
MariaDB [_]> SELECT `getSequenceNumber`('sequence_0'); -- 3
+-----------------------------------+
| `getSequenceNumber`('sequence_0') |
+-----------------------------------+
| 3 |
+-----------------------------------+
1 row in set (0.00 sec)
MariaDB [_]> SELECT `getSequenceNumber`('sequence_2'); -- 2
+-----------------------------------+
| `getSequenceNumber`('sequence_2') |
+-----------------------------------+
| 2 |
+-----------------------------------+
1 row in set (0.00 sec)
MariaDB [_]> SELECT `getSequenceNumber`('sequence_1'); -- 2
+-----------------------------------+
| `getSequenceNumber`('sequence_1') |
+-----------------------------------+
| 2 |
+-----------------------------------+
1 row in set (0.00 sec)
UPDATE
MariaDB [_]> SELECT VERSION();
+----------------+
| VERSION() |
+----------------+
| 10.2.6-MariaDB |
+----------------+
1 row in set (0.00 sec)
MariaDB [_]> DROP FUNCTION IF EXISTS `getSequenceNumber`;
Query OK, 0 rows affected (0.00 sec)
MariaDB [_]> DROP TABLE IF EXISTS `sequences`;
Query OK, 0 rows affected (0.00 sec)
MariaDB [_]> CREATE TABLE IF NOT EXISTS `sequences` (
-> `name` VARCHAR(255) COLLATE utf8mb4_unicode_ci NOT NULL,
-> `company_id` BIGINT UNSIGNED unsigned NOT NULL,
-> `value` BIGINT UNSIGNED NOT NULL,
-> PRIMARY KEY `sequences_name_company_id_unique` (`name`, `company_id`),
-> KEY `sequences_company_id_index` (`company_id`),
-> KEY `sequences_value_index` (`value`)
-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Query OK, 0 rows affected (0.00 sec)
MariaDB [_]> DELIMITER //
MariaDB [_]> CREATE OR REPLACE FUNCTION `getSequenceNumber` (
-> `_company_id` BIGINT UNSIGNED,
-> `sequence_name` VARCHAR(255)
-> ) RETURNS BIGINT UNSIGNED
-> BEGIN
-> INSERT INTO `sequences` (`name`, `company_id`, `value`)
-> VALUES (`sequence_name`, `_company_id`, LAST_INSERT_ID(1))
-> ON DUPLICATE KEY UPDATE `value` = LAST_INSERT_ID(`value` + 1);
-> RETURN LAST_INSERT_ID();
-> END//
Query OK, 0 rows affected (0.00 sec)
MariaDB [_]> DELIMITER ;
MariaDB [_]> SELECT `getSequenceNumber`(1, 'sequence_021'); -- 1
+----------------------------------------+
| `getSequenceNumber`(1, 'sequence_021') |
+----------------------------------------+
| 1 |
+----------------------------------------+
1 row in set (0.00 sec)
MariaDB [_]> SELECT `getSequenceNumber`(2, 'sequence_021'); -- 1
+----------------------------------------+
| `getSequenceNumber`(2, 'sequence_021') |
+----------------------------------------+
| 1 |
+----------------------------------------+
1 row in set (0.01 sec)
MariaDB [_]> SELECT `getSequenceNumber`(1, 'sequence_021'); -- 2
+----------------------------------------+
| `getSequenceNumber`(1, 'sequence_021') |
+----------------------------------------+
| 2 |
+----------------------------------------+
1 row in set (0.02 sec)
MariaDB [_]> SELECT `getSequenceNumber`(2, 'sequence_021'); -- 2
+----------------------------------------+
| `getSequenceNumber`(2, 'sequence_021') |
+----------------------------------------+
| 2 |
+----------------------------------------+
1 row in set (0.00 sec)
MariaDB [_]> SELECT `getSequenceNumber`(1, 'sequence_0212'); -- 1
+-----------------------------------------+
| `getSequenceNumber`(1, 'sequence_0212') |
+-----------------------------------------+
| 1 |
+-----------------------------------------+
1 row in set (0.00 sec)
MariaDB [_]> SELECT `getSequenceNumber`(1, 'sequence_021'); -- 3
+----------------------------------------+
| `getSequenceNumber`(1, 'sequence_021') |
+----------------------------------------+
| 3 |
+----------------------------------------+
1 row in set (0.00 sec)
MariaDB [_]> SELECT `getSequenceNumber`(1, 'new_sequence123'); -- 1
+-------------------------------------------+
| `getSequenceNumber`(1, 'new_sequence123') |
+-------------------------------------------+
| 1 |
+-------------------------------------------+
1 row in set (0.00 sec)
MariaDB [_]> SELECT `getSequenceNumber`(1, 'new_sequence123'); -- 2
+-------------------------------------------+
| `getSequenceNumber`(1, 'new_sequence123') |
+-------------------------------------------+
| 2 |
+-------------------------------------------+
1 row in set (0.01 sec)
I have a table of about 10,000 records there are duplicates in the titles some are repeated more than 5 times.
Sample Data
id| titleslug | views
--------------------
1 |the-box| 200
2 |the-box| 100
3 |the-box| 10
4 |the-man| 15
5 |the-man| 30
6 |the-cup| 10
7 |the-cup| 20
The box appears 3 times so I want to leave that but 'the-man' and 'the-cup' appears 2x I want to delete one of each of them so that the final table becomes
id| titleslug | views
--------------------
1 |the-box| 200
2 |the-box| 100
3 |the-box| 10
5 |the-man| 30
7 |the-cup| 20
If possible I will like to add the view count that is been deleted to the highest one that is been kept.
With the query below I was able to know the number of times items got duplicated.
select titleslug, count(*) as c from articles
group by titleslug having c > 1
order by c desc
I want to delete one of those records that repeat only two times and leave the rest.
I am thinking of this query as below
DELETE a
FROM articles as a, articles as b
WHERE
(a.titleslug = b.titleslug OR a.titleslug IS NULL AND b.titleslug IS NULL)
AND a.views < b.views;
But I need help to put the restriction to delete one only if we have two duplicates.
I have used the query below which reports rows affected but after when I query it seems duplicates were not deleted
DELETE a
FROM articles_copy a
JOIN (SELECT MAX(t.Views) AS max_a1, t.TitleSlug
FROM articles_copy t
GROUP BY t.TitleSlug, t.Views
HAVING COUNT(*)>1 AND COUNT(*)<=2) b ON b.TitleSlug = a.TitleSlug
AND b.max_a1 > a.View
An option can be (evaluate performance issues):
mysql> DROP TABLE IF EXISTS `articles`;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE IF NOT EXISTS `articles` (
-> `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> `title` VARCHAR(25) NOT NULL,
-> `views` INT UNSIGNED
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO `articles`
-> (`title`, `views`)
-> VALUES
-> ('the-box', 200),
-> ('the-box', 100),
-> ('the-box', 10),
-> ('the-man', 15),
-> ('the-man', 30),
-> ('the-cup', 10),
-> ('the-cup', 20);
Query OK, 7 rows affected (0.00 sec)
Records: 7 Duplicates: 0 Warnings: 0
mysql> SELECT
-> `id`,
-> `title`,
-> `views`
-> FROM
-> `articles`;
+----+---------+-------+
| id | title | views |
+----+---------+-------+
| 1 | the-box | 200 |
| 2 | the-box | 100 |
| 3 | the-box | 10 |
| 4 | the-man | 15 |
| 5 | the-man | 30 |
| 6 | the-cup | 10 |
| 7 | the-cup | 20 |
+----+---------+-------+
7 rows in set (0.00 sec)
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> UPDATE `articles`
-> INNER JOIN (
-> SELECT MAX(`id`) `id`, SUM(`views`) `views`
-> FROM `articles`
-> GROUP BY `title`
-> HAVING COUNT(`title`) = 2
-> ) `der`
-> SET `articles`.`views` = `der`.`views`
-> WHERE `articles`.`id` = `der`.`id`;
Query OK, 2 rows affected (0.00 sec)
Rows matched: 2 Changed: 2 Warnings: 0
mysql> DELETE FROM `articles`
-> WHERE `id` IN (SELECT MIN(`der`.`id`)
-> FROM (SELECT `id`, `title`
-> FROM `articles`) `der`
-> GROUP BY `der`.`title`
-> HAVING COUNT(`der`.`title`) = 2);
Query OK, 2 rows affected (0.00 sec)
mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT
-> `id`,
-> `title`,
-> `views`
-> FROM
-> `articles`;
+----+---------+-------+
| id | title | views |
+----+---------+-------+
| 1 | the-box | 200 |
| 2 | the-box | 100 |
| 3 | the-box | 10 |
| 5 | the-man | 45 |
| 7 | the-cup | 30 |
+----+---------+-------+
5 rows in set (0.00 sec)
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)
Say I have the following table
item_a_id, item_b_id, value
Where item_a_id and item_b_id are a composite primary key. In my example a,b and b,a are equivalent. Therefore I want to ensure that item_a_id < item_b_id. Obviously the application logic will enforce this but is there a way to ensure the database does too?
In a reasonably current version of MySql you can use triggers to emulate a check constraint that produces the desired behavior.
Well, in your case, you could use trigger to check values before insert/update and swap it to ensure item_a_id will always less than item_b_id.
Assuming the table name is item_links, you could try this:
DELIMITER |
CREATE TRIGGER ensure_a_b_before_insert BEFORE INSERT ON item_links
FOR EACH ROW
BEGIN
IF NEW.item_a_id > NEW.item_b_id THEN
SET #tmp = NEW.item_b_id;
SET NEW.item_b_id = NEW.item_a_id;
SET NEW.item_a_id = #tmp;
END IF;
END;
|
CREATE TRIGGER ensure_a_b_before_update BEFORE UPDATE ON item_links
FOR EACH ROW
BEGIN
IF NEW.item_a_id > NEW.item_b_id THEN
SET #tmp = NEW.item_b_id;
SET NEW.item_b_id = NEW.item_a_id;
SET NEW.item_a_id = #tmp;
END IF;
END;
|
DELIMITER ;
Here's what I got when I test inserting:
mysql> INSERT INTO `item_links` (`item_a_id`, `item_b_id`, `value`)
-> VALUES ('1', '2', 'a')
-> , ('3', '2', 'b')
-> , ('4', '1', 'c');
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM `item_links`;
+-----------+-----------+-------+
| item_a_id | item_b_id | value |
+-----------+-----------+-------+
| 1 | 2 | a |
| 2 | 3 | b |
| 1 | 4 | c |
+-----------+-----------+-------+
3 rows in set (0.00 sec)
Update works, too:
mysql> UPDATE `item_links`
-> SET `item_a_id` = 100, `item_b_id` = 20
-> WHERE `item_a_id` = 1 AND `item_b_id` = 2;
Query OK, 1 row affected (0.03 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> SELECT * FROM `item_links`;
+-----------+-----------+-------+
| item_a_id | item_b_id | value |
+-----------+-----------+-------+
| 20 | 100 | a |
| 2 | 3 | b |
| 1 | 4 | c |
+-----------+-----------+-------+
3 rows in set (0.00 sec)