I'm having a problem with the auto increment id increasing when I don't want to it. I'm aware that the auto increment id increases when using INSERT IGNORE so I'm working around that, but still getting a behavior I can't figure out.
I'm building a normalized table of transactions, and in this table there is a column for first name which will have a reference table of transaction_first_names. My workflow is that I load data into a non normalized staging table, compare the values in the staging table with the values in the reference tables and if they do not exist into the reference table, then move the data from the staging table to the normalized table.
The issue I'm having is that when I try to insert any "new" values from the staging table into the reference tables, it seem to increment the autoincrement id's in the reference table in a way I can't explain. I wouldn't normally be ocd or stingy with id's, but as a continuing process I don't want the id's to continually be chewed through.
Here is my setup, link & code. As you can see in the second result the last inserted value was given the id of 16, whereas the goal is that id should be 9:
Runnable Example - http://rextester.com/KVMO89341
CREATE TABLE IF NOT EXISTS `transaction_first_names` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`first_name` VARCHAR(100) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE INDEX `u_first_name` (`first_name`)
)
COLLATE='utf8mb4_general_ci'
ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `transaction_stage` (
`transaction_id` BIGINT(20) UNSIGNED NOT NULL,
`first_name` VARCHAR(255) NULL DEFAULT NULL,
PRIMARY KEY (`transaction_id`),
INDEX `first_name` (`first_name`(191))
)
COLLATE='utf8mb4_general_ci'
ENGINE=InnoDB;
TRUNCATE transaction_stage;
TRUNCATE transaction_first_names;
INSERT INTO `transaction_stage` (`transaction_id`, `first_name`) VALUES (3658822144, 'Michael');
INSERT INTO `transaction_stage` (`transaction_id`, `first_name`) VALUES (3658825319, 'Pete');
INSERT INTO `transaction_stage` (`transaction_id`, `first_name`) VALUES (3658828867, 'Robert');
INSERT INTO `transaction_stage` (`transaction_id`, `first_name`) VALUES (3658865656, 'Martin');
INSERT INTO `transaction_stage` (`transaction_id`, `first_name`) VALUES (3659080925, 'Charlews');
INSERT INTO `transaction_stage` (`transaction_id`, `first_name`) VALUES (3659943769, 'Christopher');
INSERT INTO `transaction_stage` (`transaction_id`, `first_name`) VALUES (3660191699, 'Robert');
INSERT INTO `transaction_stage` (`transaction_id`, `first_name`) VALUES (3660192662, 'Errol');
INSERT INTO `transaction_stage` (`transaction_id`, `first_name`) VALUES (3660194469, 'Frank');
INSERT INTO `transaction_stage` (`transaction_id`, `first_name`) VALUES (3660200483, 'Frank');
-- first select
SELECT DISTINCT st.first_name
FROM transaction_stage st
LEFT JOIN transaction_first_names f ON st.first_name <=> f.first_name
WHERE f.id IS NULL
AND st.first_name IS NOT NULL;
-- first insert
INSERT INTO transaction_first_names (`first_name`)
SELECT DISTINCT st.first_name
FROM transaction_stage st
LEFT JOIN transaction_first_names f ON st.first_name <=> f.first_name
WHERE f.id IS NULL
AND st.first_name IS NOT NULL;
-- second insert
INSERT INTO transaction_first_names (`first_name`)
VALUES ('Another name');
-- check autoincrement
SELECT * FROM transaction_first_names order by id asc;
DROP TABLE IF EXISTS transaction_first_names;
DROP TABLE IF EXISTS transaction_stage;
I've tried wrapping the select distinct in the first insert statement, but no luck.
Ah, InnoDB handles things a bit differently depending on how the system variable innodb_autoinc_lock_mode is set.
For lock modes 1 or 2, gaps may occur between successive statements
because for bulk inserts the exact number of auto-increment values
required by each statement may not be known and overestimation is
possible.
https://dev.mysql.com/doc/refman/5.7/en/innodb-auto-increment-handling.html
Related
I convert an id which is in a char column datatype. after that, I want to add it by 1 (plus 1).
Could you help me? why my query is not working?
query:
INSERT INTO `countries` (`id`, `country_name`) VALUES ((SELECT MAX(CAST(`id` as INTEGER)) AS `max_id` FROM `countries`) + 1, 'India');
The following would run:
INSERT INTO `countries` (`id`, `country_name`)
SELECT MAX(CAST(`id` as INTEGER)) + 1, 'India'
FROM `countries`;
But I think it would be easier if you just make the id column an AUTO_INCREMENT.
This is not how you should be doing identifiers.
If you want incrementing id values, you want to use the AUTO_INCREMENT feature when creating your table.
Your way is dangerous, there's always a possibility of two transactions running at the same time picking the same "next ID".
Just create a table with the flag on:
CREATE TABLE countries (
id MEDIUMINT NOT NULL AUTO_INCREMENT,
name CHAR(30) NOT NULL,
PRIMARY KEY (id)
);
INSERT INTO countries (`name`) VALUES ('India');
OK so I have a table (in my MySQL database) as follows:
CREATE TABLE IF NOT EXISTS `funddata` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ticker` varchar(128) NOT NULL,
`price_date` date NOT NULL,
`price` double NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=0 ;
And some sample data:
INSERT INTO funddata (ticker, price_date, price) VALUES ("tick1", '2013-06-01', 36.2);
INSERT INTO funddata (ticker, price_date, price) VALUES ("tick2", '2013-06-01', 14.7);
INSERT INTO funddata (ticker, price_date, price) VALUES ("tick3", '2013-06-01', 102.5);
INSERT INTO funddata (ticker, price_date, price) VALUES ("tick1", '2013-07-01', 38.7);
INSERT INTO funddata (ticker, price_date, price) VALUES ("tick2", '2013-07-01', 16.2);
Now let's say I want to add some more prices for tick1. If the price I want to add already exists in my table for that date then I want to update what's there with the new price, else I just want to insert it as a new record.
Does it make sense to make a unique index out of (ticker, price_date) given that no 2 records should share the same ticker and date? If so how would I do this and how would I make use of such an index.
CREATE UNIQUE INDEX index_name ON funddata(priceDate, price);
Then use INSERT... ON DUPLICATE KEY UPDATE
But still,this break the first normal form.http://en.wikipedia.org/wiki/First_normal_form
I have created two tables which i want to insert similar data in.
CREATE TABLE one(
one_id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
PRIMARY KEY (one_id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE two(
two_id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
PRIMARY KEY (two_id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;
every time in run insert.
To do that,i am using transactions
START TRANSACTION;
SET #name = uuid();
INSERT INTO one(one_id,name) VALUES (Null,#name);
INSERT INTO two(two_id, name) VALUES (Null, #name);
COMMIT;
This does not produce new values on new inserts.It however inserts the same data in the field name as i wanted.
How can i make this work?.
I don't see a need to move to transactions in order to do that, just add an before insert trigger to the table .
Something like :
CREATE TRIGGER `ONE_TABLE_TRIGG` BEFORE INSERT ON `one`
FOR EACH
ROW BEGIN
SET NEW.name= UUID( );
END ;
You can check if it's null before doing that. do this on both tables and you're good or add insert to the other table on 1 trigger.
I solved it without much complexities by having several having several transaction statements in the same file
START TRANSACTION;
SET #name = uuid();
INSERT INTO one(one_id,name) VALUES (Null,#name);
INSERT INTO two(two_id, name) VALUES (Null, #name);
COMMIT;
START TRANSACTION;
SET #name = uuid();
INSERT INTO one(one_id,name) VALUES (Null,#name);
INSERT INTO two(two_id, name) VALUES (Null, #name);
COMMIT;
/*
Etc
*/
CREATE TABLE IF NOT EXISTS `MyTable` (
`ID` SMALLINT NOT NULL AUTO_INCREMENT,
`Name` VARCHAR(50) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO MyTable (ID,Name) VALUES (ID=4,Name='xxx')
or
INSERT INTO MyTable (Name) VALUES (Name='xxx')
The problem is that both INSERT statements produce the entry (4,0). Why 0 instead of "xxx"?
UPDATE: Primary key changed.
This should do the job :
INSERT INTO MyTable (ID, Name) VALUES (4, 'xxx')
I'm pretty sure it would be something like this, instead...
INSERT INTO MyTable (Name) VALUES ('xxx')
No need for the Name= part, since you've already specified which column you wish to insert into with the first (Name) definition.
Because the expression Name='xxx' is false, hence evaluates as zero.
You use the column=expression method use in on duplicate key update clauses as described here, not in the "regular" section of inserts. An example of that:
insert into mytable (col1,col2) values (1,2)
on duplicate key update col1 = col1 + 1
You should be using the syntax:
INSERT INTO MyTable (ID,Name) VALUES (4,'xxx')
Is that syntax of Name='xxx' valid? Never seen it before, i assume it is seeing it as an unquoted literal, trying to convert it to a number and coming up with 0? I'm not sure at all
Try this:
INSERT INTO MyTable (Name) VALUES ('xxx')
This is because you should mention the name of the column in the values part. And also because you do not define you primary key correctly (airlineID is not part of the field list)
CREATE TABLE IF NOT EXISTS `MyTable` (
`ID` SMALLINT NOT NULL AUTO_INCREMENT,
`Name` VARCHAR(50) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
INSERT INTO MyTable (ID,Name) VALUES (4,'xxx')
INSERT INTO MyTable (Name) VALUES ('xxx')
Try this
INSERT INTO MyTable (ID,Name) VALUES (4,xxx)
For more Info just visit this link
This may have a really easy answer. I have done much database stuff for a while. I am trying to get the auto_increment value from one table inserted into the value on another table. is there an easy way of doing this. For eg i have done:
CREATE TABLE table_a (
id int NOT NULL AUTO_INCREMENT,
a_value varchar(4),
PRIMARY KEY (id)
);
CREATE TABLE table_b (
id int NOT NULL,
b_value varchar(15),
FOREIGN KEY (id) REFERENCES table_a (id)
);
Now i want to insert values into the table but I would like 'id' values for table_a and table_b to be the same. So far i have:
INSERT INTO table_a VALUES (NULL, 'foobar');
But I do not know how to go about extracting the auto_incermented 'id' number from table_a into the 'id' value of table_b. I have looked at SELECT #id = LAST_INSERT_ID() but can not get it to work.
You cannot do that at once. You'll have to first insert into the first table:
INSERT INTO table_a (a_value) VALUES ('foobar');
and then insert into the second using the generated id:
INSERT INTO table_b (id, b_value) VALUES (##IDENTITY, 'foobar');
LAST_INSERT_ID() and no need for the select statement part.