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.
Related
So I have a table where a column that was given an auto_increment value accidentally got started form 300 instead of 1,2,3,4......i'm a beginner and i do not know how to change it back to 1,2,3,4......screenshot of table
how to change the 307, 308 to 1,2,3,4...?
I tried to update the table but that did not work.
Step-1) First take backup of your table data.
Step-2) Truncate the table by using the below SQL query.
TRUNCATE TABLE [Your_Table_Name];
Step-3) then again insert the into your table using backup data.
Alter table to drop the auto_increment, update, alter table to add the auto_increment
drop table if exists t;
create table t
( id int auto_increment primary key, val int);
insert into t values
(307,1),(308,1),(309,1),(310,1),(311,1);
alter table t
modify column id int;
#drop primary key;
show create table t;
update t
set id = id - 306;
alter table t
modify column id int auto_increment;
show create table t;
https://dbfiddle.uk/eBQh6cj8
With MySQL 8.0 you can use a window function to calculate the row numbers and then update the table:
mysql> select * from t;
+-----+------+
| id | val |
+-----+------+
| 307 | 1 |
| 308 | 1 |
| 309 | 1 |
| 310 | 1 |
| 311 | 1 |
+-----+------+
mysql> with cte as ( select id, row_number() over () as rownum from t )
-> update t join cte using (id) set id = rownum;
Query OK, 5 rows affected (0.00 sec)
Rows matched: 5 Changed: 5 Warnings: 0
mysql> select * from t;
+----+------+
| id | val |
+----+------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 5 | 1 |
+----+------+
Then make sure the next id won't be a high value:
mysql> alter table t auto_increment=1;
You can try to set the auto_increment to 1, MySQL will automatically advances that to the highest id value in the table, plus 1.
Be aware that this doesn't guarantee subsequent rows will use consecutive values. You can get non-consecutive values if:
You insert greater values explicitly, overriding the auto-increment.
You roll back transactions. Id values generated by auto-increment are not recycled if you roll back.
You delete rows.
Occasionally InnoDB will skip a number anyway. It does not guarantee consecutive values — it only guarantees unique values. You should not rely on the auto-increment to be the same as a row number.
Here is a one approach to your problem.
Please take note of the following points before proceeding:
Take backup of your table in-case things do not go as expected.
Below test case has been performed on MySQL 5.7 and MyISAM Engine.
Step1: Generating dummy test table as per your test case.
mysql> CREATE TABLE t (
-> `Id` int(11) NOT NULL AUTO_INCREMENT,
-> `product_id` int(11) DEFAULT 0,
-> PRIMARY KEY (`Id`)
-> ) ENGINE=MyISAM;
Query OK, 0 rows affected (0.03 sec)
-- Inserting dummy data
mysql> INSERT INTO t VALUES (300,1);
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO t VALUES (302,1);
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO t VALUES (305,1);
Query OK, 1 row affected (0.00 sec)
-- Checking auto_increment value
mysql> show create table t;
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t | CREATE TABLE `t` (
`Id` int(11) NOT NULL AUTO_INCREMENT,
`product_id` int(11) DEFAULT '0',
PRIMARY KEY (`Id`)
) ENGINE=MyISAM AUTO_INCREMENT=306 DEFAULT CHARSET=latin1 |
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> INSERT INTO t (product_id) VALUES (2);
Query OK, 1 row affected (0.01 sec)
-- Below is the resultant table for which we need Id starting from 1,2,3 and so on...
mysql> SELECT * FROM t;
+-----+------------+
| Id | product_id |
+-----+------------+
| 300 | 1 |
| 302 | 1 |
| 305 | 1 |
| 306 | 2 |
+-----+------------+
4 rows in set (0.00 sec)
Step2: Remove AUTO_INCREMENT for the column and set the Ids manually.
-- Remove AUTO_INCREMENT
mysql> ALTER TABLE t MODIFY COLUMN Id int(11) NOT NULL;
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0
-- Set the Id manually starting from 1
mysql> SET #i = 0;UPDATE t SET id = #i :=#i +1;
Query OK, 0 rows affected (0.00 sec)
Query OK, 5 rows affected (0.00 sec)
Rows matched: 5 Changed: 5 Warnings: 0
-- Below is the updated table with Id starting from 1,2,3 and so on...
mysql> SELECT * FROM t;
+----+------------+
| Id | product_id |
+----+------------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 2 |
+----+------------+
5 rows in set (0.00 sec)
Step3: Enable AUTO_INCREMENT again for future record insertions.
-- Enable AUTO_INCREMENT again for future record insertions.
mysql> ALTER TABLE t MODIFY COLUMN Id int(11) NOT NULL AUTO_INCREMENT;
Query OK, 5 rows affected (0.01 sec)
Records: 5 Duplicates: 0 Warnings: 0
-- Set the AUTO_INCREMENT value to continue from highest value of id in the table.
mysql> SELECT MAX(id+1) FROM t;
+-----------+
| MAX(id+1) |
+-----------+
| 6 |
+-----------+
1 row in set (0.00 sec)
mysql> ALTER TABLE t AUTO_INCREMENT=6;
Query OK, 5 rows affected (0.00 sec)
Records: 5 Duplicates: 0 Warnings: 0
-- Table is successfully modified and will have future records inserted with no gaps in Id's
mysql> INSERT INTO t (product_id) VALUES (5);
Query OK, 1 row affected (0.00 sec)
mysql> SELECT * FROM t;
+----+------------+
| Id | product_id |
+----+------------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 2 |
| 6 | 5 |
+----+------------+
6 rows in set (0.00 sec)
The DBCC CHECKIDENT management command is used to reset identity counter
DBCC CHECKIDENT (table_name [, { NORESEED | { RESEED [, new_reseed_value]}}])
[ WITH NO_INFOMSGS ]
EXample:
DBCC CHECKIDENT ('TestTable', RESEED, 0)
GO
many times we need to just reseed to next Id available
declare #max int
select #max=max([Id]) from [TestTable]
if #max IS NULL --check when max is returned as null
SET #max = 0
DBCC CHECKIDENT ('[TestTable]', RESEED, #max)
This will check the table and reset to the next ID.
You can get help from the link below:
Reset identity seed after deleting records in SQL Server
My mother says: the mountain that can be seen is not far away, don't stop trying
This is my SQL table, a huge table with around ~6kk rows.
CREATE TABLE `slots` (
`id` mediumint(8) UNSIGNED NOT NULL,
`uid` smallint(5) UNSIGNED NOT NULL,
`music_id` mediumint(8) UNSIGNED NOT NULL,
`finished` int(10) UNSIGNED NOT NULL DEFAULT '0',
`completed` tinyint(1) UNSIGNED NOT NULL DEFAULT '0',
`hidden` tinyint(1) UNSIGNED NOT NULL DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `slots`
ADD PRIMARY KEY (`id`),
ADD KEY `SEC_UNQ` (`uid`,`music_id`) USING BTREE;
ALTER TABLE `slots` MODIFY `id` mediumint(8) UNSIGNED NOT NULL AUTO_INCREMENT;
I'm looking frequently after uid, music_id and completed. For example:
SELECT `music_id` FROM `slots` WHERE `uid` = :uid AND `completed` = :completed;
and SELECT or UPDATE by uid and music_id
SELECT `music_id` FROM `slots` WHERE **`uid` = :uid AND `music_id` = :music_id**;
UPDATE `slots` SET xxx WHERE `uid` = :uid AND `music_id` = :music_id;
so the question is:
I have to create 3 indexes for all of the following columns: uid, music_id and completed or it's enough only for uid ?
..and which is better, single column index or multi-column indexes?
PS: I always have uid in WHERE statement
Thank you in advance
You can easy test it. A good index is always the best, also for small Type Boolean. It is realy easy to understand: If you have a large table mysql must read the hole table (FULL TABLE SCAN) to find a few row to update or delete. BUT MySQL can mostly only use one index per query. So a composite index is helpfull. and MySQL can also use them for single fields. Lets say you have a composite index on field (a,b,c) MySQL can use them in the WHERE Clause if only a , a and b or a and b and c , but not only on c or b.
Hier is a sample. there you can see how man rows MySQL must read and which index are used:
Drop Table and create a new
MariaDB []> DROP TABLE IF EXISTS mytable;
Query OK, 0 rows affected (0.29 sec)
MariaDB []>
MariaDB []> CREATE TABLE `mytable` (
-> `id` INT(11) UNSIGNED NOT NULL,
-> `a` INT(11) DEFAULT NULL,
-> `b` INT(11) DEFAULT NULL,
-> `c` INT(11) DEFAULT NULL,
-> PRIMARY KEY (`id`)
-> ) ENGINE=INNODB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.24 sec)
MariaDB []>
Insert 3000000 ROWS (only MariaDB)
MariaDB []> INSERT INTO mytable (id,a,b,c)
-> SELECT seq, (seq MOD 2), (seq MOD 3) , (seq MOD 4) FROM seq_0_to_3000000;
Query OK, 3000001 rows affected (15.66 sec)
Records: 3000001 Duplicates: 0 Warnings: 0
MariaDB []>
Test WHERE on field a - MySQL reads 2995634 rows
MariaDB []> EXPLAIN SELECT * FROM mytable WHERE a=1;
+------+-------------+---------+------+---------------+------+---------+------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+---------+------+---------------+------+---------+------+---------+-------------+
| 1 | SIMPLE | mytable | ALL | NULL | NULL | NULL | NULL | 2995634 | Using where |
+------+-------------+---------+------+---------------+------+---------+------+---------+-------------+
1 row in set (0.12 sec)
Add a Key on Field a
MariaDB []> ALTER TABLE mytable ADD KEY key_a (a);
Query OK, 0 rows affected (10.74 sec)
Records: 0 Duplicates: 0 Warnings: 0
Test the last query again (WHERE a) - MySQL reads only 1496635 rows
MariaDB []> EXPLAIN SELECT * FROM mytable WHERE a=1;
+------+-------------+---------+------+---------------+-------+---------+-------+---------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+---------+------+---------------+-------+---------+-------+---------+-------+
| 1 | SIMPLE | mytable | ref | key_a | key_a | 5 | const | 1496635 | |
+------+-------------+---------+------+---------------+-------+---------+-------+---------+-------+
1 row in set (0.00 sec)
Test with WHERE on fiels a and b - 1496635 rows
MariaDB []> EXPLAIN SELECT * FROM mytable WHERE a=1 AND b=2;
+------+-------------+---------+------+---------------+-------+---------+-------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+---------+------+---------------+-------+---------+-------+---------+-------------+
| 1 | SIMPLE | mytable | ref | key_a | key_a | 5 | const | 1496635 | Using where |
+------+-------------+---------+------+---------------+-------+---------+-------+---------+-------------+
1 row in set (0.00 sec)
Add key on field b
MariaDB []> ALTER TABLE mytable ADD KEY key_b (b);
Query OK, 0 rows affected (9.53 sec)
Records: 0 Duplicates: 0 Warnings: 0
Same test with a and b - same rows - only use key_a
MariaDB []> EXPLAIN SELECT * FROM mytable WHERE a=1 AND b=2;
+------+-------------+---------+------+---------------+-------+---------+-------+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+---------+------+---------------+-------+---------+-------+---------+-------------+
| 1 | SIMPLE | mytable | ref | key_a,key_b | key_a | 5 | const | 1496635 | Using where |
+------+-------------+---------+------+---------------+-------+---------+-------+---------+-------------+
1 row in set (0.00 sec)
Create index on a and b
MariaDB []> ALTER TABLE mytable ADD KEY key_ab (a,b);
Query OK, 0 rows affected (11.86 sec)
Records: 0 Duplicates: 0 Warnings: 0
Test with a and b - use key_ab and only 946702 rows read
MariaDB []> EXPLAIN SELECT * FROM mytable WHERE a=1 AND b=2;
+------+-------------+---------+------+--------------------+--------+---------+-------------+--------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+---------+------+--------------------+--------+---------+-------------+--------+-------+
| 1 | SIMPLE | mytable | ref | key_a,key_b,key_ab | key_ab | 10 | const,const | 946702 | |
+------+-------------+---------+------+--------------------+--------+---------+-------------+--------+-------+
1 row in set (0.01 sec)
Test with field a,b and c -- kay_ab used and 946702 rows read
MariaDB []> EXPLAIN SELECT * FROM mytable WHERE a=1 AND b=2 AND c=3;
+------+-------------+---------+------+--------------------+--------+---------+-------------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+---------+------+--------------------+--------+---------+-------------+--------+-------------+
| 1 | SIMPLE | mytable | ref | key_a,key_b,key_ab | key_ab | 10 | const,const | 946702 | Using where |
+------+-------------+---------+------+--------------------+--------+---------+-------------+--------+-------------+
1 row in set (0.00 sec)
Add Key on field a,b,c
MariaDB []> ALTER TABLE mytable ADD KEY key_abc (a,b,c);
Query OK, 0 rows affected (18.64 sec)
Records: 0 Duplicates: 0 Warnings: 0
Test with field a,b,c - key_abc used - and 511082 rows read
MariaDB []> EXPLAIN SELECT * FROM mytable WHERE a=1 AND b=2 AND c=3;
+------+-------------+---------+------+----------------------------+---------+---------+-------------------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+---------+------+----------------------------+---------+---------+-------------------+--------+-------------+
| 1 | SIMPLE | mytable | ref | key_a,key_b,key_ab,key_abc | key_abc | 15 | const,const,const | 511082 | Using index |
+------+-------------+---------+------+----------------------------+---------+---------+-------------------+--------+-------------+
1 row in set (0.01 sec)
So the most effect is on composite index, but it also depends on your used querys.
I have a MySQL database with tables t1 and t2. One of the columns in table t1 has a foreign key to t2.
Need to allow the foreign key column to accept null values. There is already some important data so recreating the table is not an option.
Tried the usual alter table commands but it showed syntax error.
Is there a way to go around it without affecting the database?
This is what I tried:
ALTER TABLE t1 MODIFY fk_column_id NULL;
The missing part is the type definition in the modify statement. With MODIFY you redefine the column, thus you need to give the new type as well. But in case you only modify that it can be null, no data will be lost.
Create referenced table and filling it :
mysql> -- Creating referenced table
mysql> create table `tUser` (
-> `id` int auto_increment not null,
-> `name` varchar(16),
-> primary key (`id`)
-> );
Query OK, 0 rows affected (0.07 sec)
mysql> -- Filling and checking referenced table
mysql> insert into `tUser` (`name`) values ("Jane"), ("John");
Query OK, 2 rows affected (0.04 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from `tUser`;
+----+------+
| id | name |
+----+------+
| 1 | Jane |
| 2 | John |
+----+------+
2 rows in set (0.07 sec)
mysql> -- Creating referencing table
mysql> create table `tHoliday` (
-> `id` int auto_increment not null,
-> `userId` int,
-> `date` date,
-> primary key (`id`),
-> foreign key (`userId`) references `tUser` (`id`)
-> );
Query OK, 0 rows affected (0.14 sec)
mysql> -- Filling and checking referencing table
mysql> insert into `tHoliday` (`userId`, `date`) values
-> (1, "2014-11-10"),
-> (1, "2014-11-13"),
-> (2, "2014-10-10"),
-> (2, "2014-12-10");
Query OK, 4 rows affected (0.08 sec)
Records: 4 Duplicates: 0 Warnings: 0
mysql> select * from `tHoliday`;
+----+--------+------------+
| id | userId | date |
+----+--------+------------+
| 1 | 1 | 2014-11-10 |
| 2 | 1 | 2014-11-13 |
| 3 | 2 | 2014-10-10 |
| 4 | 2 | 2014-12-10 |
+----+--------+------------+
4 rows in set (0.05 sec)
mysql> -- Updating foreign key column to allow NULL
mysql> alter table `tHoliday` modify `userId` int null;
Query OK, 0 rows affected (0.08 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> -- Inserting line without foreign key
mysql> insert into `tHoliday` (`date`) values ("2014-11-15");
Query OK, 1 row affected (0.06 sec)
mysql> select * from `tHoliday`;
+----+--------+------------+
| id | userId | date |
+----+--------+------------+
| 1 | 1 | 2014-11-10 |
| 2 | 1 | 2014-11-13 |
| 3 | 2 | 2014-10-10 |
| 4 | 2 | 2014-12-10 |
| 5 | NULL | 2014-11-15 |
+----+--------+------------+
5 rows in set (0.03 sec)
Lets say, I have the following mysql table :
CREATE TABLE player (
id int(9) unsigned NOT NULL DEFAULT 0 ,
score MEDIUMINT(8) unsigned NOT NULL DEFAULT 0,
signupdate DATE NOT NULL,
lastupdate DATE NOT NULL
) DEFAULT CHARACTER SET utf8 ENGINE=InnoDB;
Currently I have a primary key on id column. lastupdate column is updated everyday, and if its not updated it means that the player has deleted the account, this means the cardianlity of this column is very low.
Also there is a relational table matches with feilds matchid , playerid and matchdate
Most my queries are like
SELECT id,score,signupdate FROM player
JOIN matches ON matches.playerid = player.id
WHERE lastupdate = '{today}'
So 3 cases for indices come to my mind
PRIMARY KEY on id
PRIMARY KEY on id and an INDEX on lastupdate
PRIMARY KEY on (id,lastupdate)
Which one would be the best??
You should have an index on table matches column playerid and an index on table player column lastupdate.
As a very rough rule of thumb is that what you use in the WHERE and JOIN clause should have an index if it is a large table.
To get more information what index was used you can use the explain statement. Here is what it looks like. Notice the explain statement at the very end:
mysql> CREATE TABLE player (
-> id int(9) unsigned NOT NULL DEFAULT 0 ,
-> score MEDIUMINT(8) unsigned NOT NULL DEFAULT 0,
-> signupdate DATE NOT NULL,
-> lastupdate DATE NOT NULL
-> ) DEFAULT CHARACTER SET utf8 ENGINE=InnoDB;
Query OK, 0 rows affected (0.12 sec)
mysql>
mysql> CREATE TABLE matches (
-> matchid int(9) unsigned NOT NULL DEFAULT 0 ,
-> playerid int(9) unsigned NOT NULL DEFAULT 0 ,
-> matchdate DATE NOT NULL
-> ) DEFAULT CHARACTER SET utf8 ENGINE=InnoDB;
Query OK, 0 rows affected (0.22 sec)
mysql>
mysql> SELECT id,score,signupdate FROM player
-> JOIN matches ON matches.playerid = player.id
-> WHERE lastupdate = now()
-> ;
Empty set (0.00 sec)
mysql>
mysql> explain
-> SELECT id,score,signupdate FROM player
-> JOIN matches ON matches.playerid = player.id
-> WHERE lastupdate = '{today}'
-> ;
+----+-------------+---------+------+---------------+------+---------+------+------+--------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+------+---------------+------+---------+------+------+--------------------------------+
| 1 | SIMPLE | player | ALL | NULL | NULL | NULL | NULL | 1 | Using where |
| 1 | SIMPLE | matches | ALL | NULL | NULL | NULL | NULL | 1 | Using where; Using join buffer |
+----+-------------+---------+------+---------------+------+---------+------+------+--------------------------------+
2 rows in set, 2 warnings (0.00 sec)
mysql> CREATE INDEX player_idx_1
-> ON player (id)
-> ;
Query OK, 0 rows affected (0.15 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> CREATE INDEX matches_idx_1
-> ON matches (playerid)
-> ;
Query OK, 0 rows affected (0.16 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql>
mysql> explain SELECT id,score,signupdate FROM player JOIN matches ON matches.playerid = player.id WHERE lastupdate = '{today}';
+----+-------------+---------+------+---------------+---------------+---------+-----------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+------+---------------+---------------+---------+-----------------+------+-------------+
| 1 | SIMPLE | player | ALL | player_idx_1 | NULL | NULL | NULL | 1 | Using where |
| 1 | SIMPLE | matches | ref | matches_idx_1 | matches_idx_1 | 4 | mysql.player.id | 1 | Using index |
+----+-------------+---------+------+---------------+---------------+---------+-----------------+------+-------------+
2 rows in set, 2 warnings (0.00 sec)
mysql>
add the index for lastupdate
mysql> CREATE INDEX player_idx_2
-> ON player (lastupdate)
-> ;
Query OK, 0 rows affected (0.13 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> explain
-> SELECT id,score,signupdate FROM player
-> JOIN matches ON matches.playerid = player.id
-> WHERE lastupdate = curdate()
-> ;
+----+-------------+---------+------+---------------+---------------+---------+-----------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+------+---------------+---------------+---------+-----------------+------+-------------+
| 1 | SIMPLE | player | ref | player_idx_2 | player_idx_2 | 3 | const | 1 | |
| 1 | SIMPLE | matches | ref | matches_idx_1 | matches_idx_1 | 4 | mysql.player.id | 1 | Using index |
+----+-------------+---------+------+---------------+---------------+---------+-----------------+------+-------------+
2 rows in set (0.00 sec)
mysql>
Definitely number 2. Primary key is used to uniquely identify a row, and the id attribute is enough for that, so you don't need option 3. And since most of your queries look like what you said, then having an index on lastupdate will definitely be useful to speed your queries.
Maybe I didnt explain well.
these are the tables:
Table 1
CREATE TABLE `notforeverdata` (
`id` int(11) NOT NULL auto_increment,
`num` varchar(255) default NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `notforeverdata` VALUES (1, '4,3,0,5');
Table 2
CREATE TABLE `notforeverdata2` (
`id2` int(11) NOT NULL auto_increment,
`num2` varchar(255) default NULL,
PRIMARY KEY (`id2`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `notforeverdata2` VALUES (1, '2,5,6,8');
What I need to do is to check is if any of the numbers of the column "num" in notforeverdata exists in the column num2 of notforeverdata2. in this case the number "5" in the col num of notforeverdata exists in notforeverdata2.
Any Idea?
Thanks
For this example I will create a table, load it with random numbers, and search for each number in a provided list. Here is the catch: the provided list must start with and end with a comma.
From your question, I will use ',3,2,5,'
Here is the example
use test
drop table if exists notforeverdata;
create table notforeverdata
(
id int not null auto_increment,
num VARCHAR(255),
PRIMARY KEY (id)
);
insert into notforeverdata (num) values
(2),(7),(9),(11),(13),(15),(4),(3),(90),(97),(18),(5),(17);
SELECT * FROM notforeverdata;
SELECT * FROM notforeverdata WHERE LOCATE(CONCAT(',',num,','),(',3,2,5,'));
I actually ran it in MySQl 5.5.12 on my desktop. Here is the result:
mysql> use test
drop table if exists notforeverdata;
Database changed
mysql> drop table if exists notforeverdata;
Query OK, 0 rows affected (0.03 sec)
mysql> create table notforeverdata
-> (
-> id int not null auto_increment,
-> num VARCHAR(255),
-> PRIMARY KEY (id)
-> );
Query OK, 0 rows affected (0.12 sec)
mysql> insert into notforeverdata (num) values
-> (2),(7),(9),(11),(13),(15),(4),(3),(90),(97),(18),(5),(17);
Query OK, 13 rows affected (0.06 sec)
Records: 13 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM notforeverdata;
+----+------+
| id | num |
+----+------+
| 1 | 2 |
| 2 | 7 |
| 3 | 9 |
| 4 | 11 |
| 5 | 13 |
| 6 | 15 |
| 7 | 4 |
| 8 | 3 |
| 9 | 90 |
| 10 | 97 |
| 11 | 18 |
| 12 | 5 |
| 13 | 17 |
+----+------+
13 rows in set (0.00 sec)
mysql> SELECT * FROM notforeverdata WHERE LOCATE(CONCAT(',',num,','),(',3,2,5,'));
+----+------+
| id | num |
+----+------+
| 1 | 2 |
| 8 | 3 |
| 12 | 5 |
+----+------+
3 rows in set (0.00 sec)
mysql>
This will, of course, perform a full table scan. Notwithstanding, this works.
Give it a Try !!!