Mysql auto_increment proceed with lowest value - mysql

My problem is: I have a table with an auto_increment column. When I insert some values, all is right.
Insert first row : ID 1
Insert second row : ID 2
Now I want to insert a row at ID 10.
My problem is, that after this there are only rows inserted after ID 10 (which is the normal behaviour ).
But I want that the database first fills up ID 3-9 before making that.
Any suggestions?
EDIT:
To clarify: this is for an URL shortener I want to build for myself.
I convert the id to a word(a-zA-z0-9) for searching, and for saving in the database I convert it to a number which is the ID of the table.
The Problem is now:
I shorten the first link (without a name) -> ID is 1 and the automatically name is 1 converted to a-zA-Z0-9 which is a
Next the same happenes -> ID is 2 and the name is b, which is 2 converted.
Next interesting, somebody want to name the link test -> ID is 4597691 which is the converted test
Now if somebody adds another link with no name -> ID is 4597692 which would be tesu because the number is converted.
I want that new rows will be automatically inserted at the last gap that was made (here 3)

You could have another integer column for URL IDs.
Your process then might look like this:
If a default name is generated for a link, then you simply insert a new row, fill the URL ID column with the auto-increment value, then convert the result to the corresponding name.
If a custom name is specified for a URL, then, after inserting a row, the URL ID column would be filled with the number obtained from converting the chosen name to an integer.
And so on. When looking up for integer IDs, you would then use the URL ID column, not the table auto-increment column.
If I'm missing something, please let me know.

You could do 6 dummy inserts and delete/update them later as you need. The concept of the auto increment, by design, is meant to limit the application's or user's control over the number to ensure a unique value for every single record entered into the table.

ALTER TABLE MY_TABLE AUTO_INCREMENT = 3;

