Unpredictable random number unique in table in MariaDB (not just incremental) - mysql

I have table of Users in MariaDB and I need to generate serviceNumber for each newly created user.
Example of this code: 865165
Only two requirements are:
Unique in User table
Unpredictable when creating user (Not based on AutoIncrement maybe?)
Is this possible with just database? Or I need to implement it in backend when creating user.

The only (theoretically) collision free solution would be to generate the serviceNumber with UUID() function (or maybe UUID_SHORT()).
The disadvantage of this solution is, that it can't be used in statement based replication, in this case you should create the value in your backend.

Steps 1-3 are setup steps:
Decide on how big you want the numbers to be. 6-digit numbers would let you have a million numbers.
Build a temp table t with all 6-digit numbers (t_num).
Build and populate a permanent table:
CREATE TABLE `u` (
id INT AUTO_INCREMENT NOT NULL,
t_num INT NOT NULL,
PRIMARY KEY(id)
);
INSERT INTO u (t_num)
SELECT t_num FROM t ORDER BY RAND();
4--Plan A You have an auto_inc id in the real table; simply join to u to get the random 6-digit number.
4--Plan B
BEGIN;
SELECT t_num FROM u ORDER BY id LIMIT 1 FOR UPDATE; -- to get the random id
DELETE FROM u ORDER BY id LIMIT 1; -- Remove it from the list of available ids

From MySQL reference manual:
To obtain a random integer R in the range i <= R < j, use the
expression FLOOR(i + RAND() * (j − i)). For example, to obtain a
random integer in the range the range 7 <= R < 12, use the following
statement: SELECT FLOOR(7 + (RAND() * 5));
Make the field holding serviceNumber uniqe and use the above math expression to generate serviceNumbers.

Related

Generating an auto generated number with 6 digits

