How do I make auto generated id with unique random order. Is it possible ? I need my output shows like whenever new row added id field shows random numbers not in sequence order. How can I modify this script.
Script:
CREATE TABLE `student`.`new_table` (
`id` INT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(45) NOT NULL,
PRIMARY KEY (`id`));
If I understood you correctly this what you want:
UUID_SHORT() Return an integer-valued universal identifier
UUID() Return a Universal Unique Identifier (UUID)
http://dev.mysql.com/doc/refman/5.1/en/miscellaneous-functions.html
Related
I have a database. As you can see the primary key is an auto_increment and is also unique. I read that publically sharing a row's primary key of a table to the public is unsafe. I want to assign each row in customers a unique ID that I can publically share. How can I do this without having to specify each time what the public_id is in the INSERT statement? The database should automatically find a unique ID to assign to that row just like it does for id because of auto_increment.
CREATE TABLE customers (
id int primary key auto_increment,
name varchar(32) not null,
-- public_id (an ID I can give to the public to uniquely identify this row
);
INSERT INTO customers (name) VALUES ('Bob'), ('Sarah'), ('Bob');
Well, here's one way:
CREATE TABLE customers (
id int primary key auto_increment,
name varchar(32) not null,
public_id char(36) not null unique default uuid()
);
Note that the manual says:
Warning
Although UUID() values are intended to be unique, they are not necessarily unguessable or unpredictable. If unpredictability is required, UUID values should be generated some other way.
So this is simple, and maybe will float your goat, but we can also try better:
CREATE TABLE customers (
id int primary key auto_increment,
name varchar(32) not null,
public_id char(24) not null unique default to_base64(random_bytes(18))
);
This will be a nice and dense identifier, but it will have characters + and / which don't play well with URLs. You can encode them, of course, but if you want to go one lazier, you can also do this:
CREATE TABLE customers (
id int primary key auto_increment,
name varchar(32) not null,
public_id char(32) not null unique default hex(random_bytes(16))
);
Mind you, the identifier will get quite a bit longer this way.
To get the best of both worlds, we can do this, at the expense of a really long default value:
CREATE TABLE customers (
id int primary key auto_increment,
name varchar(32) not null,
public_id char(24) not null unique default replace(replace(to_base64(random_bytes(18)), '+', '_'), '/', '-')
);
Also note that messing around with MD5()/SHA()/SHA1()/SHA2() is no better than just generating a random hex string with a given length.
I'm trying to create a trigger with sql so that When I insert a row in Point I insert before it a row in PointAbs.
CREATE TABLE PointAbs (
ID INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
X INTEGER NOT NULL,
Y INTEGER NOT NULL
);
CREATE TABLE Point(
ID INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
Name VARCHAR(50) ,
IDPointAbs INTEGER NOT NULL,
FOREIGN KEY (IDPointAbs) REFERENCES PointAbs(ID) ON DELETE CASCADE
);
the problem is that I need to provide "X" and "Y" for PointAbs and "Name" for Point at the same time. Ho can I achieve that?
I could use a JDBC functionality to get the last insertedID but I don't like it that way.
It seems like the relation is 1 to 1, as you have to create a new PointAbs for each Point. Unless you have another table that relates to PintAbs, there will be one PointAbs for each Point. If you don't need two separated objects, you can state X and Y as an index of Point:
CREATE TABLE Point(
ID INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
Name VARCHAR(50) ,
IDPointAbs INTEGER NOT NULL,
X INTEGER NOT NULL,
Y INTEGER NOT NULL,
INDEX INDEX_X_Y ON Point(X,Y)
);
Of course, this might not be possible nor desirable in your design.
As you can't send parameters to the trigger like the X and Y values, your best option is to use a single transaction for both inserts.
BEGIN;
INSERT INTO PointAbs(X,Y) VALUES (10,15);
INSERT INTO Point(Name, IDPointAbs) VALUES ('Fancy Name', LAST_INSERT_ID(PointAbs));
COMMIT;
You can control the insertions using the programming language of the system back-end, but as there is no specific language mentioned other than mysql, I won't enter into details.
Here's what I'm trying to do:
CREATE TABLE IF NOT EXISTS hashes (
id int NOT NULL AUTO_INCREMENT,
text varchar(50) NOT NULL,
hash varchar(64) NOT NULL AS (SHA2(CONCAT(text), 256) STORED,
PRIMARY KEY (id)
) DEFAULT CHARSET=utf8;
And then I want to run an insert like this:
INSERT INTO `hashes` (`text`) VALUES ('testing');
From the research I've done, the id should be automatically generated since auto_increment is enabled, so I don't need to define it in the insert query.
From my CREATE TABLE query, the hash should be automatically generated based upon the data entered into the text field. However, when I run the CREATE TABLE command I get an error with this line:
hash varchar(64) NOT NULL AS (SHA2(CONCAT(text), 256) STORED
I'm just wanting the hash to be automatically generated similar to how CURRENT_TIMESTAMP will automatically generate the current time by default.
What am I doing wrong?
It seems you have syntax error. You should write NOT NULL after SHA2 hash function. Please try:
CREATE TABLE IF NOT EXISTS hashes (
id int NOT NULL AUTO_INCREMENT,
text varchar(50) NOT NULL,
hash varchar(64) AS (SHA2(CONCAT(text), 256)) STORED NOT NULL ,
PRIMARY KEY (id)
) DEFAULT CHARSET=utf8;
INSERT INTO `hashes` (`text`) VALUES ('testing');
You don't need to declare your hash column as NOT NULL. It's based on another NOT NULL column, text, so the hash will naturally be NOT NULL as well.
You also have forgotten a closing parenthesis.
hash varchar(64) AS (SHA2(CONCAT(text), 256) STORED,
1 2 3 3 2 ^
You need another closing paren where I indicated ^.
If you already have the table filled by some content, you can Alter it with :
ALTER TABLE `page` ADD COLUMN `hash` char(64) AS (SHA2(`content`, 256)) AFTER `content`
This solution will add hash column right after the content one, make hash for existing and new records too. Unique index can be added to prevent insertion of large content duplicates.
I have created a table empInfo as follow
CREATE TABLE empInfo (
empid INT(11) PRIMARY KEY AUTO_INCREMENT ,
firstname VARCHAR(255) DEFAULT NULL,
lastname VARCHAR(255) DEFAULT NULL
)
Then I run below Insert statements :-
INSERT INTO empInfo VALUES(NULL , 'SHREE','PATIL');
INSERT INTO empInfo(firstname,lastname) VALUES( 'VIKAS','PATIL');
INSERT INTO empInfo VALUES(NULL , 'SHREEKANT','JOHN');
I thought first or Third SQL will fail as empid is PRIMARY KEY and We are trying to insert NULL for empid .
But MYSQL proved me wrong and all 3 queries ran successfully .
I wanted to know Why it is not failing when trying to insert NULL in empid column ?
Final Data available in table is as below
empid firstname lastname
1 SHREE PATIL
2 VIKAS PATIL
3 SHREEKANT JOHN
I can figure out that it has something releted to AUTO_INCREMENT But I am not able to figure out reason for it . Any pointers on this .
This behaviour is by design, viz inserting 0, NULL, or DEFAULT into an AUTO_INCREMENT column will all trigger the AUTO_INCREMENT behaviour.
INSERT INTO empInfo VALUES(DEFAULT, 'SHREEKANT','JOHN');
INSERT INTO empInfo VALUES(NULL, 'SHREEKANT','JOHN');
INSERT INTO empInfo VALUES(0, 'SHREEKANT','JOHN');
and is commonplace practice
Note however that this wasn't however always the case in versions prior to 4.1.6
Edit
Does that mean AUTO_INCREMENT is taking precedance over PRIMARY KEY?
Yes, since the primary key is dependent on the AUTO_INCREMENT delivering a new sequence prior to constraint checking and record insertion, the AUTO_INCREMENT process (including the above re-purposing of NULL / 0 / DEFAULT) would need to be resolved prior to checking PRIMARY KEY constraint in any case.
If you remove the AUTO_INCREMENT and define the emp_id PK as INT(11) NULL (which is nonsensical, but MySql will create the column this way), as soon as you insert a NULL into the PK you will get the familiar
Error Code: 1048. Column 'emp_id' cannot be null
So it is clear that the AUTO_INCREMENT resolution precedes the primary key constraint checks.
It is exactly because of the auto increment. As you can see, no empid values are null in the db. That is the purpose of auto increment. Usually you would just not include that column in the insert, which is same as assigning null
As per the documentation page:
No value was specified for the AUTO_INCREMENT column, so MySQL assigned sequence numbers automatically. You can also explicitly assign 0 to the column to generate sequence numbers. If the column is declared NOT NULL, it is also possible to assign NULL to the column to generate sequence numbers.
So, because you have an auto increment null-allowed field, it ignores the fact that you're trying to place a NULL in there, and instead gives you a sequenced number.
You could just leave it as is since, even without the not null constraint, you can't get a NULL in there, because it will auto-magically convert that to a sequenced number.
Or you can change the column to be empid INT(11) PRIMARY KEY AUTO_INCREMENT NOT NULL if you wish, but I still think the insert will allow you to specify NULLs, converting them into sequenced numbers in spite of what the documentation states (tested on sqlfiddle in MySQL 5.6.6 m9 and 5.5.32).
In both cases, you can still force the column to a specific (non-zero) number, constraints permitting of course.
CREATE TABLE empInfo (
empid INT(11) PRIMARY KEY AUTO_INCREMENT NOT NULL,
firstname VARCHAR(255) DEFAULT NULL,
lastname VARCHAR(255) DEFAULT NULL
)
Not sure but i think it will work :)
I am using a VARCHAR as my primary key. I want to auto increment it (base 62, lower/upper case, numbers), However, the below code fails (for obvious reasons):
CREATE TABLE IF NOT EXISTS `campaign` (
`account_id` BIGINT(20) NOT NULL,
`type` SMALLINT(5) NOT NULL,
`id` VARCHAR(16) NOT NULL AUTO_INCREMENT PRIMARY KEY
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
however, this works:
CREATE TABLE IF NOT EXISTS `campaign` (
`account_id` BIGINT(20) NOT NULL,
`type` SMALLINT(5) NOT NULL,
`id` VARCHAR(16) NOT NULL PRIMARY KEY
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
What is the best way to keep track of incrementation of 'id' myself? (Since auto_increment doesn't work). Do i need to make another table that contains the current iteration of ID? Or is there a better way to do this?
EDIT: I want to clarify that I know that using INT is a auto_increment primary key is the logical way to go. This question is in response to some previous dialogue I saw. Thanks
you have to use an INT field
and translate it to whatever format you want at select time
example of a solution to your problem:
create a file with a unique number and then increment with a function.
the filename can be the prefix and the file binary content represent a number.
when you need a new id to the reg invoque the function
Example
String generateID(string A_PREFIX){
int id_value = parsetoInt(readFile(A_PREFIX).getLine())
int return_id_value = id_value++
return return_id_value
}
where "A_PREFIX-" is the file name wich you use to generate the id for the field.
Or just create a sequence and maintain the pk field using the sequence to generate the primary key value with nextval function. And if perf is an issue, use cache on sequence.
But as others have stated, this is sub-optimal, if your primary key contains a numbered sequence then it's better to use int and auto-increment.
I don't see a use case where pk has to auto-increment but be a varchar data type, it doesn't make sense.
Assuming that for reasons external to the database, you do need that varchar column, and it needs to autoIncrement, then how about creating a trigger that grabs the existing autoIncrement value and uses Convert() to convert that value into a VarChar, dropping the VarChar into the field of interest. As mentioned in a previous answer, you could concatenate the table-name with the new varChar value, if there is some advantage to that.