Guten Tag,
ich bin relativ neu mit MySQL und versuche gerade eine procedure zu erstellen, welche garantiert das eine eindeutige Seriennummer erstellt wird, wenn mehrere Clienten die procedure gleichzeitig aufrufen.
Die Datenbank hat nur einen Wert, welcher Primary ist und somit nur einmal vorkommen soll.
Mein Ansatz wäre, wenn bei INSERT ein duplicate error auftritt, wird die schleife noch einmal durchgelaufen.
Anhand des @@ROWCOUNTS wollte ich erkennen, ob INSERT erfolgreich war, jedoch hab ich bemerkt, das dies von MySQL nicht unterstützt wird und jetzt bin ich ratlos, wie sich das lösen lässt. Ich hoffe jemand kann mir dabei helfen.
Des weiteren gibt die Zeile ```
SELECT MAX(SERIAL) FROM serials WHERE serial LIKE CONCAT(article_number, date_format(now(), '%y%m%d'), '%');``` einen Syntax-Error aus, obwohl ich denn Abruf selbst getested habe und dieser funktioniert.
Ich wäre dankbar wenn mir jemand helfen könnte.
ich bin relativ neu mit MySQL und versuche gerade eine procedure zu erstellen, welche garantiert das eine eindeutige Seriennummer erstellt wird, wenn mehrere Clienten die procedure gleichzeitig aufrufen.
Die Datenbank hat nur einen Wert, welcher Primary ist und somit nur einmal vorkommen soll.
Mein Ansatz wäre, wenn bei INSERT ein duplicate error auftritt, wird die schleife noch einmal durchgelaufen.
Anhand des @@ROWCOUNTS wollte ich erkennen, ob INSERT erfolgreich war, jedoch hab ich bemerkt, das dies von MySQL nicht unterstützt wird und jetzt bin ich ratlos, wie sich das lösen lässt. Ich hoffe jemand kann mir dabei helfen.
Code:
-- Delete this procedure if it already exists to overwrite it with the new one
DROP PROCEDURE IF EXISTS `GenerateUniqueSerialNumber`;
-- Change delimiter to // so that procedure is handled as one statement
DELIMITER //
-- Create procedure for serial number generation
CREATE PROCEDURE GenerateUniqueSerialNumber(IN article_number VARCHAR(6), OUT serial_number VARCHAR(16))
BEGIN
-- Counter variable for serial number in numerical and string form
DECLARE serial_counter_num INT DEFAULT 1;
DECLARE serial_counter_str VARCHAR(4) DEFAULT '0001';
-- Continue procedure if duplicate error occurs
DECLARE CONTINUE HANDLER FOR 1062
DECLARE retry_count INT DEFAULT 0;
DECLARE max_retries INT DEFAULT 10; -- You can adjust the maximum number of retries as needed
-- Retry loop to handle concurrency
RETRY_BLOCK: LOOP
-- Increment retry count
SET retry_count = retry_count + 1;
-- Check if a serial number for current date already exists
IF EXISTS (SELECT * FROM serials WHERE serial LIKE CONCAT(article_number, date_format(now(), '%y%m%d'), '%')) THEN
-- Search table for latest entry for given article number and current date
SET serial_number = SELECT MAX(SERIAL) FROM serials WHERE serial LIKE CONCAT(article_number, date_format(now(), '%y%m%d'), '%');
-- Get the last four chars from the serial number
SET serial_counter_str = RIGHT(serial_number, 4);
-- Convert to int
SET serial_counter_num = CAST(serial_counter_str AS UNSIGNED);
-- Inkrement serial counter
SET serial_counter_num = serial_counter_num + 1;
-- Check if serial counter is within bounds (1 - 9999)
IF serial_counter_num > 9999 THEN
SET serial_counter_num = 1;
END IF;
-- Convert to string with four digits (leading zeros)
SET serial_counter_str = LPAD(serial_counter_num, 4, '0');
END IF;
-- Create new serial number
SET serial_number = CONCAT(article_number, date_format(now(), '%y%m%d'), serial_counter_str);
-- Insert incremented serial number into database and ignore execution errors
INSERT IGNORE INTO serials(serial) VALUES (serial_number);
-- Affected rows should be >0 if commit was successful
IF @@ROWCOUNT > 0 THEN
-- Exit loop
LEAVE RETRY_BLOCK;
END IF;
-- Check if the maximum retry count is reached
IF retry_count >= max_retries THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Failed to generate unique serial number after maximum retries';
END IF;
-- Wait for a short period before retrying (you may need to adjust the sleep time)
DO SLEEP(0.1);
END LOOP RETRY_BLOCK;
-- And of procedure
END //
-- Reset delimiter to default
DELIMITER ;
-- Call function
CALL GenerateUniqueSerialNumber('123456');
SELECT * FROM GenerateUniqueSerialNumber();
SELECT MAX(SERIAL) FROM serials WHERE serial LIKE CONCAT(article_number, date_format(now(), '%y%m%d'), '%');``` einen Syntax-Error aus, obwohl ich denn Abruf selbst getested habe und dieser funktioniert.
Ich wäre dankbar wenn mir jemand helfen könnte.