So I've been having a problem and either I am forgetting something fundamental or I found a bug. I've narrowed it down to this:
My table:
CREATE TABLE `tbl` (
`id` int(11) NOT NULL,
`timestmp` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Simple. My query:
insert into tbl (id, timestmp) values (1, 1)
on duplicate key update timestmp = if(values(timestmp) > timestmp,
values(timestmp), timestmp)
Table will contain
(1, 1)
Repeat the query with
values (1, 2)
Table will contain
(1, 2)
Repeat the query with
values (1, 1)
Table will still contain
(1, 2)
Great. Just what we want. Instead with this table:
CREATE TABLE `tbl` (
`id` int(11) NOT NULL,
`timestmp` bigint(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Let's do the same queries:
insert into tbl (id, timestmp) values (1, 1)
on duplicate key update timestmp = if(values(timestmp) > timestmp,
values(timestmp), timestmp)
Table contains:
(1, 1)
Query with:
values (1, 2)
Table contains:
(1, 1)
What? Let's try
values (1, -1)
Table contains:
(1, -1)
JKLFSD!!!!! What's going on? Is this supposed to happen? Am I completely misinterpreting something? Do I need a special function for bigint comparison?
Related
I am new to mysql
I have two Tables in my database.
id_details_table
CREATE TABLE `id_details_table` (
`ID` int(11) NOT NULL,
`CNIC` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
sample record
INSERT INTO `id_details_table` (`ID`, `CNIC`) VALUES
(1, '3230328119795'),
(2, '4200004873681'),
(3, '4230188867895'),
(4, '3740566124323'),
(5, '4220191179125');
mobiles_sim_details
> CREATE TABLE `mobiles_sim_details` (
`Mobile` double DEFAULT NULL,
> `CNIC` varchar(255) DEFAULT NULL, `id_cnic` int(11) DEFAULT NULL )
> ENGINE=InnoDB DEFAULT CHARSET=latin1;
sample Record for table
INSERT INTO `mobiles_sim_details` (`Mobile`, `CNIC`, `id_cnic`) VALUES
(3000651082, '3230328119795', 0),
(3040877459, '4200004873681', 0),
(3013329415, '4230188867895', 0),
(3028590340, '3740566124323', 0),
(3000720166, '4220191179125', 0);
2 columns CNIC are present in both tables
Now What I want is, where there is 0 in the 2nd table I want it to be auto filled with the relevant ID from table 1 based on the data of CNIC from 2nd table.
I have tried this query but it didn't worked
UPDATE `mobiles_sim_details` SET `id_cnic`='[value-3]' WHERE (SELECT id FROM id_details_table WHERE CNIC = mobiles_sim_details.CNIC);
How can i Acheive this ?
UPDATE mobiles_sim_details t1
JOIN id_details_table t2 USING (CNIC)
SET t1.id_cnic = t2.id
I got a little problem with my recursive query.
I got a database of menu of a bar.
We got: Category, each category got sub-categories and each-subcategories got multiple items.
The database is this one and the query is linked inside:
CREATE TABLE category (
id int(10) unsigned NOT NULL AUTO_INCREMENT,
title varchar(255) NOT NULL,
parent_id int(10) unsigned DEFAULT NULL,
PRIMARY KEY (id),
FOREIGN KEY (parent_id) REFERENCES category (id)
ON DELETE CASCADE ON UPDATE CASCADE
);
CREATE TABLE `items` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`cat_id` int unsigned DEFAULT NULL,
`parent_id` int unsigned DEFAULT NULL,
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
PRIMARY KEY (`id`),
KEY `cat_id` (`cat_id`),
KEY `sub_id` (`parent_id`),
CONSTRAINT `cat_id` FOREIGN KEY (`cat_id`) REFERENCES `category` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `sub_id` FOREIGN KEY (`parent_id`) REFERENCES `category` (`parent_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
BEGIN;
INSERT INTO `category` VALUES (1, 'Colazione', NULL);
INSERT INTO `category` VALUES (2, 'Pranzo', NULL);
INSERT INTO `category` VALUES (3, 'Primi piatti', 2);
INSERT INTO `category` VALUES (4, 'Second dish', 2);
INSERT INTO `category` VALUES (5, 'Other things for lunch', 2);
COMMIT;
-- ----------------------------
-- Records of items
-- ----------------------------
BEGIN;
INSERT INTO `items` VALUES (1, 1, NULL, 'Cornetto');
INSERT INTO `items` VALUES (2, 3, 2, 'Pasta al sugo 1');
INSERT INTO `items` VALUES (3, 3, 2, 'Pasta al sugo 2');
INSERT INTO `items` VALUES (4, 3, 2, 'Pasta al sugo 3');
INSERT INTO `items` VALUES (5, 3, 2, 'Pasta al sugo 1 X');
INSERT INTO `items` VALUES (6, 3, 2, 'Pasta al sugo 2 X');
INSERT INTO `items` VALUES (7, 4, 2, 'Pasta al sugo 3 X');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
Query:
with combine_trees as (
with make_tree as (
WITH RECURSIVE category_path AS
(
SELECT id, title, parent_id
FROM category
WHERE parent_id IS NULL
UNION ALL
SELECT c.id, c.title, c.parent_id
FROM category_path AS cp JOIN category AS c
ON cp.id = c.parent_id
)
SELECT cp.title, cp.id,
if(cp.id = category.id,
json_arrayagg(json_object('item_name', it.name)),
json_object(cp.title, json_object('items',json_arrayagg(json_array(json_object('item_name', it.name))))))
as tree
FROM category_path cp
INNER JOIN items it ON it.cat_id = cp.id
join category on category.id = ifnull(cp.parent_id, cp.id)
group by cp.title, cp.id, category.id
)
select json_arrayagg(json_object(title, json_array('items', tree))) output_json from make_tree group by id
)
select json_object('menu',group_concat(output_json)) as output from combine_trees;
https://sqlize.online/
The problem is that its not printing the result as JSON but its printing it formatted in one-string. How can we transform it in a JSON without that all the output is an unique string?
In your last line,
select json_object('menu',group_concat(output_json)) as output from combine_trees
you cannot use group_concat to combine the json arrays you get from the 2nd to last line (e.g. select json_arrayagg(...) output_json from make_tree group by id).
The arrays you get there each look like [...], and group_concat will give you [...], [...]. This is not a valid json array (which would need additional brackets around it, e.g. [[...],[...]]), but a string, and creating a json object from it will give you, well, that string as the value.
To combine your json arrays, you can use (as you did before) json_arrayagg instead of group_concat, e.g.
select json_object('menu',json_arrayagg(output_json)) as output from combine_trees
I have a MySQL table running on AWS RDS with structure like the following:
CREATE TABLE `my_table` (
`col1` int(11) NOT NULL,
`col2` int(11) NOT NULL DEFAULT '0',
`f_name` varchar(45) DEFAULT NULL,
`l_name` varchar(45) DEFAULT NULL,
PRIMARY KEY (`col1`,`col2`),
KEY `idx_col1` (`col1`),
KEY `idx_col2` (`col2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
The query
SELECT * FROM my_table WHERE col1=111 AND col2=222;
returns 0 row.
But when I run an insert query
INSERT INTO my_table
(col1, col2, f_name, l_name)
VALUES (111, 222, 'John', 'Doe')
I got an error saying
Duplicate entry '111-222' for key 'PRIMARY'.
Why does this happen? The table doesn't contain a row with col1=111 and col2=222.
There's already a row with values col1=111, col2=111, f_name='John', and l_name='Doe'. But I don't think this would cause a duplicate entry error.
=========================== EDIT ======================================
There's a trigger that generates the duplicate error. Here's the script to reproduce the error.
# Initialize the tables
CREATE TABLE `my_table` (
`col1` int(11) NOT NULL,
`col2` int(11) NOT NULL DEFAULT '0',
`f_name` varchar(45) DEFAULT NULL,
`l_name` varchar(45) DEFAULT NULL,
PRIMARY KEY (`col1`,`col2`),
KEY `idx_col1` (`col1`),
KEY `idx_col2` (`col2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `triggered_table` (
`col1` int(11) NOT NULL,
`col2` int(11) NOT NULL DEFAULT '0',
`update_date` bigint(20) DEFAULT NULL,
PRIMARY KEY (`col1`,`col2`),
KEY `idx_col1` (`col1`),
KEY `idx_col2` (`col2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
# Insert the data that cause duplicate error
INSERT INTO triggered_table (col1, col2) VALUES (111, 222);
# Create the trigger
DELIMITER $$
CREATE TRIGGER weird_trigger AFTER INSERT
ON my_table
FOR EACH ROW
BEGIN
INSERT INTO triggered_table
(col1, col2)
VALUES (NEW.col1, NEW.col2);
END$$
DELIMITER ;
# Create the duplicate error
INSERT INTO my_table
(col1, col2, f_name, l_name)
VALUES (111, 222, 'John', 'Doe');
I really don't understand why the developers created the triggered_table table. Why didn't they put update_date column to my_table?
This is so weird.
All you have to do is:
Truncate your table then run (Assuming that you have only a test data but if not, you have to do some backup first)
INSERT INTO my_table
(col1, col2, f_name, l_name)
VALUES (111, 222, 'John', 'Doe')
Now if the error still exists, this is a pretty much problem.
Your error seems like you concatinated col1 and col2 as your primary key ('111-222')
You can try
select * from yourTable where FieldPrimary = '111-222' if it is already exists
The duplicate key error does not come from the my_table table but from the triggered_table table instead. When you add a row in triggered_table for the key (111, 222) and then add a new row in the my_table table (with the same key), your trigger will also try to add a new row with the key (111, 222) in your triggered_table. However there is already such a key in use and you will get the duplicate key error.
Depending on what you want to do with the my_table and triggered_table tables, you might want to change the trigger to use REPLACE INTO instead of INSERT INTO. Or you run a check with SELECT first to see if you need to add a new row or not. After that you can run an UPDATE query to change the value of update_date. But to answer your question, the duplicate key error comes from the duplicate key in the triggered_table table.
I have got 2 MySQL tables that have (InnoDB) foreign keys going into each other. For example,
-- Adminer 4.2.3 MySQL dump
SET NAMES utf8;
SET time_zone = '+00:00';
SET foreign_key_checks = 0;
SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';
DROP TABLE IF EXISTS `a`;
CREATE TABLE `a` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`null_or_b_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `null_or_b_id` (`null_or_b_id`),
CONSTRAINT `a_ibfk_1` FOREIGN KEY (`null_or_b_id`) REFERENCES `b` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `a` (`id`, `null_or_b_id`) VALUES
(1, NULL),
(2, 2),
(4, 3),
(3, 4),
(5, 5),
(6, 6),
(7, 7),
(8, 8);
DROP TABLE IF EXISTS `b`;
CREATE TABLE `b` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`null_or_a_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `null_or_a_id` (`null_or_a_id`),
CONSTRAINT `b_ibfk_1` FOREIGN KEY (`null_or_a_id`) REFERENCES `a` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `b` (`id`, `null_or_a_id`) VALUES
(1, NULL),
(8, NULL),
(2, 2),
(4, 3),
(3, 4),
(5, 6),
(6, 7),
(7, 8);
-- 2016-02-03 06:45:07
What I want to do is delete the records with the ids 1, 2, 3 and 5 from a and delete any records that need to deleted in both a and b due to the foreign key constraints. I have tried:
delete from a where a.id in (1,2,3,5);
delete a,b from a left join b on b.null_or_a_id = a.id where a.id in (1,2,3,5);
Both the above give the same error:
Error in query (1451): Cannot delete or update a parent row: a foreign key constraint fails (`test/multi_delete_with_references`.`b`, CONSTRAINT `b_ibfk_1` FOREIGN KEY (`null_or_a_id`) REFERENCES `a` (`id`))
I get the same error even if I remove the foreign key constraint on b defined in a.
Things I can't do:
Disable foreign key checks: because both the tables are also referenced by other tables and I don't want those tables to have orphaned rows, if this delete is going to cause such orphaned rows I need this delete to fail.
Delete from the child table first: because as you can see in the case of rows with id 2 in both tables, they reference each other so one can't be deleted without the other, also in the case of rows with ids 3 and 4 in both tables, they form a self-referencing chain.
I have looked at the answer here and it won't work for me because both the tables reference each other.
Is there a way out of this?
BTW, I also tried to generate complex, nested queries dynamically but it ended up being endless:
delete from a where id in (1,2,3,5);
delete from b where null_or_a_id is not null and null_or_a_id in (select * from (select id from a where id in (1,2,3,5)) x);
delete from a where null_or_b_id is not null and null_or_b_id in (select * from (select id from b where null_or_a_id is not null and null_or_a_id in (select * from (select id from a where id in (1,2,3,5)) x)) x);
delete from b where null_or_a_id is not null and null_or_a_id in (select * from (select id from a where null_or_b_id is not null and null_or_b_id in (select * from (select id from b where null_or_a_id is not null and null_or_a_id in (select * from (select id from a where id in (1,2,3,5)) x)) x)) x)
...
Your problem is quite similar to this one and the same solution applies: first remove the references by setting to NULL the referencing columns in those rows that you intend to delete. Then delete.
Sorry for long POST:
Is it possible that I can call a Stored Procedures from another
Stored procedure in MySQL.
For example:
I have two tables (test and testcomp):
With the structures below:
-- Table structure for table test
CREATE TABLE IF NOT EXISTS `test` (
`t_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`t_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
and
-- Table structure for table testcomp
CREATE TABLE IF NOT EXISTS `testcomp` (
`c_id` int(11) NOT NULL AUTO_INCREMENT,
`t_id` int(4) NOT NULL,
`place` varchar(255) NOT NULL,
PRIMARY KEY (`c_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
Now I populated test table with:
INSERT INTO `test` (`t_id`, `name`) VALUES
(1, 'foo'),
(2, 'bar'),
(3, 'ma');
and table testcomp with:
INSERT INTO `testcomp` (`c_id`, `t_id`, `place`) VALUES
(1, 1, 'gugs'),
(2, 2, 'nyanga'),
(3, 1, 'gugs'),
(4, 3, 'skom');
Now if I have 2 Procedures:
First QryTestComp:
SELECT t_id, place FROM TestComp
The one above works as the just querying normal table:
But the Second One QryTestPlac, which calls the above procedure:
SELECT * FROM Test INNER JOIN QryTestComp ON Test.t_id = QryTestComp.t_id
Comes with a error:
It says Error: 1146 (42S01): Table 'mydb.qrytestcomp' doesn't exist.
It not a table but a procedure.
Pointer, please.
Regards,
--Jongi
you can't join onto a stored procedure, perhaps using views might be more suitable ?