2014-02-08 137 views
3

我的應用程序通過一個存儲過程將每個http請求的詳細信息記錄到多個MySQL表中,存儲過程嚮應用程序返回一個唯一的請求ID。MySQL存儲過程 - 插入多行

CALL http_req('ip', 'url', 'method', 'timestamp', @error, @request_id); 

現在我也希望所有的HTTP請求頭登錄到一個表,在一個單獨的行中的每個標題:

CREATE TABLE `http_header` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, 
`request_id` INT(10) UNSIGNED NOT NULL, 
`name` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci', 
`value` VARCHAR(255) NOT NULL COLLATE 'utf8_unicode_ci', 
PRIMARY KEY (`id`)) 

的問題是,每個客戶都有不同的數量和類型頭。我還沒有找到一種方法將所有頭部細節傳遞給我的存儲過程,然後將它們插入上表中。

目前我有生成和存儲過程調用之後,從我的應用程序執行第二插入查詢保存標題:

INSERT INTO http_header (request_id, name, value) 
    VALUES (20153, 'cache-control', 'max-age=0'), 
      (20153, 'accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'), 
      (20153, 'accept-encoding', 'gzip,deflate,sdch'); 

是否是可能挽救第二個查詢,並從內部存儲的插入頭程序?就像將所有標題作爲單個字符串傳遞並解析存儲過程一樣?

回答

0

是的,這是可能的。 MySQL支持足夠的流量控制結構(REPEAT,IF)和字符串處理(LOCATE(),SUBSTRING()),以允許分割數據庫中的頭字符串。這是一個非常簡單的例子:

CREATE PROCEDURE http_req(IN ip CHAR(12), IN url VARCHAR(512), IN method CHAR(8), IN ts DATETIME, IN headers TEXT, OUT err INT, OUT request_id INT) 
BEGIN 
DECLARE loc INT; 
DECLARE hloc INT; 
DECLARE hdr TEXT DEFAULT NULL; 
DECLARE hval TEXT DEFAULT NULL; 
DECLARE s TEXT DEFAULT NULL; 

START TRANSACTION; 

INSERT INTO http_requests VALUES (NULL,INET_ATON(ip), url, method, ts); 
SELECT last_insert_id() INTO request_id; 

REPEAT 
    SET loc=LOCATE("\n",headers); 

    IF (loc = 0) THEN 
    SET s=headers; 
    ELSE 
    SET s=SUBSTRING(headers,1,loc-1); 
    SET headers=SUBSTRING(headers,loc+1); 
    END IF; 

    SET hloc=LOCATE(':',s); 

    IF (hloc = 0) THEN 
    SET hdr=s; 
    SET hval=''; 
    ELSE 
    SET hdr=SUBSTRING(s,1,hloc-1); 
    SET hval=SUBSTRING(s,hloc+1); 
    END IF; 

    INSERT INTO http_header VALUES (null,request_id,hdr,hval); 

UNTIL (loc=0) END REPEAT; 

COMMIT; 

END 

這個代碼有一些明顯的問題;就像您的標題包含換行符(\n)將被錯誤地存儲一樣。也沒有錯誤管理(例如err返回值沒有正確填充;沒有回滾)。解決這些問題已作爲練習留給讀者;)