MySQL insert skipped IDs - mysql

I have a mysql table which has two columns, id and value.
id(auto_increment primary key)
value(varchar 255)
insert into table columns(`id`,`value`)VALUES(,'something1');
insert into table columns(`id`,`value`)VALUES(,'something2');
output
+----+---------------+
| id | value |
+----+---------------+
| 1 | something1 |
| 2 | something2 |
+----+---------------+
Now Inserting one value again
insert into table columns(`id`,`value`)VALUES(8,'something8');
Updated Table
+----+---------------+
| id | value |
+----+---------------+
| 1 | something1 |
| 2 | something2 |
| 8 | something8 |
+----+---------------+
Now I am inserting one value again
insert into table columns(`id`,`value`)VALUES(,'something');
Final Output
+----+---------------+
| id | value |
+----+---------------+
| 1 | something1 |
| 2 | something2 |
| 8 | something8 |
| 9 | something |
+----+---------------+
But I want the final output like this
+----+---------------+
| id | value |
+----+---------------+
| 1 | something1 |
| 2 | something2 |
| 8 | something8 |
| 3 | something |
+----+---------------+
Now id is 3 and further insertion will create id 4,5,6,7,9 and so on.
Is there any way to get achieve this ?

I know it is old post but mybie it will help someone :)
I am afraid it cannot be done automatically, however, I solved it to my client, maybe some of you could find it useful:
DECLARE FirstEmptyId int;
SELECT l.id +1 AS
START
FROM TableName AS l
LEFT OUTER JOIN TableName AS r ON l.id +1 = r.id
WHERE r.id IS NULL
LIMIT 1 INTO FirstEmptyId;
Insert Into TableName (Id..) Values (FirstEmptyId...)
STILL, YOU HAVE TO MIND THAT IT IS NOT ADVISABLE TO INSERT ID VALUE OTHER WAY THAN BY AUTOINCREMENT IT AND THERE IS A REASON FOR THAT :)
Consider creating the second column just for performance purposes.
Good luck fellow coders!

Related

How to write a join query for many to many relationship? for dictionary project

I have working on database for dictionary project. I have to store a word and meaning with -- many to many -- relationship.
Below I have mentioned the sample with my table structure. I hope the table structure is right, but I don't know how to select all meanings for single word while user searching.
And also I have to write a query to select all word linked to a single meaning.
And also I have to write a query to select all meaning linked to a single word.
word_table
+----+------+
| id | word |
+----+------+
| 1 | A |
| 2 | B |
| 3 | C |
+----+------+
meaning_table
+----+--------+
| id | meaning|
+----+--------+
| 1 | X |
| 2 | Y |
| 3 | Z |
+----+--------+
word_meaning_table
+---------+-----------+
| word_id | meaning_id|
+---------+-----------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 3 |
| 3 | 2 |
| 3 | 3 |
+---------+-----------+
Expected output should be like this.
If user searching for a word "A" in word table the result should be
Result for word "A"
+----+----------+
| word| meaning |
+----+----------+
| A | X |
| A | Y |
| A | Z |
+----+----------+
I don't know how to write a join query for this scenario.
SELECT wt.word, mt.meaning
FROM word_table wt
INNER JOIN word_meaning_table wmt
ON wt.id = wmt.word_id
INNER JOIN meaning_table mt
ON wmt.meaning_id = mt.id
WHERE wt.word = 'A'
Follow the link below for a working demo:
SQLFiddle
Try
select word, meaning
from word_table
join meaning_table on word_table.id=meaning_table.id;

Mysql->autoincrementing related to an other field

I am stuck on a project design. One of the table has 1-M relation with users table. So it has a foreign key. Same field is also primary key.
Table as follows
Itemid:
Primarykey
Autoincrement
Useriditem:
Primarykey
Foreign key of id in users table
Itemname:
Not null
Values:
-----------------------------------------
| **ITEMID** | **USERID** | ITEMNAME |
-----------------------------------------
| 1 | 1 | fooooooo |
-----------------------------------------
| 2 | 1 | tinytext |
-----------------------------------------
| 3 | 1 | MediumText |
-----------------------------------------
| 4 | 2 | LARGEtext |
-----------------------------------------
| 5 | 2 | HUGETEXT |
-----------------------------------------
| 6 | 1 | BLOOOOOB |
-----------------------------------------
| 7 | 3 | 001010101 |
-----------------------------------------
This is the result of the current design. What i am wondering is that a way to make auto increment for each user separately.
Something like "Autoincrement item id GROUP BY user id"
-----------------------------------------
| **ITEMID** | **USERID** | ITEMNAME |
-----------------------------------------
| 1 | 1 | fooooooo |
-----------------------------------------
| 2 | 1 | tinytext |
-----------------------------------------
| 3 | 1 | MediumText |
-----------------------------------------
| 1 | 2 | LARGEtext |
-----------------------------------------
| 2 | 2 | HUGETEXT |
-----------------------------------------
| 4 | 1 | BLOOOOOB |
-----------------------------------------
| 1 | 3 | 001010101 |
-----------------------------------------
Is there a way to do this using mysql?
You want something like this:
Demo
CREATE TRIGGER item_id_auto_inc
BEFORE INSERT ON items
FOR EACH ROW
BEGIN
SET NEW.item_id := (SELECT CASE WHEN ISNULL(MAX(item_id)) THEN 0 ELSE MAX(item_id) END +1 FROM items WHERE user_id=NEW.user_id);
END
//
I dont know what happens when multiple users execute queries but i think i managed to narrow down the algorithm.
how to "insert into table (col1, col2) values (select max(id) from table2, select id from table3); "?
INSERT INTO table VALUES (
(SELECT (MAX(itemid)+1)
FROM table
WHERE userid = 'theid') , 'theid' , 'foo1');
Can this solve the simultaneous execution by multiple user problem.
The safer way to do this is taking into account that your application can get hit by more than 1 user at any given time
START TRANSACTION;
Insert into table A
Select Last inserted id from table A using Last_Insert_ID()
Update table B
COMMIT;
At least you are guaranteed to get this last inserted id from table A into table B.

