I have two mysql tables, one needs to start its auto-increment column id with the last value of the last inserted row in the other table (plus 1).
According to mysql manual you can restart the value of an auto increment column like this:
mysql> ALTER TABLE tbl AUTO_INCREMENT = 100;
However, this is not possible:
mysql> ALTER TABLE tb2 AUTO_INCREMENT = (SELECT MAX(id) FROM tbl1);
I need to perform something like this because I'm filling the tables using a script. Is there another way to achieve it?
I think you are trying to use the auto-increment column for something it is not well suited to. If you care about the exact values that get inserted then it shouldn't be auto-increment.
IT IS USING THIS SCRIPT
ALTER TABLE `people` AUTO_INCREMENT =1
where people is my table, or you can do this through GUI (operation tab of phpmyadmin with current table selected)
What about create a dummy record and increment?
-- insert dummy forcing id
INSERT INTO 'tb2' (ID, NAME, ...)
VALUES (SELECT MAX(id) FROM tb1, "dummy", ...);
-- automagically increment to last id + 1
ALTER TABLE `tb2' AUTO_INCREMENT = 1; -- only myISAM
-- delete dummy
DELETE FROM 'tb2' WHERE NAME="dummy";
Related
I have a table with id column as a number which have meanings. Different types of accounts start from different ranges. E.g Organisation 10000 <-> 100000, users 1000000 <-> 1kk. How can i properly increment ids on insert (with possible concurrency problem)?
If you were doing this in Oracle's table server, you would use different SEQUENCE objects for each type of account.
The MariaDB fork of MySQL has a similar kind of SEQUENCE object, as does PostgreSQL. So if you were using MariaDB you would do something like this.
CREATE SEQUENCE IF NOT EXISTS org_account_id MINVALUE=10000 MAXVALUE=999999;
CREATE SEQUENCE IF NOT EXISTS user_account_id MINVALUE=1000000;
Then to use a sequence in place of autoincrement you'll do something like this.
INSERT INTO tbl (id, col1, col2)
VALUES (NEXTVAL(user_account_id), something, something);
In MySQL you can emulate sequence objects with dummy tables containing autoincrement ids. It's a kludge. Create the following table (one for each sequence).
CREATE TABLE user_account_id (
sequence_id BIGINT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`sequence_id`)
);
ALTER TABLE user_account_id AUTO_INCREMENT=1000000;
Then issue these queries one after the other to insert a row with a unique user id.
INSERT INTO user_account_id () VALUES ();
DELETE FROM sequence WHERE sequence_id < LAST_INSERT_ID();
SET #id:=LAST_INSERT_ID();
INSERT INTO tbl (id, col1, col2)
VALUES (#id, something, something);
After your insert into the dummy table, LAST_INSERT_ID() returns a unique id. The DELETE query merely keeps this dummy table from taking up too much space.
I recommend that you use a normal sequence-based bigint column. Then, on SELECT, add the base for the appropriate account type to the column.
PreparedStatement ps = con.prepareStatement("insert into emp(emp_code,emp_name,join_date,designation,birth_date,gender,mobile) values((select max(emp_code)+1 from emp),?,?,?,?,?,?)")
This query will definitely help..
ALTER TABLE advance_d ADD testcolumn INTEGER NOT NULL AUTO_INCREMENT;
This is the sql code i typed. i have a table called advace_d. It has a primary key column called "ad_id" . when i wrote this code ALTER TABLE advance_d ADD testcolumn INTEGER; a new column was created with null values. I want to know how to create the column with values starting from a given value auto incremented by 1.
so my table would have 1 primary key column for ID and another column with values starting from 50 incremented by 1.
The only way I know how to do this is via insertion into a table with an auto increment column. I don't know how to do this with your existing table, but you can create a new one, and then copy the previous table over to it, populating the auto increment column in the process:
CREATE TABLE newTable (col1, col2, ..., colAuto INT NOT NULL AUTO_INCREMENT);
INSERT INTO newTable (col1, col2, ..., colAuto)
SELECT col1, col2, ..., NULL -- NULL for colAuto
FROM yourTable
ORDER BY ad_id;
This should result in a new table with the same data, and a column colAuto which starts as 1, as ordered by the ad_id column in your original table. After this, you may alter colAuto if you don't want it to be auto increment anymore. You may also delete the original table if it no longer serves any purpose.
Edit:
We might also be able to do this using a row number session variable:
SET #rn := 0;
UPDATE yourTable
SET colAuto = (SELECT #rn := #rn + 1 )
ORDER BY ad_id;
But in practice, doing such an update into a non auto increment column may not make much business sense. This is because as soon as you add more data to your table, you would have to manually update again, but this time the sequence would be starting from some number other than zero. Really, an auto increment column is the way to go for easily maintaining a sequence in SQL.
I have a quick question about MySQL behavior.
Imagine a table with 3(relevant) columns:
id (PK + AI),somedate,someuser,etc...
I have put a unique constraint on (date,user). So when I start with a clean test table and run the following query twice:
REPLACE INTO `testtable` (somedate,someuser) VALUES('2017-01-01','admin');
I expected a row with the 'id' column on 1. but instead everytime I run this query the id goes up because of the auto increment and I can't have that happen (this would corrupt my data relations). Why is this? Can I make it so that I can keep the original primary key when a replace into occurs?
Not with the REPLACE. That's like an INSERT preceded by a DELETE. The behavior you observe with REPLACE is the same as the behavior you would see if you executed these two statements:
DELETE FROM `testtable` WHERE somedate = '2017-01-01' and someuser = 'admin';
INSERT INTO `testtable` (somedate,someuser) VALUES ('2017-01-01','admin');
And that means the auto_increment column on the newly inserted row will have a new value.
Perhaps consider using INSERT ... ON DUPLICATE KEY UPDATE.
Reference: https://dev.mysql.com/doc/refman/5.7/en/insert-on-duplicate.html
(Note that the attempt to insert a row that gets updated will use an auto_increment value.)
To me looks like you actually wanted an UPDATE statement rather like
update `testtable`
set somedate = '2017-01-01',
someuser = 'admin'
where id = <id of the record> ;
I need two columns in table that would have same value on insert. Is there any way to do it from database side?
So you want to let one column use the auto_increment feature, but make another column in the same table also have the same value?
I can't think of a reason you would need this feature. Perhaps you could explain what you're trying to accomplish, and I can suggest a different solution?
A trigger won't work for this. It's a chicken-and-egg problem:
You can't change any column's value in an AFTER trigger.
But the auto-increment value isn't set yet when a BEFORE trigger executes.
It also won't work to use a MySQL 5.7 GENERATED column:
CREATE TABLE MyTable (
id INT AUTO_INCREMENT PRIMARY KEY,
why_would_you_want_this INT GENERATED ALWAYS AS (id)
);
ERROR 3109 (HY000): Generated column 'why_would_you_want_this'
cannot refer to auto-increment column.
You can't do it in a single SQL statement. You have to INSERT the row, and then immediately do an UPDATE to set your second column to the same value.
CREATE TABLE MyTable (
id INT AUTO_INCREMENT PRIMARY KEY,
why_would_you_want_this INT
);
INSERT INTO MyTable () VALUES ();
UPDATE MyTable SET why_would_you_want_this = LAST_INSERT_ID()
WHERE id = LAST_INSERT_ID();
You could alternatively generate the ID value using some other mechanism besides AUTO_INCREMENT (for example a Memcached incrementing key). Then you could insert the new value in both columns:
INSERT INTO MyTable (id, why_would_you_want_this) VALUES ($gen_id, $gen_id);
Define a before or after insert trigger and assign the value of the 2nd field in the trigger.
If the 1st field is an auto increment column, then you need to use an after insert trigger. If your application assigns value to the 1st field, then you can use a before insert trigger.
However, I would no necessarily duplicate the value on insert. You can leave the 2nd field as null on insert, which would mean that its value is the same as the 1st field's. The only drawback of this approach is that it may be more difficult to create joins on the 2nd field.
You can do this in one query by using the primary key (assumed to be id) and setting your column (assumed to be columnName):
"INSERT INTO tableName SET `columnName` = (SELECT MAX(x.id) FROM tableName x)+1"
This will not work if you have deleted the most recent primary key row however. To get past this, you can insert into the id as well:
"INSERT INTO tableName SET `columnName` = (SELECT MAX(x.id) FROM tableName x)+1, `id`= (SELECT MAX(x.id) FROM tableName x)+1"
However, this solution has the downside (or upside depending on the case) of reusing primary key values that have already been deleted.
suggested way:
To use the actual auto_increment value, you can do this:
"INSERT INTO tableName SET `columnName` = (SELECT `AUTO_INCREMENT` FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'db_name' AND TABLE_NAME = 'table_name')"
Sources that helped me solve this: Prashant Pimpale's answer
I have a table with primary key (its name is "id") defined as auto_increment. I use NULL in INSERT statements to "fill" the id value. It works, of course. However now I need to "move" an existing record to a new primary key value (the next available, the value is not so much important, but it must be a new one, and the last one if ordered by id). How can I do it in an "elegant" way? Since the "use NULL at INSERT" does not work too much with UPDATE:
update idtest set id=NULL where id=1;
This simply makes the id of the record zero. I would expect to do the same thing as with INSERT, but it seems my idea was incorrect.
Of course I can use "INSERT ... SELECT" statement, then a DELETE on the old one, or I can use something like MAX(id) + 1 to UPDATE the id of the old record in one step, etc, but I am curious if there is a finer solution.
Also, the MAX(id) solution doesn't seem to work either by the way:
mysql> update idtest set id=max(id)+1 where id=3;
ERROR 1111 (HY000): Invalid use of group function
mysql> update idtest set id=(select max(id)+1 from idtest) where id=3;
ERROR 1093 (HY000): You can't specify target table 'idtest' for update in FROM clause
This is the way I believe:
UPDATE users SET id = (SELECT `AUTO_INCREMENT`
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'test'
AND TABLE_NAME = 'users') WHERE id = 2;
select * from users;
I used by own tables substitute yours.
test is database name, users is table name and id is AUTO_INCREMENT in my case.
EDIT: My Query above works perfect but its side effects are somewhat 'dangerous', upon next insert as AUTO_INCREMENT value will collide with this recently updated record so just next single insert will fail. To avoid that case I've modified above query to a transaction:
START transaction;
UPDATE users SET id = (SELECT `AUTO_INCREMENT`
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'test'
AND TABLE_NAME = 'users') WHERE id = 2;
#renew auto increment to avoid duplicate warning on next insert
INSERT IGNORE INTO users(username) values ('');
COMMIT
Hope this will help someone if not OP.
The way you are trying to update same table is wrong but you can use join on same table
update idtest t
join (select id +1 as id
from idtest order by id desc
limit 1) t1
set t.id=t1.id
where t.id=3;
or
update idtest t
join (select max(id) +1 as id
from idtest ) t1
set t.id=t1.id
where t.id=3;
You can use the REPLACE INTO clause to do the trick.
From the manual:
REPLACE works exactly like INSERT, except that if an old row in the table has the same value as a new row for a PRIMARY KEY or a UNIQUE index, the old row is deleted before the new row is inserted. See Section 13.2.5, "INSERT Syntax".
EDIT
My mistake (in the comments) that you have to have two unique constraint to achieve this:
When you use the auto_increment value to REPLACE the record, the record will be replaced with the give ID and will not change (however the AI value will increment).
You have to exclude the AI column from the query. You can do that if you have one more UQ constraint.
Check this SQLFiddle demo: http://sqlfiddle.com/#!2/1a702e
The first query will replace all the records (but the id's value will not change).
The second one will replace it too, and the new AI value will be used. (Please note, that the second query does not contain the id column, and there is a UQ constraint on the some column).
You can notice, that the second query uses higher AI values than it is excepted: this is because the first replace incremented the AI value.
If you do not have two unique keys (one for the AI and one for another columns), the REPLACE statement will work as a normal INSERT statement!
(Ofcourse you can change one of the UNIQUE KEYs with a PRIMARY KEY)