2014-09-24 36 views
0

我有一個相對較大的(對我來說)存儲過程,我正在負責維護庫存值,只要發生「移動」。MySQL存儲過程詳細表和交易

我原本以PHP方式進行所有檢查和插入操作,但我覺得需要在數據庫中發生的事情數量使它更容易控制,方法是將它放入存儲過程並拒絕這些對象的INSERT/UPDATE權限表。

因此,歷史擱置,我很好奇,如果有一種方法來運行存儲過程的準備好的語句,我可以傳入多個值將被插入到一個細節表。

例如,我們假設我想將以下數據插入父代和子代記錄。

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

父記錄將包含ACME,和孩子們記錄將有TNT, 100Anvil, 5細節。

是否有可能以某種方式將此數據傳遞到單個存儲過程?

我希望能夠一次完成這件事的原因是讓我們說我們沒有足夠的TNT可用,我不想插入原始父記錄,除非整個事務可以發生。

+0

爲什麼不開始/通過PHP提交事務,如果您已經有工作的代碼? – Bulat 2014-09-25 00:09:45

+0

我想確保來自不同應用程序的調用執行某些檢查以保持數據完整性。如果提供給存儲過程的數據不符合客戶標誌/要求,我可以輕鬆地拋出錯誤並回滾事務。有些東西會依賴於誰在PHP/Java /等中實現它。 – 2014-09-25 18:31:34

+0

好吧,如果你想在可重用代碼的基礎上構建,我通常使用服務層而不是在數據庫中構建你的應用程序。然後你可以通過JSON或XML傳遞它沒問題。 – Bulat 2014-09-25 21:09:55

回答

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;