How to make unique incrementing counter in MySQL - mysql

How to assign unique auto incrementing values to a certain column? Kind of like AUTO_INCREMENT does but it should be NULL at the time of insertion and assigned at some later point.
I have a table that gets regular data inserts and a few workers that process that data and set processed_at datetime field when they're done. Now I want incrementally select new processed rows since the last call. If I naively use where processed_at > #last_update_time I'm afraid there might be a situation where some records are processed at the same second and I miss some rows.
update: Can I just do
begin;
select #max := max(foo) from table1;
update table1 set foo = #max + 1 where id = 'bar' limit 1;
commit;
if foo column is indexed?

You can use a trigger to implement that.
CREATE TABLE my_increment (value INT, table_name TEXT);
INSERT INTO my_increment VALUES (0, 'your_table_name');
CREATE TRIGGER pk AFTER UPDATE ON your_table_name
BEGIN
UPDATE my_increment
SET value = value + 1
WHERE table_name = 'your_table_name';
UPDATE your_table_name
SET ID2 = (
SELECT value
FROM my_increment
WHERE table_name = 'your_table_name')
WHERE ROWID = new.ROWID;
END;
But bear in mind that this trigger will work on every execution of the Update query.
You can also do it manually:
Create the table to store increment value:
CREATE TABLE my_increment (value INT, table_name TEXT);
INSERT INTO my_increment VALUES (0, 'your_table_name');
Then when you want to update the table, get the last value from this table and insert value+1 to your column needed to be incremented.

Related

Automatically add days to a column based on other table columns

I have a table A which has column NoOfDays, and another table B which has a column MyDate of type datetime and it is set to Default as "CURRENT_TIMESTAMP".
Now in table B, I want to add a new column (called ValidDate), which should AUTOMATICALLY store the sum value of (B.MyDate + A.NoOfDays)
For example, if B.MyDate has value of "2022-07-25 04:50:26" and A.NoOfDays has value of "60", then B.ValidDate should get the value of "2022-09-23 04:50:26"
What is the way in MySQL to set this new column value to store this summed value automatically.
Checked for existing threads, but found only this one which does not offer a solution to store, but to create a view output only.
MySQL - Add number of days to date in 3rd column automatically
For existing rows in table_b , use an update statement like UPDATE table_b set ValidDate=date_add(MyDate , interval + (select NoOfDays from table_a) day);
For new inserts, we can use a trigger to handle that. Here is the complete script written and tested in workbench:
create table table_a (NoOfDays int);
create table table_b(MyDate timestamp,ValidDate datetime);
insert table_a values(60);
DELIMITER //
drop trigger if exists auto_sum //
create trigger auto_sum before insert on table_b for each row begin
set new.ValidDate=date_add(new.MyDate , interval + (select NoOfDays from table_a) day);
end //
delimiter ;
insert into table_b (MyDate) values (default); -- The value of ValidDate is calculated in the trigger,so we only need to specify the value for MyDate.
Please try this:
CREATE TABLE TableA (NoOfDays INT);
INSERT INTO TableA VALUES(60);
CREATE TABLE TableB(MyDate DATETIME DEFAULT CURRENT_TIMESTAMP);
INSERT INTO TableB VALUES('2022-07-25 04:50:26');
ALTER TABLE TableB
ADD ValidDate DATETIME;
UPDATE TableB
SET ValidDate = date_add(MyDate, INTERVAL (SELECT NoOfDays FROM TableA) DAY);
If we test the result :
SELECT * FROM TableB;

How do I change the auto increment counter in MySQL from +1 to +43

I am trying to change the auto increment counter in MySQL from +1 to +43.
For example my rows have Id = 1, 2, 3.
But I don’t want the Id’s having +1 sequence.
I want them like 43, 86, 129
I tried
ALTER TABLE `table_name` AUTO_INCREMENT=43
But this just changed the sequence to 43, 44, 45
You have to change the system variable auto_increment_offset to the offset you want. But be careful using this solution since you change the offset for all tables (and INSERT commands). I don't recommend this solution, another column with a custom (calculated) ID would be a better solution:
SET ##session.auto_increment_offset = 43;
INSERT INTO table_name (col1, col2) VALUES ('val1', 'val2')
You can also use the default auto increment (offset = 1) and using a calculation to get the custom increment:
SELECT id, id * 43 AS `custom_id`
FROM table_name
Answer from Mark S. Rasmussen's blog: https://improve.dk/working-with-identity-column-seed-and-increment-values/
Changing the identity increment value
Unfortunately there’s no easy way to change the increment value of an identity column. The only way to do so is to drop the identity column and add a new column with the new increment value. The following code will create a new temporary table, copy the data into it, recreate the original table with the correct increment value and then finally copy the data back using SET IDENTITY_INSERT ON.aspx) to insert explicit values into the identity column.
BEGIN TRAN
-- Create new temporary table to hold data while restructuring tblCars
CREATE TABLE tblCars_TMP
(
CarID int NOT NULL,
Name nvarchar(50) NOT NULL
)
-- Insert tblCars data into tblCars_TMP
INSERT INTO tblCars_TMP SELECT * FROM tblCars
-- Drop original table
DROP TABLE tblCars
-- Create new tblCars table with correct identity values (1,1) in this case
CREATE TABLE [dbo].[tblCars]
(
[CarID] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) NOT NULL,
)
-- Reinsert data into tblCars table
SET IDENTITY_INSERT tblCars ON
INSERT INTO tblCars (CarID, Name) SELECT CarID, Name FROM tblCars_TMP
SET IDENTITY_INSERT tblCars OFF
COMMIT

