2014-02-08 105 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返回值没有正确填充;没有回滚)。解决这些问题已作为练习留给读者;)