How do I generate a unique sequential number in java? - mysql

I need to create an entity form which has unique identification column in the database and its not a primary key column and I need to display that in the form creation page. I've set this column as UNIQUE and not null. Now whenever I create a new user, employee or any entity I need to generate a sequence number like in this format and display it in the form,
ID_001, ID_002 ... ID_00N and so on.
EMP_001, EMP_002 ... EMP_00N and so on.
and when the three digit sequence number reaches the max limit of 999. The seqence number should generate the number as four digits until 9999 is reached and the employee code will be like EMP_1000. So when I get the last insert id when creating the form, it will not work if more than one user is creating simultaneously and there would be a conflict. I thought about creating a new table like sequence_generator. Where I store key-value pair of the the entity-last insert id. So whenver next insert happens I can read from this table and increment by 1 for new sequence numbers.
So How do I best implement this sequence generating which is also Unique in Java/MySql/Mybatis/Spring?

I would create my own sequencing implementation using triggers. I am not very familiar with mysql. So, take my examples as a pseudo-code. Your trigger would look like:
Create a table with no auto-increment. Example:
CREATE TABLE EMPLOYEE (
ID CHAR(30), NAME CHAR(30)
)
Create a trigger with the logic to auto-increment your columns. Similar to:
CREATE TRIGGER EMPLOYEE_SEQUENCE BEFORE INSERT ON EMPLOYEE
FOR EACH ROW
BEGIN
SET #PREPENDED_ZEROS = '';
SET #ID_AS_NUMBER = CAST(SUBSTRING(ID,3) AS INT) + 1;
IF #ID_AS_NUMBER < 10 THEN
SET #PREPENDED_ZEROS = '00';
ELSEIF #ID_AS_NUMBER < 100 THEN
SET #PREPENDED_ZEROS = '0';
END IF;
SET NEW.ID = 'EMP_' || #PREPENDED_ZEROS || #ID_AS_NUMBER;
END;

Related

mysql auto increment from 00001 - 99999 and reset the value every year

My first aim is to generate customer reference code automaticaly everytime when I insert a new customer
so when it shown in my nodejs it should be : "MS2200001"
So my idea is set id from customer table (mysql) with auto increment and zerofill (int)
length = 5
So I can get id 00001
and insert to another column named as "customer reference"
with
("MS" + (2022)+ "00001")
And I am trying to reset the counter to 00001 again if become 2023,2024,2025 etc.
How can I archive this in phpmyadmin or I should chnage my idea?
Use trigger-generating technique and additional MyISAM table with secondary AUTO_INCREMENT column in PRIMARY KEY.
An example:
-- base table for complete identifier generation
CREATE TABLE base_for_complete_id (
`year` YEAR,
id INT AUTO_INCREMENT,
PRIMARY KEY (`year`, id)
) ENGINE = MyISAM;
-- create trigger which will generate complete identifier
CREATE TRIGGER generate_complete_id
BEFORE INSERT ON maintable
FOR EACH ROW
BEGIN
DECLARE tmp INT;
-- insert row into base table
INSERT INTO base_for_complete_id (`year`) VALUES (YEAR(NEW.created_at));
-- store id generated for current year
SET tmp = LAST_INSERT_ID();
-- save generated complete identifier into main table
SET NEW.complete_id = CONCAT('prefix_', YEAR(NEW.created_at), '_', tmp);
-- clear excess rows from base table
DELETE FROM base_for_complete_id WHERE `year` = YEAR(NEW.created_at) AND id < tmp;
END
DEMO fiddle
If you need to format id part of generated value with leading zeros then use LPAD() function, for example SET tmp = LPAD(LAST_INSERT_ID(), 5, 0);.
Caution! If the value for generated number exceeds 99999 then it will be truncated, and only 5 leading digits will be stored.

unknow system variable: "new.id" is not recognized

