Explain to me exactly what last_insert_id(expr) does - mysql

Here's my table:
CREATE TABLE `files` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`filename` varchar(255) NOT NULL,
`hash` varchar(255) NOT NULL,
`path` varchar(255) NOT NULL,
`mimetype` varchar(255) NOT NULL,
`size` int(10) unsigned NOT NULL,
`uploaded` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `filename` (`filename`,`hash`)
)
Let's say I insert something with filename "myFile" and hash "abc". Let's say it's not a duplicate and its id is 45.
Then let's say I insert some more queries so that the auto_increment index is higher now. For the sake of this example we'll say it's 70.
Now what happens when I do this:
insert into files(filename, hash, ...) values ("myFile", "abc", ...) ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id);
What actually happens? Will it update the id of the file I am currently inserting to be 45? Or will it change the ID of the existing row to be 70? In the case of the former does that mean the old row is written over? In the case of the latter how does it know to use 45?

If neither (filename, hash) does not match, the IODKU statement will act like
insert into files(filename, hash, ...) values ("myFile", "abc", ...)`
And your subsequent SELECT last_insert_id will get the new id.
Else it will do a mostly no-op UPDATE. Your SET contains only id=LAST_INSERT_ID(id), which does not change id. However, it does capture the existing value of id (45) so that your subsequent SELECT last_insert_id will get that value.
So, either way, you get the id of the row, whether it was INSERTed or UPDATEd.
(Yeah, the syntax is kinda kludgy.)

Related

MySQL null value not inserting

I have a query like
INSERT INTO support_users VALUES("1",,"2","1","4",,,"2017-05-06 20:24:36");
but new MySQL not inserting given error Error Code: 1064
but I changed it to
INSERT INTO support_users VALUES("1","","2","1","4",,,"2017-05-06 20:24:36");
working
but previous MySQL not having such an issue.how to solve that. without changing query
table definition
CREATE TABLE support_users (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`client` int(11) DEFAULT NULL,
`user` int(11) DEFAULT NULL,
`ticket` int(11) DEFAULT NULL,
`scope` int(11) DEFAULT NULL,
`notify` tinyint(1) DEFAULT NULL,
`email` tinyint(1) DEFAULT NULL,
`added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=46 DEFAULT CHARSET=utf8;
Firstly, respect the Datatype. If its Integer don't use quotes.
The right way to approach your problem will be use of NULL. So this works across any version of MySQL.
INSERT INTO support_users VALUES(1,NULL,2,1,4,NULL,NULL,'2017-05-06 20:24:36');
1)
Integer column values should not be quoted.
So "1" becomes 1
2)
Auto Increment values should not be manally given to the SQL -- let it work it out itself.
3)
Inserting NULL using the NULL keyword.
4)
Your date-time column is set in its definition to show the current date-time of the row being inserted when it is inserted. As you are inserting (rather than updating, etc.) you therefore do not need to include this data.
5)
It is easier for your sanity to also list which columns are being added to with the INSERT instruction.
6)
Use single quotes ' around string data not double quotes ("), when working directly with MySQL.
Result:
INSERT INTO support_users( `id`, `ticket`, `scope` , `notify`)
VALUES (1, 2,1,4);
This will cause errors if you try to insert twice, because you are forcing the Primary Key (id) to be 1. To avoid this, skip the Auto Increment (id) column value.
Or for clarity only; the full SQL:
INSERT INTO support_users VALUES (1, NULL, 2, 1, 4, NULL, NULL, '2017-05-06 20:24:36');
Skipping the Auto Increment (id) column value (as referenced above):
INSERT INTO support_users VALUES (NULL, NULL, 2, 1, 4, NULL, NULL, '2017-05-06 20:24:36');

Hash of two columns in mysql

I have a MYSQL table, with 5 columns in it:
id bigint
name varchar
description varchar
slug
Can I get MySQL to automatically generate the value of slug as a 256 Bit Hash of name+description?
I am now using PHP to generate an SHA256 value of the slug prior to saving it.
Edit:
By automatic, I mean see if it's possible to change the default value of the slug field, to be a computed field that's the sha256 of name+description.
I already know how to create it as part of an insert operation.
MySQL 5.7 supports generated columns so you can define an expression, and it will be updated automatically for every row you insert or update.
CREATE TABLE IF NOT EXISTS MyTable (
id int NOT NULL AUTO_INCREMENT,
name varchar(50) NOT NULL,
description varchar(50) NOT NULL,
slug varchar(64) AS (SHA2(CONCAT(name, description), 256)) STORED NOT NULL,
PRIMARY KEY (id)
) DEFAULT CHARSET=utf8;
If you use an earlier version of MySQL, you could do this with TRIGGERs:
CREATE TRIGGER MySlugIns BEFORE INSERT ON MyTable
FOR EACH ROW SET slug = SHA2(CONCAT(name, description));
CREATE TRIGGER MySlugUpd BEFORE UPDATE ON MyTable
FOR EACH ROW SET slug = SHA2(CONCAT(name, description), 256);
Beware that concat returns NULL if any one column in the input is NULL. So, to hash in a null-safe way, use concat_ws. For example:
select md5(concat_ws('', col_1, .. , col_n));
Use MySQL's CONCAT() to combine the two values and SHA2() to generate a 256 bit hash.
CREATE TABLE IF NOT EXISTS `mytable` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`description` varchar(50) NOT NULL,
`slug` varchar(64) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `mytable` (`name`,`description`,`slug`)
VALUES ('Fred','A Person',SHA2(CONCAT(`name`,`description`),256));
SELECT * FROM `mytable`
OUTPUT:
COLUMN VALUE
id 1
name Fred
description A Person
slug ea76b5b09b0e004781b569f88fc8434fe25ae3ad17807904cfb975a3be71bd89
Try it on SQLfiddle.