Update field with another auto increment field value MySQL

I have a table in MYSQL database with two fields:
Id (auto increment field).
Post_Id.
When I insert a new record both fields should have the same value. So I should update post_id with Id value, and at the same time make sure that I update the field with the right value not with any other new inserted record value.
I tried this SQL statement but it was very slow and I was not sure that I select the right value:
set #auto_id := (SELECT AUTO_INCREMENT
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME='table_name'
AND TABLE_SCHEMA=DATABASE() );
update table_name set post_id= #auto_id where id=#auto_id ;
I don't have long experience with MySQL and I cannot change the table structure .
The approach you followed is not transaction safe as well.
The best option I can think about is to use trigger
Edit: According to #lagripe's mentionings
CREATE TRIGGER sometrigger
AFTER INSERT ON sometable
BEGIN
SET NEW.post_id := (SELECT id from sometable order by DESC limit 1) + 1 ; // you may need +1 here. I couldn't test it.
END
or you may consider to use LAST_INSERT_ID
insert into table_name values ( .... );
update table_name set post_id = LAST_INSERT_ID();
but why do you need two columns with the same id at first place?
if you really need why don't you use computed/generated columns?
CREATE TABLE Table1(
id DOUBLE,
post_id DOUBLE as (id)
);
you can use triggers :
CREATE TRIGGER UpdatePOST_id
BEFORE INSERT ON table_db
FOR EACH ROW
SET NEW.post_id := (select id from table_db order by id DESC LIMIT 1)+1 ;
from now on, whatever you insert your as a value in post_id column will be replaced with the id inserted automatically.
Test :
|id|post_id|
|20| 20 |
|21| 21 |
|22| 22 |
|23| 23 |
To drop the trigger :
DROP trigger UpdatePOST_id

SQL insert with empty value for the id

How do I insert a sql row into a new table where it meets criteria but resets the id value. In other words, copy the row, but reset the id value.
This is my current sql
INSERT INTO followers_lost SELECT * FROM followers WHERE pk = $pk
I tried to SET id=null and VALUE (0), but both don't work.
All you have to do since you want all the columns except the identity is specify all the non-identity columns on the insert:
INSERT INTO [followers_lost] ([Column1],[column2]...{but not the identity
column})
SELECT [Column1],[column2]...{but not the identity column} FROM followers WHERE
pk = $pk
You can create the column and then update it:
SET #new_id=0;
UPDATE your_table
SET id = #new_id := #new_id + 1
where id = 0
OK based on your comment I think you are trying to take all or some of the fields from Followers except the PK and put them into Followers_Lost where they equal a certain PK. If you want multiple PK's you would need to change the where clause to an IN statement instead of an equal and adjust your values accordingly.
CREATE TABLE dbo.UAT_Followers_Lost (PK INT IDENTITY(1,1),DATA VARCHAR(50) )
CREATE TABLE dbo.UAT_Followers (PK INT IDENTITY(1,1),DATA VARCHAR(50) )
INSERT INTO dbo.UAT_Followers
(DATA)
SELECT 'Jan'
UNION ALL
SELECT 'Feb'
UNION ALL
SELECT 'Mar'
DECLARE #PK INT
SET #PK = 1
INSERT INTO dbo.UAT_Followers_Lost
(Data)
SELECT Data
FROM dbo.UAT_Followers
WHERE PK = #PK

mysql insert with value equal to primary key + 1

I have an auto increment column ID, and for some situation I wanted the other column to be equal to the primary key + 1 value
ID | other
1 | 2
2 | 3
3 | 4
4 | 123 (some situation, it is not always plus 1)
How can I achieve this?
Here's what I have tried
INSERT INTO table (`ID`,`other`) VALUES ('',(SELECT MAX(ID)+1 FROM table))
But that returns an error
You can't specify target table 'table' for update in FROM clause
Try Below query:
ALTER TABLE dbo.table ADD
Column AS ([ID]+1)
GO
It will definitely work
Using a normal AUTO_INCREMENT column as id, I cannot think of a way to do this in MySQL. Triggers, which otherwise would have been an option, don't work well with AUTO_INCREMENT columns.
The only way I see is to do two commands for an INSERT;
INSERT INTO bop (value) VALUES ('These values should be 1 and 2');
UPDATE bop SET other = id+1 WHERE id = LAST_INSERT_ID();
An SQLfiddle to test with.
The closest I'm getting to what you're looking for is to generate sequences separately from AUTO_INCREMENT using a function, and use that instead to generate the table id;
DELIMITER //
CREATE TABLE bop (
id INT UNIQUE,
other INT,
value VARCHAR(64)
)//
CREATE TABLE bop_seq ( seq INT ) // -- Sequence table
INSERT INTO bop_seq VALUES (1) // -- Start value
CREATE FUNCTION bop_nextval() RETURNS int
BEGIN
SET #tmp = (SELECT seq FROM bop_seq FOR UPDATE);
UPDATE bop_seq SET seq = seq + 1;
RETURN #tmp;
END//
CREATE TRIGGER bop_auto BEFORE INSERT ON bop
FOR EACH ROW
SET NEW.id = bop_nextval(), NEW.other=NEW.id + 1;
//
That'd let you do inserts and have it autonumber like you want. The FOR UPDATE should keep the sequence transaction safe, but I've not load tested so you may want to do that.
Another SQLfiddle.
I solved this by updating 2 times the DB..
I wanted to do +1 from 19 till ..
UPDATE `table` SET `id`=`id`+101 WHERE id <= 19
UPDATE `table` SET `id`=`id`-100 WHERE id <= 119 AND id >= 101