Let's say 6,7,8 are all taken, and l tried to insert data with id = 6. The purpose of the trigger is to find the next available number. However, MySQL does not recognize new.id
Or, can l alter auto_increment's value?
Why am l doing this? Because in OracleDB, the sequence generator will increment(and eventually find that available number) whereas MySQL's sequence generator won't increment if a duplicate primary key is generated somehow.
tried to replace "new.id = #valid" with "alter table wooster_brush_employee auto_increment = #valid" in trigger, but it did not work.
create table wooster_brush_employee(
id int primary key auto_increment,
first_name varchar(15),
last_name varchar(20),
username varchar(10),
password varchar(15),
email varchar(30)
);
delimiter //
create trigger validate_id before insert on wooster_brush_employee
for each row
set #old = last_insert_id();
set #valid = last_insert_id();
call wooster_brush_employee_id_validator(#old, #valid);
set NEW.id = #valid;
end;
delimiter;
I believe that your whole approach here is off kilter, and you don't even need to use this trigger. The point of an auto increment column, in either MySQL or Oracle, is that the database handles the problem of finding the next available number in the sequence. While the auto increment contract does not guarantee that the next value found will be greater than every value already in the column, it does guarantee that the next value will be unique.
So, if you want to make use of MySQL's auto increment functionality, then next time you insert, simply omit id from the column list:
INSERT INTO wooster_brush_employee (first_name, last_name, username, password, email)
VALUES
('Jon', 'Skeet', 'jonskeet', '*****", 'jon.skeet#google.com');
Since id was omitted, MySQL will automatically generate the next value in the sequence behind the scenes.

Before trigger that checks if new value is greater than value in another table

This is what I have so far:
DELIMITER //
CREATE TRIGGER insert_tr BEFORE INSERT ON ordline FOR EACH ROW
BEGIN
IF (NEW.Qty > ProdQ) THEN
CALL ErrorMsg ('Not enough quantity to cover this order');
END IF;
END // DELIMITER ;
Where "ProdQ" is a column from another table, and "NEW.Qty" is the integer value being passed in. However, I get an error saying ProdQ isn't in the table "ordline". How can I check if the new value is greater than a value in a different table?
Thanks!
Assuming the ProdQ is stored in another table, called Product, and both the ordline and Product tables contain a key column called ProdID, then you could do something like this:
if (NEW.Qty >
(select ProdQ from Product where Product.ProdID = NEW.ProdID limit 0,1)) THEN
In summary, you need to compare the NEW.Qty value against another value, not against a column. The Product table contains potentially many rows, one for each Product, and you need to tell the trigger which of these rows it needs to take the ProdQ value from to compare against the NEW.Qty.

creating triggers and functions in postgresql

how can i create a trigger function before adding/updating,the function should check records that have the same id (i.e comparison by id with existing objects that have the same property as the temporary_object)If a record with the id is found, then that entry is set to the time_dead, and then it adds an entry containing the corresponding values ​​of the attributes found in that record (except those that are set for a new record), when time_dead is empty then time_create of a new time is equal to that time at the current moment . Thus,a new record time_create is like the time_dead's ancestor.
If a record with that id is found then it is added to the database with the establishment as the time_create of the current time.
for example here is a simple explanation(just for explanation purposes)
id time_create time-dead student amount
1 06.12 07.12 henry 500
1 07.12 henry 1000
so if a student called henry with id 1 entered a room at 06.12 and left at 07.12 the next time he enters another room again time_dead will be equal to time_create(so time_dead of old entry and time_create of new entry - will be equal)
these are my tables below in sql format
CREATE TABLE temporary_object
(
id integer NOT NULL,
time_create timestamp without time zone NOT NULL,
time_dead timestamp without time zone,
CONSTRAINT temporary_object_pkey PRIMARY KEY (id, time_create)
)
CREATE TABLE persons
(
fname text,
fsurname text,
)
INHERITS (temporary_object)
CREATE TABLE rooms
(
roomnum integer,
course integer,
passport text,
students_number text
)
INHERITS (temporary_object)
this is what i am trying to do but im afraid i do not know how to finish it but im 100% not right may some help out
CREATE TRIGGER trigger2
BEFORE INSERT OR UPDATE
ON persons
FOR EACH ROW
EXECUTE PROCEDURE func1();
and this is the function
CREATE OR REPLACE FUNCTION func1() RETURNS TRIGGER AS $persons$
DECLARE
time_create integer;
time_dead timestamp;
id timestamp;
BEGIN
IF (TG_OP = 'INSERT') THEN
time_create=
I can't tell you what I'm missing from your question, but I try to answer what I think I understood.
Row level triggers can access the version of the row affected with the NEW and OLD variables (depending on TG_OP). In this case, you can use NEW:
CREATE OR REPLACE FUNCTION func1()
RETURNS TRIGGER AS
$persons$
DECLARE
i integer;
BEGIN
IF TG_OP = 'INSERT'
THEN
UPDATE persons
SET time_dead = NEW.time_create
WHERE
id = NEW.id -- we are looking for the same ID
AND time_dead IS NULL
;
ELSE -- UPDATE
-- do here something
END IF;
END;
$persons$
LANGUAGE plpgsql;
This is only a starter, modify it to your needs.

remove gaps in auto increment

Say I have a MySQL table with an auto incrementing id field, then I insert 3 rows. Then, I delete the second row. Now the id's of the table go 1,3. Can I get MySQL to correct that and make it 1,2 without having to write a program to do so?
MySQL won't let you change the indexing of an Auto-Index column once it's created. What I do is delete the Auto-Index column and then add a new one with the same name, mysql will index the newly generated column with no gaps. Only do this on tables where the Auto-Index is not relevant to the rest of the data but merely used as a reference for updates and deletes.
For example I recently did just that for a table containing proverbs where the Auto-Index column was only used when I updated or deleted a proverb but I needed the Auto-Index to be sequential as the proverbs are pulled out via a random number between 1 and the count of the proverbs, having gaps in the sequence could have led to the random number pointing to a non-existant index.
HTH
Quoting from The Access Ten Commandments (and it can be extensible to other RDBMS: "Thou shalt not use Autonumber (or Auto Incremental) if the field is meant to have meaning for thy users".
The only alternative I can think of (using only MySQL) is to:
Create a trigger that adds the row number to a column (not the primary key)
Create a procedure to delete rows and update the row number (I couldn't make this work with triggers, sorry)
Example:
create table tbl_dummy(
id int unsigned not null auto_increment primary key,
row_number int unsigned not null default 0,
some_value varchar(100)
);
delimiter $$
-- This trigger will add the correct row number for each record inserted
-- to the table, regardless of the value of the primary key
create trigger add_row_number before insert on tbl_dummy
for each row
begin
declare n int unsigned default 0;
set n = (select count(*) from tbl_dummy);
set NEW.row_number = n+1;
end $$
-- This procedure will update the row numbers for the records stored
-- after the id of the soon-to-be-deleted record, and then deletes it.
create procedure delete_row_from_dummy(row_id int unsigned)
begin
if (select exists (select * from tbl_dummy where id = row_id)) then
update tbl_dummy set row_number = row_number - 1 where id > row_id;
delete from tbl_dummy where id = row_id;
end if;
end $$
delimiter ;
Notice that you'll be forced to delete the records one by one, and you'll be forced to get the correct primary key value of the record you want to delete.
Hope this helps