Regex vs Join Performance Mysql

I am at hesitation what type should I use. There will be really a lot of IDs and Groups, normally they learned me to do multiple tables but the second version with regexp seems great and less redundant. I would love to know with of those two version is better.
+----+ +----+-------+
| ID | | ID | Group |
+----+ +----+-------+
| 1 | | 1 | gr1 |
| 1 | | 1 | gr2 |
| 2 | | 2 | gr2 |
| 2 | | 2 | gr3 |
+----+ +----+-------+
SELECT * FROM tbl1 join tbl2 USING(ID) WHERE Group="gr1";
+----+-----------+
| ID | Group |
+----+-----------+
| 1 | gr1,gr2 |
| 2 | gr2,gr3 |
+----+-----------+
SELECT * FROM tbl1 WHERE Group REGEXP '(^|,)gr1($|,)';
As long as you have small tables, you can use both at your discretion.
If you expect the table to grow, you really need to opt for the first choice. The reason behind is that a query with where regexp will not make use of the indexes. And as you know, indexes are the key to fast queries.
If you're using InnoDB, define a foreign key that links the two tables.
You say, you find the first choice having more redundance than the second one. It doesn't seem to me. Thinking about this your sketch might show that there is a misunderstanding. It should rather look like this, i.e. there is only one row per id in table 1, and therefore, there is no redundance.
Tbl1 Tbl2
+----+----------+ +----+-------+
| ID |Other cols| | ID | Group |
+----+----------+ +----+-------+
| 1 | | | 1 | gr1 |
| 2 | | | 1 | gr2 |
+----+----------+ | 2 | gr2 |
| 2 | gr3 |
+----+-------+

MySQL copy column from different tables, insert at top of table

I'm trying to merge a couple tables together to consolidate the data, but when I try to insert a column from one table to the other, the query I'm using inserts the records after the last currently existing record in the table. There are a ton of questions about duplicating columns, but they all seem to be starting with an empty table.
INSERT INTO newTable( newColumn ) SELECT oldColumn FROM oldTable
How do I modify this query to insert the rows at the beginning of the table instead of the end?
Visual representation of what is happening (left) vs. what I want to happen (right):
+--------+--------+------------+ +--------+--------+------------+
| ID | Column | newColumn | | ID | Column | newColumn |
+--------+--------+------------+ +--------+--------+------------+
| 1 | 12345 | | | 1 | 12345 | 12345 |
| 2 | 12345 | | | 2 | 12345 | 12345 |
| 3 | 12345 | | | 3 | 12345 | 12345 |
| 4 | | 12345 | +--------+--------+------------+
| 5 | | 12345 |
| 6 | | 12345 |
+--------+--------+------------+
As mentioned in the comments you need an UPDATE statement not an INSERT statement:
UPDATE newTable
JOIN oldTable
ON newTable.id = oldTable.id
SET newcolumn = oldcolumn;
A tested example may be seen here: http://sqlfiddle.com/#!2/77724/1

mySQL query; Ignore specific ID values

I need to make a mySQL query and am not sure what the format should be.
Here is the situation, I have a table with the fields - id, name, type
I would use a query similar to the following to get results from the table:
SELECT * FROM table WHERE type='1'
However, I have a list of ID's from another query. These are items that should be excluded from the results.
I'm sure the answer is simple, but I don't know enough about mySQL queries to find the answer.
A simple NOT IN will be what you want :) It lets you send a list of values and makes sure that its not in them :)
SELECT * FROM table WHERE ID NOT IN (1,2,3)
You could also do it with a subquery with something like:
SELECT id FROM table WHERE ID NOT IN (SELECT id FROM table2 WHERE type = 1)
You can use NOT IN query like this:
SELECT * FROM `table` WHERE `type`=1 WHERE `id` NOT IN (SELECT `blocked_ids` FROM `block`);
So, you would be having blocked IDs in the block table! Hope this helps! :)
Consider this table:
+----+-------------+
| id | name |
+----+-------------+
| 1 | America |
| 2 | Europe |
| 3 | India |
| 4 | Japan |
| 5 | Brazil |
| 6 | Switzerland |
| 7 | Syria |
| 8 | Wales |
| 9 | Taiwan |
| 10 | Zaire |
+----+-------------+
And the blocked table:
+-----+
| IDs |
+-----+
| 1 |
| 4 |
| 6 |
| 8 |
| 9 |
+-----+
Now, when I give a query like:
SELECT * FROM `countries` WHERE `id` NOT IN (SELECT * FROM `blocked`);
I get this result:
+----+--------+
| id | name |
+----+--------+
| 2 | Europe |
| 3 | India |
| 5 | Brazil |
| 7 | Syria |
| 10 | Zaire |
+----+--------+
Hope this helps! :)