Would concatenating the data sent to the stored procedure work? I don't imagine sending more than 1000 detail lines at a time to the database.
do_movement('ACME','2:TNT,100||Anvil,5');
The 2 in front denotes the number of details to expect, might help with error catching. Just a thought.
This way the code would be responsible for formatting, but I could output SQLEXCEPTIONS and have everything happen in one true transaction.
Drawing heavily from this post: MySQL Split Comma Separated String Into Temp Table
Using the SPLIT_STR function from (also referenced in previous post): http://blog.fedecarg.com/2009/02/22/mysql-split-string-function/
CREATE FUNCTION SPLIT_STR(
x VARCHAR(255),
delim VARCHAR(12),
pos INT
)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
delim, '');
And then my functionality to parse N:s1|s2|..|sN
and check.
I could easily call SPLIT_STR again if I had something like N:s1,a1|s2,a2|..|sN,aN
BEGIN
DECLARE defined_quantity INT;
IF serial_numbers REGEXP '^[^0]{0,}[[:digit:]]+:.*$' = TRUE THEN -- check that we are indeed at least starting properly formatted.
SET defined_quantity = CONVERT(LEFT(serial_numbers,LOCATE(':',serial_numbers)-1), UNSIGNED);
IF defined_quantity <= 0 THEN
SIGNAL SQLSTATE '45006'
SET MESSAGE_TEXT = 'The quantity defined with the serial number list is <= 0.';
END IF;
SET serial_numbers = RIGHT(serial_numbers,LENGTH(serial_numbers) - LOCATE(':',@serial_numbers));
BEGIN
DECLARE a INT Default 0 ;
DECLARE str VARCHAR(255);
DECLARE q INT;
simple_loop: LOOP
SET a=a+1;
SET str=TRIM(SPLIT_STR(serial_numbers,"|",a));
IF str='' THEN
SET a=a-1; -- we ignore the last increment
LEAVE simple_loop;
END IF;
#Do Inserts into temp table here with str going into the row
INSERT INTO transaction_detail (transaction_id, serial_number,created_at,updated_at) VALUES(transaction_id, str,NOW(),NOW());
END LOOP simple_loop;
SELECT a, defined_quantity, quantity;
IF a <> defined_quantity OR a <> quantity OR defined_quantity <> quantity THEN
SIGNAL SQLSTATE '45007'
SET MESSAGE_TEXT = 'The quantities do not match for the serial numbers provided.';
END IF;
END;
ELSE
SIGNAL SQLSTATE '45005'
SET MESSAGE_TEXT = 'The serial number formatted list is not properly formatted. Please provide in "n:s1|s2|s3|...|sn" format.';
END IF;
END;