I am generating new ids for my animals and i am running the following Query
SELECT concat('TZ',YEAR(CURDATE()),FLOOR(RAND() * 999999.99)) as ID , animalid FROM adggeth.view_allanimals;
my output for the following query is
# ID, animalid
'TZ2019703169', 'TZN000044001722'
'TZ2019914906', 'TZN000067976797'
'TZ2019465022', 'TZN000094299429'
'TZ2019580395', 'TZN000192792688'
my expected output
# ID, animalid
'TZ2019000001', 'TZN000044001722'
'TZ2019000002', 'TZN000067976797'
'TZ2019000003', 'TZN000094299429'
'TZ2019000004', 'TZN000192792688'
How can generate a random number for my id to achieve the expected output
After changes i get the following unexpected error
using
CONCAT('TZ', YEAR(CURDATE()), LPAD(#seq, 6, '0'))
'TZ2019000001', 'TZN000044001722'
'TZ2019000001', 'TZN000067976797'
'TZ2019000001', 'TZN000094299429'
'TZ2019000001', 'TZN000192792688'
It looks like you want IDs with the format TZYYYYNNNNNN where YYYY is the present year and NNNNNN is a guaranteed sequential number. Here you ask about how to generate the sequential number in a way where it's guaranteed to be unique.
If you were using Oracle you could use a sequence object. But who can afford Oracle?
So, you need to simulate the sequence object in MySQL. It's a little nasty, but here we go:
Create the following table:
CREATE TABLE sequence (
sequence_id BIGINT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`sequence_id`)
)
Then, each time you need a new sequence number, issue these three queries one after the other:
INSERT INTO sequence () VALUES ();
DELETE FROM sequence WHERE sequence_id < LAST_INSERT_ID();
SET #seq := LAST_INSERT_ID();
The third line places a guaranteed unique number into the #seq variable. This guarantee holds even if you have dozens of different client programs connected to your database generating sequence numbers. (The DELETE query merely keeps this otherwise pointless table from taking up too much space.)
Once you have #seq you can use it to generate your id values, something like this.
CONCAT('TZ', YEAR(CURDATE()), LPAD(#seq, 6, '0'))
To reset the sequence number at the first of the next year simply drop and recreate the sequence table.

How to generate random 10 digit number and place into database table?

I am working with a MySQL database that has a table of customers. One of the columns consist of phone_numbers varchar(10). My question is how can I create a simple loop that goes through all the customers and inserts a random phone numbers?
customer table
Use an UPDATE statement with the RAND and LPAD functions (docs: RAND, LPAD).
Example (generates numbers from 0000000000 to 9999999999): UPDATE table SET phone_numbers = LPAD(FLOOR(RAND() * 10000000000), 10, '0')

How to create random unique (not repeated) and fix length (9 digits) primary key in mysql database?

As the title, how to create a 9 digits number primary key which is random, unique, not repeated and from range 100000000 to 999999999?
And this method must be work on the godaddy server, seems godaddy have so many limitation.
I can only think of two reliable ways of creating unique numbers.
Use a systematic process, such as auto-incrementing, where you now the numbers are unique.
Store generated numbers in a table.
You want random numbers, so the first method could be applied using a pseudo-random number generator. But the second is probably simpler to implement.
It goes something like this:
create table numbers (
numberid int auto_increment primary key,
n varchar(10) not null unique
);
Then you need to create numbers using a loop. Do the following until it succeeds:
insert into numbers (n)
select cast((rand(*) * 900000000) + 1000000000 as varchar);
You can use last_inserted_id() to then get the most recent number inserted.
If pseudo-random is OK for you, you could create a trigger like this:
create trigger tr_setid before insert on mytable for each row
set new.id := (
select mod ((count(*) ^ 42) * 479001599 + 714320596, 900000000)+100000000
from mytable);
This system is not good if you also delete records from your table, as this solution assumes count(*) is one larger every time this trigger runs.
The multiplier is a prime and not a divisor of 900000000, guaranteeing that no duplicate number will be generated before all possible numbers have been visited.
The ^ operator is just mapping the count(*) so to make the generated series a bit less predictable.
With this trigger the first 10 records in the table will get these id values:
232387754
711389353
174384556
653386155
348394150
827395749
290390952
769392551
900374962
479376561

How to Generate unique random number?

Can someone tell me a good method for automatically placing a unique random number in a mysql database table when a new record is created.
I would create a table with a pool of numbers:
Create Table pool (number int PRIMARY KEY AUTO_INCREMENT);
Insert Into pool (),(),(),(),(),(),(),(),…;
And then define a trigger which picks one random number from that pool:
CREATE TRIGGER pickrand BEFORE INSERT ON mytable
FOR EACH ROW BEGIN
DECLARE nr int;
SET nr = (SELECT number FROM pool order by rand() limit 1);
DELETE FROM pool WHERE number = nr;
SET NEW.nr = nr;
END
In order to avoid concurrency issues you have to run queries in transactions. If performance becomes an issue (because of the slow order by rand()) you can change the way to select a random record.
Your criteria of unique and random are generally conflicting. You can easily accomplish one or the other, but both is difficult, and would require evaluating every row when testing a new potential number to insert.
The best method that meets your criteria is to generate a UUID with the UUID function.
The better choice would be to re-evaluate your design and remove one of the (unique, random) criteria.
Your best option is Autoincrement Column
see here for syntax
perhaps for Random number
try this!
select FLOOR(RAND() * 401) + 100
edit
SELECT FLOOR(RAND() * 99999) AS sup_rand
FROM table
WHERE "sup_rand" NOT IN (SELECT sup_rand FROM table)
LIMIT 1
Steps:
1.Generate a random number
2.Check if its already present
3.if not continue use the number
4.Repeat

optimizing query and optimizing table

`CREATE TABLE emailAddress
(
ID int NOT NULL AUTO_INCREMENT,
EMAILID varchar(255),
LastIDfetched int,
PRIMARY KEY (ID)
)
SELECT LastIDfetched WHERE ID=1; //say this value is x
SELECT EMAILID FROM emailAddress WHERE ID>x && ID<x+100;
UPDATE emailAddress SET LastIDfetched=x+100 WHERE ID=1;`
Basically I am trying to fetch all the email id from the database using multiple computers running in parallel, so that none of the email id is fetched by 2 computer.
What is the best way to do this?
there are millions of email id.
here for example i have shown that in one query 100 email id is fetched, it can vary depending on the need.
My suggestion would be to query by autoincrement ID's. You may not get an exact split of records across candidate computers if there are gaps in you autoincrement system, but this should be pretty good.
One approach is to simply look at the remainder of the autoincrement ID and grab all items of a certain value.
SELECT `EMAILID`
FROM `emailAddress`
WHERE ID % X = Y
Here X would equal the number of of computers you are using. Y would be an integer between 0 and X - 1 that would be unique to each machine running the query.
The con here is that you would not be able to use an index on this query, so if you need to do this query a lot, or on a production system taking traffic, it could be problmematic.
Another approach would be to determine the number of rows in the table and split the queries into groups
SELECT COUNT(`ID`) FROM `emailAddress`; // get row count we will call it A below
SELECT `EMAILID`
FROM `emailAddress`
WHERE ID
ORDER BY ID ASC
LIMIT (A/X) * Y, (A/X)
Here again X is number of machines, and Y is unique integer for each machine (from 0 to X -1)
The benefit here is that you are able to use index on ID. The downside is that you may miss some rows if the number of row grows between the initial query and the queries that retrieve data.
I don't understand your lastFetchedID field, but it looked like it was an unnecessary mechanitoin you were trying to use to achieve what can easily be achieved as noted above.