mysql table with varchar primary key field - mysql

I have create users table with following structure
CREATE TABLE `users` (
`id` varchar(36) NOT NULL,
`first_name` varchar(100) NOT NULL,
`last_name` varchar(100) NULL,
`email` varchar(100) NOT NULL,
`password` varchar(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I just want to auto filled id value when we insert new row.

If you do wish to generate a uuid in conjuntion with a trigger then your table design has some problems for example
drop table if exists t;
CREATE TABLE t (
`id` varchar(36) not null,
`first_name` varchar(100) NOT NULL,
`last_name` varchar(100) NULL,
`email` varchar(100) NULL,
`password` varchar(100) NULL ,
PRIMARY KEY (`id`)
) ;
drop trigger if exists t;
delimiter $$
create trigger t before insert on t
for each row
begin
set new.id = (select uuid());
end $$
delimiter ;
truncate table t;
insert into t (first_name) values (1),(2);
ERROR 1364 (HY000): Field 'id' doesn't have a default value
And you cannot use a default value because a duplicate error will occur when attempting to insert (2);
And you cannot change the not null to null because the primary key has to have a value.
You can change the id to null and change the primary key to a unique key
drop table if exists t;
CREATE TABLE t (
`id` varchar(36) null,
`first_name` varchar(100) NOT NULL,
`last_name` varchar(100) NULL,
`email` varchar(100) NULL,
`password` varchar(100) NULL ,
unique key (`id`)
) ;
drop trigger if exists t;
create trigger t before insert on t
for each row
set new.id = (select uuid());
truncate table t;
insert into t (first_name) values (1),(2);
select * from t;
+--------------------------------------+------------+-----------+-------+----------+
| id | first_name | last_name | email | password |
+--------------------------------------+------------+-----------+-------+----------+
| 874bd297-adeb-11e8-b404-b8aeed249e19 | 1 | NULL | NULL | NULL |
| 874bda27-adeb-11e8-b404-b8aeed249e19 | 2 | NULL | NULL | NULL |
+--------------------------------------+------------+-----------+-------+----------+
2 rows in set (0.00 sec)

Try id int(11) NOT NULL AUTO_INCREMENT,
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`first_name` varchar(100) NOT NULL,
`last_name` varchar(100) NULL,
`email` varchar(100) NOT NULL,
`password` varchar(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

You're trying to make a VARCHAR column auto incrementing. You Can't Do Thatâ„¢.
VARCHAR columns containing the text of integers are notoriously hard to ORDER correctly.
In MySQL, an automatically filled (autoincrementing) ID column must have an integer datatype.
Try changing
`id` varchar(36) NOT NULL,
to
`id` UNSIGNED BIGINT NOT NULL AUTO_INCREMENT,
(I chose UNSIGNED BIGINT because it's the largest integer available, and your choice of 36 in your VARCHAR(36) makes it look like you are expecting an enormous number of rows in this table. But UNSIGNED INT will give you four gigarows, which is probably enough.)
If you choose to use a trigger or some other means to generate the autoincrementing values for your VARCHAR ID column, you will have to do a lot of hard work with transactions to avoid the possibility of duplicate values.
If your client software must see this column as a VARCHAR, you can do it in a view or select. SELECT CAST(id AS VARCHAR(36)) id does it.

Assuming you want an automatically generated GUID for the primary key, this only seems possible in MySql using a trigger.
CREATE TRIGGER before_insert_users
BEFORE INSERT ON users
FOR EACH ROW
BEGIN
IF new.id IS NULL THEN
SET new.id = uuid();
END IF;
END
More information can be found here:
https://www.electrictoolbox.com/mysql-guid-uuid-default-column/

According to Cookbook 3.x:
Rather than using an auto-increment key as the primary key, you may
also use char(36). CakePHP will then use a unique 36 character UUID
(Text::uuid) whenever you save a new record using the Table::save()
method.
Means CakePHP automatically saves a unique 36 character UUID (Text::uuid) whenever you save a new record using the Table::save() method.
Just change
id varchar(36) NOT NULL
to
id char(36) NOT NULL
Hope this will help!

Related

MySql using a select and insert or update in an IF ELSE statement

In MySql is it possible to do something like this in a statement that is to be used in PHP and not in a stored procedure or anything else.
if(select count(*) from reports where empId = 9 and repId = 10 = 0,'Do an insert',' Update the existing row')// Just for example
I know about the INSERT ... ON DUPLICATE KEY UPDATE thing. But I cannot use that.
CREATE TABLE `reports` (
`genId` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NULL DEFAULT NULL,
`designation` VARCHAR(50) NULL DEFAULT NULL,
`empId` INT(11) NULL DEFAULT NULL,
`repId` INT(11) NULL DEFAULT NULL,
PRIMARY KEY (`genId`)
)

How to create INT field (not a primary key) who start at 1000 with auto_increment

I want to create a field INT(11) in my MYSQL Database who start at the value of 1000 and is incremented of 1 after each INSERT.
WARNING: THIS IS NOT A PRIMARY KEY
The DB is running with MYSQL 6.0 and InnoDB engine
Who can I achieve this, if it's possible ?
You can have an auto_increment column as long as it is defined as a key (it doesn't have to be a PRIMARY KEY). So for example:
CREATE TABLE auto_inc_test (
ID INT PRIMARY KEY,
IncValue INT AUTO_INCREMENT,
SomeData VARCHAR(50),
INDEX(IncValue)
);
ALTER TABLE auto_inc_test AUTO_INCREMENT = 1000;
(The ALTER TABLE line sets the next value for the AUTO_INCREMENT.)
If you then run the following insert (which, obviously, gives no value for the IncValue field):
INSERT INTO auto_inc_test (ID, SomeData)
VALUES (1, 'test 1'), (2, 'test 2'), (3, 'test3')
You'll get:
ID IncValue SomeData
1 1000 test 1
2 1001 test 2
3 1002 test 3
Try below code hope this should help you focus on the syntax part in below code -- KEY (id) --
CREATE TABLE IF NOT EXISTS `users`(
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`username` varchar(50) NOT NULL,
`password` varchar(100) NOT NULL,
`email` varchar(80) NOT NULL,
`type` int(11) NOT NULL,
`created` datetime NOT NULL,
`modified` datetime NOT NULL,
`status` enum('1','0') NOT NULL COMMENT '''0'' for inactive ''1'' for active',
PRIMARY KEY (`username`),
KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1000;

MySql - can BEFORE INSERT TRIGGER insert into 2 columns?

Can this trigger be changed so that the sortorder table gets 2 column values (sortOrderId, sortOrder) inserted?
How is the value of sortOrder found?
If it is known and can be inserted into image table then can it also be inserted into the sortorder table?
-- Trigger DDL Statements
DELIMITER $$
USE `nextcart`$$
CREATE
DEFINER=`root`#`localhost`
TRIGGER `nextcart`.`insert_sortorderid`
BEFORE INSERT ON `nextcart`.`image`
FOR EACH ROW
BEGIN
INSERT INTO sortorder SET sortOrderId = NULL, sortOrder = NEW.sortOrder;
SET NEW.sortOrderId = (SELECT LAST_INSERT_ID());
END;
$$
CREATE TABLE sortorder:
delimiter $$
CREATE TABLE `sortorder` (
`sortOrderId` int(11) NOT NULL AUTO_INCREMENT,
`sortOrder` tinyint(4) NOT NULL,
PRIMARY KEY (`sortOrderId`),
KEY `sort_order` (`sortOrderId`,`sortOrder`),
CONSTRAINT `fk_sortOrderId` FOREIGN KEY (`sortOrderId`) REFERENCES `image` (`imageId`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8$$
CREATE TABLE image:
delimiter $$
CREATE TABLE `image` (
`imageId` int(11) NOT NULL AUTO_INCREMENT,
`imageFileName` varchar(45) DEFAULT NULL,
`imagePath` varchar(255) DEFAULT NULL,
`imageTitle` varchar(100) DEFAULT NULL,
`imageAlt` varchar(100) DEFAULT NULL,
`imageWidth` int(11) DEFAULT NULL,
`imageHeight` int(11) DEFAULT NULL,
`classId` int(11) DEFAULT NULL,
`imageSizeId` tinyint(4) NOT NULL,
`isImageEnabled` bit(1) DEFAULT b'0',
`sortOrderId` int(11) DEFAULT NULL,
PRIMARY KEY (`imageId`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8$$
ERROR MESSAGE:
Error 1054: Unknown column 'sortOrder' in 'NEW' SQL Statement:
CREATE TRIGGER insert_sortorderid BEFORE INSERT ON image FOR EACH
ROW BEGIN INSERT INTO nextcart.sortorder SET sortOrderId = NULL,
sortOrder = NEW.sortOrder; SET NEW.sortOrderId = ( SELECT
LAST_INSERT_ID()); END; Error when running failback script. Details
follow. Error 1050: Table 'image' already exists SQL Statement: CREATE
TABLE image ( imageId int(11) NOT NULL AUTO_INCREMENT,
imageFileName varchar(45) DEFAULT NULL, imagePath varchar(255)
DEFAULT NULL, imageTitle varchar(100) DEFAULT NULL, imageAlt
varchar(100) DEFAULT NULL, imageWidth int(11) DEFAULT NULL,
imageHeight int(11) DEFAULT NULL, classId int(11) DEFAULT NULL,
imageSizeId tinyint(4) NOT NULL, isImageEnabled bit(1) DEFAULT
b'0', sortOrderId int(11) DEFAULT NULL, PRIMARY KEY (imageId)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
There is no column named sortOrder in the image table.
So, the reference to NEW.sortOrder (on the insert statement in the trigger) is invalid.
To answer your first question: No. Since there is no value supplied for that in the INSERT statement (which fires the BEFORE INSERT TRIGGER), you don't really have a source for that value.
The easy option is to provide a default value for it.
If you want to supply a value for the sortOrder column, then one option is to add a sortOrder column to the image table, and then the value can be supplied in the INSERT INTO image statement. Then it would available in the trigger.
(The purpose of the sortorder table is not at all clear.)

How do I reset primary key according to timestamp in MySQL table?

I know that I can reset the primary key in this way:
ALTER TABLE `users` DROP `id`;
ALTER TABLE `users` AUTO_INCREMENT = 1;
ALTER TABLE `users` ADD `id` int UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST;
But I'm wondering how I can adapt this to apply the primary key according to the timestamp in my timestamp column, i.e. the row with the oldest timestamp gets the value 1, the next oldest, the value 2, etc.
OUTPUT of SHOW CREATE TABLE
CREATE TABLE `tracks` (
`id` int(10) unsigned NOT NULL auto_increment,
`timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP,
`from_user` varchar(50) NOT NULL,
`source_filename` varchar(80) NOT NULL,
`uploaded_page` varchar(50) NOT NULL,
`operating_system` varchar(50) NOT NULL,
`browser` varchar(50) NOT NULL,
`os_browser_version` varchar(200) NOT NULL,
`title` varchar(100) NOT NULL,
`artist` varchar(60) NOT NULL,
`album` varchar(120) NOT NULL,
`genre` varchar(120) NOT NULL,
`format` varchar(10) NOT NULL,
`bitrate` mediumint(9) NOT NULL,
`conversion_needed` tinyint(1) NOT NULL COMMENT 'if not mp3, or higher than 192kbps',
`conversion_successful` tinyint(1) NOT NULL,
`art_extracted` tinyint(1) NOT NULL,
`art_location` varchar(200) NOT NULL,
`file_location` varchar(200) NOT NULL,
`status` varchar(500) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=96 DEFAULT CHARSET=utf8
Create a new table called users2 that has the same structure as users:
CREATE TABLE users2 LIKE users;
Then run this statment:
INSERT INTO users2
(col1, col2, ... coln)
SELECT col1, col2, ... coln
FROM users
ORDER BY your_timestamp
For your specific table:
INSERT INTO tracks2
(`timestamp`,`from_user`,`source_filename`,`uploaded_page`,`operating_system`,`browser`,`os_browser_version`,`title`,`artist`,`album`,`genre`,`format`,`bitrate`,`conversion_needed`,`conversion_successful`,`art_extracted`,`art_location`,`file_location`,`status`)
SELECT `timestamp`,`from_user`,`source_filename`,`uploaded_page`,`operating_system`,`browser`,`os_browser_version`,`title`,`artist`,`album`,`genre`,`format`,`bitrate`,`conversion_needed`,`conversion_successful`,`art_extracted`,`art_location`,`file_location`,`status`
FROM tracks
ORDER BY timestamp
I know you've already accepted an answer, but for the sake of posterity I want to chime in with a simpler solution. MySQL allows you to re-order the rows of a table using ALTER TABLE...ORDER BY..., so you can easily do this by adding one more ALTER TABLE statement to your original example:
ALTER TABLE `users` DROP COLUMN `id`;
ALTER TABLE `users` ORDER BY `timestamp`;
ALTER TABLE `users` AUTO_INCREMENT = 1;
ALTER TABLE `users` ADD COLUMN `id` int UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST;

SQL Code for INSERT while checking of multiple keys for duplicates

I have the following table:
CREATE TABLE IF NOT EXISTS `customer_list` (
`id` INT AUTO_INCREMENT,
`first_name` char(4) NOT NULL,
`last_name` varchar(80) NOT NULL,
`phone` varchar(50) NOT NULL,
`province` varchar(50) NOT NULL,
`country` varchar(30) NOT NULL,
`start_date` TIMESTAMP NOT NULL,
`end_date` TIMESTAMP NOT NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
I want to be able to insert into this table with the only restriction being that first_name, last_name and phone CANNOT be the same. If they are the same I want some sort of error returned to warn the end user that the record already exists - No insert/update/replace action is performed.
The key here is the INSERT statement must somehow check 3 fields for duplication. The error must only return if ALL 3 fields are duplicates. IE. 1 or 2 out of the 3 are allowed to be duplicates and still be entered.
Is this possible with one INSERT statement?
Try:
alter table customer_list add unique index(first_name, last_name, phone);