2014-09-24 2 views
0

У меня относительно большая (для меня) хранимая процедура, над которой я работаю, несет ответственность за сохранение инвентарных значений всякий раз, когда происходит «движение».Хранимые процедуры MySQL с подробной таблицей и транзакциями

Первоначально у меня были все проверки и вставки, происходящие на PHP, но я чувствовал, что количество вещей, которые должны произойти в базе данных, сделало его более управляемым, поместив его в хранимую процедуру и отказав разрешениям INSERT/UPDATE для этих столы.

Так что в стороне от истории, мне любопытно, есть ли способ запустить подготовленный оператор для хранимой процедуры, в которой я могу передать несколько значений, которые будут вставляться в таблицу подробностей.

Например, предположим, что я хочу вставить следующие данные в родительскую и дочернюю записи.

"ACME", "TNT", 100 
"ACME", "Anvil", 5 

Родитель запись будет содержать ACME, и дети записи будут иметь подробности TNT, 100 и Anvil, 5.

Возможно ли каким-либо образом передать эти данные в одну хранимую процедуру?

Причина, по которой я надеюсь сделать это за один проход, допустим, у нас недостаточно TNT, я не хочу, чтобы исходная родительская запись была вставлена, если вся транзакция не может быть выполнена.

+0

почему бы не просто начать/совершить транзакцию с помощью PHP, если у вас уже есть код, который работает? – Bulat

+0

Я хочу, чтобы звонки из разных приложений выполняли определенные проверки для обеспечения целостности данных. Я могу легко отправить ошибку и отменить транзакцию, если флаг/требование клиента не удовлетворяются данными, предоставленными хранимой процедуре. Что-то, что будет зависеть от того, кто его реализовал в PHP/Java/и т. Д. –

+0

Ну, если вы хотите создать поверх многократно используемого кода, я, хотя обычно использую уровень сервиса для этого, а не для создания вашего приложения внутри базы данных , Тогда вы можете передать его в JSON или XML без проблем. – Bulat

ответ

0

Будет ли конкатенация данных, отправленных на хранимую процедуру, работать? Я не думаю, что вы отправляете более 1000 строк подробностей за один раз в базу данных.

do_movement('ACME','2:TNT,100||Anvil,5'); 2 в начале означает количество деталей, которое следует ожидать, может помочь с обнаружением ошибок. Просто мысль.

Таким образом, код будет отвечать за форматирование, но я мог бы выводить SQLEXCEPTIONS, и все происходит в одной истинной транзакции.

Рисунок сильно от этого поста: MySQL Split Comma Separated String Into Temp Table

Использование функции SPLIT_STR из (также ссылка в предыдущем посте): 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, ''); 

И тогда моя функциональность для анализа N:s1|s2|..|sN и проверить.

Я мог бы легко назвать SPLIT_STR снова, если я что-то вроде 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; 
Смежные вопросы