You would have to find first unused id, store it as user variable, use as id for insert.
SELECT #id := t1.id +1
FROM sometable t1 LEFT JOIN sometable t2
ON t2.id = t1.id +1 WHERE t2.id IS NULL LIMIT 1;
INSERT INTO sometable(id, col1, col2, ... ) VALUES(#id, 'aaa', 'bbb', ... );
You will have to run both queries for every insert if you still have gaps, its up to you to decide whether it is worth doing it.

not 100% sure what you're trying to achieve but something like this might work:
drop table if exists foo;
create table foo
(
id int unsigned not null auto_increment primary key,
row_id tinyint unsigned unique not null default 0
)
engine=innodb;
insert into foo (row_id) values (1),(2),(10),(3),(7),(5);
select * from foo order by row_id;
+----+--------+
| id | row_id |
+----+--------+
| 1 | 1 |
| 2 | 2 |
| 4 | 3 |
| 6 | 5 |
| 5 | 7 |
| 3 | 10 |
+----+--------+
6 rows in set (0.00 sec)

Related

Update table row value to a random row value from another table

I have 2 MySQL tables.
One table has a column that lists all the states
colStates | column2 | column 3
------------------------------
AK | stuff | stuff
AL | stuff | stuff
AR | stuff | stuff
etc.. | etc.. | etc..
The second table has a column(randomStates) with all NULL values that need to be populated with a randomly selected state abbreviation.
Something like...
UPDATE mytable SET `randomStates`= randomly selected state value WHERE randomStates IS NULL
Can someone help me with this statement. I have looked around at other posts, but I don't understand them.
this works for me with trial data in SQLite:
UPDATE mytable
SET randomStates = (SELECT colStates FROM
(SELECT * FROM first_table ORDER BY RANDOM())
WHERE randomStates IS NULL)
without the first SELECT portion, you end up with the same random value inserted into all the NULL randomStates field. (i.e. if you just do SELECT StateValue FROM counts ORDER BY RANDOM() you don't get what you want).

MySQL retrieving INSERT parameters retrieved by SELECT

If I have table structure as so:
CREATE TABLE a (
aid INT AUTO_INCREMENT,
acol1 INT,
acol2 INT,
PRIMARY KEY(aid);
)
CREATE TABLE b (
bid INT AUTO_INCREMENT,
bcol INT,
PRIMARY KEY(bid);
)
and run the statement:
`INSERT INTO a SET acol1 = (SELECT MAX(acol1) + 1 as newMax FROM a WHERE id = ?)
Is there anyway for me to retrieve the value of newMax after the query is executed? I am looking for something similar to last_insert_id() in PHP but for temporary values in the query.
Obviously I am trying to not query the database again if possible.
EDIT:
Actual situation:
CREATE TABLE group (
group_id INT AUTO_INCREMENT,
PRIMARY KEY(group_id)
) ENGINE = MyISAM;
CREATE TABLE item (
group_refid INT, --references group.group_id
group_pos INT, --represents this item's position in its group
text VARCHAR(4096), --data
PRIMARY KEY(group_refid, group_pos)
) ENGINE = MyISAM;
So the issue is that when I add a new item to a group, I need to make its
group_pos = MAX(group_pos) WHERE group_refid = ?
which would require a query with something like:
INSERT INTO item (group_refid, group_pos) SET group_refid = 1, group_pos = (SELECT MAX(group_pos) + 1 FROM item WHERE group_refid = 1);
As you know, this query does not work. There is added complexity that there may not be an item entry yet for a particular group_id.
I am trying to get this all into one atomic statement to prevent race conditions.
INSERT INTO item (group_refid,group_pos)
SELECT 1, (
SELECT IFNULL(MAX(group_pos),0) + 1
FROM item
WHERE group_refid=1
);
However, if we're talking MyISAM tables explicitly, not another engine, this would work:
mysql> CREATE TABLE items (group_refid INT, group_pos INT AUTO_INCREMENT, PRIMARY KEY(group_refid,group_pos)) ENGINE=MyISAM;
Query OK, 0 rows affected (0.12 sec)
mysql> INSERT INTO items (group_refid) VALUES (1),(2),(1),(1),(2),(4),(2),(1);
Query OK, 8 rows affected (0.02 sec)
Records: 8 Duplicates: 0 Warnings: 0
mysql> SELECT * FROM items ORDER BY group_refid, group_pos;
+-------------+-----------+
| group_refid | group_pos |
+-------------+-----------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 1 | 4 |
| 2 | 1 |
| 2 | 2 |
| 2 | 3 |
| 4 | 1 |
+-------------+-----------+
However, that AUTO_INCREMENT on a second column in the PK is not portable to another database engine.
you cant. insert query is for insering not selecting.
You must run other query like that
SELECT MAX(acol1) + 1 as newMax FROM a WHERE acol2 = ?
for more read this
I think you can do:
INSERT INTO b
SET bcol = (SELECT #acol := MAX(acol1) + 1 as newMax FROM a WHERE acol2 = ?);
Then you can use the variable #acol to get the value you want.
EDIT:
Is this what you want?
INSERT INTO item (group_refid, group_pos)
SELECT 1, MAX(group_pos) + 1
FROM item
WHERE group_refid = 1;
Not directly in the statement, no. You'll need a separate statement to retrieve values.
But, you could "capture" the value from the SELECT into a user-defined variable, and then retrieve that with a SELECT (in the same database session), if you needed to "know" the value returned from the SELECT.
For example:
INSERT INTO b (bcol)
SELECT #bcol := (MAX(a.acol1) + 1) AS newMax
FROM a WHERE a.acol2 = ?)
SELECT #bcol + 0 AS new_bcol
NOTE:
Note that the user-defined variable assigned in the select is subject to modification elsewhere in the session, for example, it could be overwritten by the execution of a trigger defined the target table of the INSERT.
As an edge case, not that anyone would do this, but it's also possible there might be a BEFORE INSERT trigger that modifies the value of bcol, before it gets inserted. So, if you need to "know" the value that was actually inserted, that would be available in an AFTER INSERT trigger. You could capture that in a user-defined variable in that trigger.
Running a second, separate query against the a table is subject to a race condition, a small window of opportunity for a another session to insert/update/delete a row in table a, such that it's possible that a second query could return a different value than the first query... it might not be the value that was retrieved the first time. Unless of course you are within the context of an InnoDB transaction with REPEATABLE READ isolation level, or you've implemented some concurrency-killing locking strategy.

MySQL Update by Row number

I need to update rows by their number(not AI ID, cause some of the rows may will be removed). How can I do this?
I mean something like this:
UPDATE cars SET idx = value WHERE row_number = i
I would do this in a 'for' statement, and i is the integer of my statement. So I would update every row in the statement.
Sorry for my bad english, and thanks!
Here's a pure MySQL solution:
/*test data*/
create table foo (id int auto_increment primary key, a int);
insert into foo (a) values (10), (11), (12);
/*update statement*/
update foo
set a = 5
where id = (
select id from (
select id, #rownum:=#rownum + 1 as rownumber
from foo, (select #rownum:=0) vars order by id
) sq where rownumber = 2
);
Results in:
| ID | A |
-----|----|--
| 1 | 10 |
| 2 | 5 |
| 3 | 12 |
Feel free to ask if you have any questions about this.
Also, note the order by id in there. It's important, cause in a database there is no first or last row. Without an order by clause theoretically there could be each time a different result.
You can also see it working live here in an sqlfiddle.
i don't know this about mysql but you can do this in php
$row_number=? ;//the row no of mysql you want to change the id
$id=? ;//the new id
mysql_connect //do it yourself
$query="select 8 from tablename"; //the query
$result=mysql_query($qyery,$conn);
$count=0;
while($row=mysql_fetch_array($result)) // fetch each row one by one an put data in array $row
{
$count++; //increment count means the no of rows are incermented
if($count==$rownumber) //the row where you want to edit the id
{
$query1="update tablename set id='".$id."' where id=".$row["id"]; //new query on that particular row
$result1=mysql_query($query1,$conn);
}
}
this will work , just modify this code according to your use

Add from the 5th value

The goal
Add from the 5th value.
The problem
There is a table on my database called markets. Within it, there are 5 values:
+----+------+
| Id | Name |
+----+------+
| 0 | NULL |
+----+------+
| 1 | A |
+----+------+
| 2 | B |
+----+------+
| 3 | C |
+----+------+
| 4 | D |
+----+------+
Id is a primary key and auto-incremented column and its start by zero (I added it manually to use as default). When I add some market to this table, seems that MySQL adds the market in question with 0 as Id — and I want to set the Id as 5 to continue the table's logic. So I ask: how can I add some value from the 5th Id?
What I've already tried
I already set the auto_increment value for 5, but without success. The query that I used is the following:
ALTER TABLE `markets` AUTO_INCREMENT = 5;
How do I know that the MySQL is attempting to add the market with its Id as 0?
My application is powered by C# that is throwing an exception:
Duplicate entry '0' for key 'PRIMARY'
On your INSERT statement, leave the auto_increment field out of the statement. This will leave MySQL to increment it and add it automatically.
how can I add some value from the 5th Id
Just try:;--
INSERT INTO markets(Name) VALUES('E');
ie, dont use the auto_increment field while inserting the data. MySQL is smart enough to do that for you ;)
Already there are four values are there in the table, So you can just insert next row. it will automatically take 5 as a next value.
When we are using auto_increment no need to specify that column in the insert command.
INSERT INTO markets(Name) VALUES('E');
In case if you want to alter the auto_increment value you can use the following statement
ALTER TABLE market AUTO_INCREMENT = 5;

SELECT(MAX) not going past 10 - mysql with phpmyadmin

I'm creating a PHP script to insert rows into a database called orders based on a shopping cart that is stored in an associative array using a sessional array $_SESSION['cart']. The database looks something like this:
orders
----------+--------------+-------------+-------------+-------------+
Id | Username | Item1Id | Item2Id | Item3Id |
----------+--------------+-------------+-------------+-------------+
1 | a#aa.com | 8000001 | 8000002 | 800003 |
----------+--------------+-------------+-------------+-------------+
5 | a#aa.com | 7000001 | 6000002 | 700003 |
----------+--------------+-------------+-------------+-------------+
7 | b#bb.com | 8000001 | 8000002 | NULL |
----------+--------------+-------------+-------------+-------------+
10 | a#aa.com | 3000001 | 1000002 | 800009 |
----------+--------------+-------------+-------------+-------------+
Id column type is CHAR(20) as I may choose to use letters later on.
As part of inserting the row, I need to assign an Id (Primary Key) to the order row which will be set to 1 higher than the current highest Id number found.
The whole script works perfectly; query finds highest Id in the table and I increment that by 1 and assign it to a variable to use as part of the insert query. The only problem is that "SELECT MAX(Id) FROM orders" can't seem to find anything higher than 9. Is there a condition which prevents the SELECT MAX(Id) from identifying anything in double digits?
I've got it written like:
$highestID = mysqli_query($conn, "SELECT MAX(Id) FROM orders");
$orderID = $highestID +1;
I've emptied the database except for Id numbers1 and 2. Running the PHP script inserts new rows with Id numbers 3, 4, 5 except when it gets to 10, the script is unable to as it produces an error of having duplicate primary key of '10' (from $orderID's value). Even when manually entering a row into the database with Id of '25', $orderID still only returns '10' when I echo out its result.
I have not set any specific limits to the amount of rows that can be entered or anything like that.
Id is char(20) so order by Id using string sort. You could use cast or convert function to sort numbers.
Like:
select max(cast(Id as unsigned)) from orders
You really do not need to go through ALL that trouble for an auto-incremental PK. Here's how you can go about it.
Step 1 : In your phpmyadmin, edit your table, and check the A_I checkbox for your PK column.
Step 2 : While inserting from PHP, leave the field blank. It will automatically assign a value of the current max + 1 to your PK.
Eg,
$query = "Insert into mytable (id, name) values ('', 'Name1'), ('', 'Name2')";
Edit : You really cannot have a CHAR(20) PK and then expect the increment to work btw.