MySQL Auto increment not incrementing

I've created a table with 3 columns: postID, userID, and comment.
I have the postID as the primary key, and I am trying to make this auto-increment every time I add a new row to the table.
INSERT INTO CommentTable (postID, userID, comment) VALUES (DEFAULT, "test", "test")
When I run this query, it will run OK once but then when I run it again I get "1062 - Duplicate entry '0' for key 'PRIMARY'".
How do I properly set up an auto-increment primary key?
Here is the table structure:
DROP TABLE IF EXISTS `CommentTable`;
CREATE TABLE `CommentTable` (
`postID` int(10) NOT NULL,
`userID` varchar(10) NOT NULL,
`comment` varchar(1000) DEFAULT NULL,
PRIMARY KEY (`commentID`)
)
No need to put the field postID
INSERT INTO CommentTable (userID, comment) VALUES ("test", "test")
Edit your table as:
CREATE TABLE `CommentTable` (
`postID` int(10) NOT NULL AUTO_INCREMENT,
`userID` varchar(10) NOT NULL,
`comment` varchar(1000) DEFAULT NULL,
PRIMARY KEY (`postID`)
)
Recently I had the same issue where Auto Increment was not saved. It failed every time I tried to save it. My problem was that I had a record where the value was 0 instead of 1, so I updated that record value to a non-zero value, then tried saving the Auto Increment, and it worked.
The zero(0) value in the Primary Index field was causing the ALTER tablename to fail. Once it worked, I put the value back to 0.

alter table statment to insert duplicate into another table

I have a table in which there is a column name with SP varchar(10) NOT NULL. I want that column always to be unique so i created unique index on that column . My table schema as follows :
CREATE TABLE IF NOT EXISTS `tblspmaster` (
`CSN` bigint(20) NOT NULL AUTO_INCREMENT,
`SP` varchar(10) NOT NULL,
`FileImportedDate` date NOT NULL,
`AMZFileName` varchar(50) NOT NULL,
`CasperBatch` varchar(50) NOT NULL,
`BatchProcessedDate` date NOT NULL,
`ExpiryDate` date NOT NULL,
`Region` varchar(50) NOT NULL,
`FCCity` varchar(50) NOT NULL,
`VendorID` int(11) NOT NULL,
`LocationID` int(11) NOT NULL,
PRIMARY KEY (`CSN`),
UNIQUE KEY `SP` (`SP`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=10000000000 ;
Now i want that if anybody tries to insert duplicate record then that record should be inserted into a secondary table name tblDuplicate.
I have gone through this question MySQL - ignore insert error: duplicate entry but i am not sure that instead of
INSERT INTO tbl VALUES (1,200) ON DUPLICATE KEY UPDATE value=200;
can i insert duplicate row into another table ?
what changes needed to be done in main table scheme or index column ?
**Note : Data will be inserted by importing excel or csv files and excel files generally contains 500k to 800 k records but there will be only one single column **
I believe you want to use a trigger for this. Here is the MySQL reference chapter on triggers.
Use a before insert trigger. In the trigger, check if the row is a duplicate (maybe count(*) where key column value = value to be inserted). If the row is a duplicate, perform an insert into your secondary table.

insert update multiple rows mysql

I need to add multiple records to a mysql database. I tried with multiple queries and its working fine, but not efficient. So I tried it with just one query like below,
INSERT INTO data (block, length, width, rows) VALUES
("BlockA", "200", "10", "20"),
("BlockB", "330", "8", "24"),
("BlockC", "430", "7", "36")
ON DUPLICATE KEY UPDATE
block=VALUES(block),
length=VALUES(length),
width=VALUES(width),
rows=VALUES(rows)
But it always update the table (columns are block_id, block, length, width, rows).
Should I do any changes on the query with adding block_id also. block_id is the primary key. Any help would be appreciated.
I've run your query without any problem, are you sure you don't have other keys defined with the data table ? And also make sure you have 'auto increment' set for the id field. without auto_increment, the query always update existing row
***** Updated **********
Sorry I've mistaken your questions. Yes, with only one auto_increment key, you query will always insert new rows instead of updating existing one ( because the primary key is the only way to detect 'existing' / duplication ), since the key is auto_increment, there's never a duplication if the primary key is not given in the insert query.
I think what you want to achieve is different, you might want to set up composite unique key on all fields (i.e. block, field, width, rows )
By the way, i've set up a SQL fiddle for you.
http://sqlfiddle.com/#!2/e7216/1
The syntax to add the unique key:
CREATE TABLE `data` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`block` varchar(10) DEFAULT NULL,
`length` int(11) DEFAULT NULL,
`width` int(11) DEFAULT NULL,
`rows` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uniqueme` (`block`,`length`,`width`,`rows`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;