2011-03-27 42 views
1

在我的previous question。我有解決方案來檢查插入數據前重複哪些數據。這是MySQL存儲過程來檢查數據:如何在MySQL或PHP中多次執行相同的存儲過程?

DROP PROCEDURE IF EXISTS check_user_files; 
DELIMITER \\ 
CREATE PROCEDURE check_user_files(IN p_user_id INT,IN p_file_id CHAR(10)) 
    BEGIN 
     IF EXISTS(SELECT 1 FROM myTable WHERE user_id = p_user_id AND file_id= p_file_id) THEN 
      UPDATE myTable SET `file_status`=0 WHERE user_id=p_user_id AND file_id=p_file_id; 
     ELSE 
      INSERT INTO myTable(`user_id`,`file_status`,`file_id`) 
      VALUES (p_user_id,0,p_file_id); 
     END IF; 
    END \\ 
DELIMITER ; 

要調用存儲過程:

CALL check_user_files('1','12'); 

table [myTable]結構:

auto_id user_id file_id file_status 
1  1  12  1 
2  3  12  0 
3  1  17  1 
4  4  31  1 
5  1  41  0 
6  4  31  0 
7  1  18  1 
8  5  11  0 
9  1  10  0 

而且我的問題是,我必須多數據要同時檢查和插入。例如:

('1','12'),('2','14'),('3','16'),... 

但我不能調用存儲過程在同一時間在一個time.E.g檢查所有記錄:

CALL check_user_files('2','12'); 
CALL check_user_files('3','12'); 
... 

只調用存儲過程的第一道防線。

所以,我怎麼能檢查在一個查詢中的所有記錄在同一時間!>

非常感謝您!

回答

-1

可以使用單個調用存儲過程完成,但由於mysql不支持數組參數,它會變得有點醜,因爲我們必須傳遞逗號分隔的字符串user_id; file_id標記。唯一的另一種選擇是多次調用存儲過程。

這裏充分腳本:http://pastie.org/1722362

mysql> select * from user_files; 
+---------+---------+-------------+ 
| user_id | file_id | file_status | 
+---------+---------+-------------+ 
|  1 |  2 |   0 | 
|  3 |  6 |   0 | 
+---------+---------+-------------+ 
2 rows in set (0.00 sec) 

call check_user_files('user_id;file_id, user_id;file_id...'); 

call check_user_files('1;2, 2;4, 3;6, 4;10, 50;50, 1000;1, 1;10001'); 

mysql> select * from user_files; 
+---------+---------+-------------+ 
| user_id | file_id | file_status | 
+---------+---------+-------------+ 
|  1 |  2 |   0 | 
|  1 | 10001 |   0 | 
|  2 |  4 |   0 | 
|  3 |  6 |   0 | 
|  4 |  10 |   0 | 
|  50 |  50 |   0 | 
| 1000 |  1 |   0 | 
+---------+---------+-------------+ 
7 rows in set (0.00 sec) 

存儲過程

drop procedure if exists check_user_files; 

delimiter # 

create procedure check_user_files 
(
in p_users_files_csv varchar(4096) 
) 
proc_main:begin 

declare v_token varchar(255); 

declare v_done tinyint unsigned default 0; 
declare v_token_idx int unsigned default 1; 

declare v_user_id int unsigned default 0; 
declare v_file_id int unsigned default 0; 

    set p_users_files_csv = replace(p_users_files_csv, ' ',''); 

    if p_users_files_csv is null or length(p_users_files_csv) <= 0 then 
     leave proc_main; 
    end if; 

    -- the real ugly bit 

    -- split the string into user_id/file_id tokens and put into an in-memory table... 

    create temporary table tmp(
     user_id int unsigned not null, 
     file_id int unsigned not null 
    )engine = memory; 

    while not v_done do 

     set v_token = trim(substring(p_users_files_csv, v_token_idx, 
     if(locate(',', p_users_files_csv, v_token_idx) > 0, 
      locate(',', p_users_files_csv, v_token_idx) - v_token_idx, length(p_users_files_csv)))); 

     if length(v_token) > 0 then 

    set v_token_idx = v_token_idx + length(v_token) + 1; 

     set v_user_id = mid(v_token, 1, instr(v_token, ';')-1); 
     set v_file_id = mid(v_token, instr(v_token, ';')+1, length(v_token)); 

     insert into tmp (user_id, file_id) values(v_user_id, v_file_id); 
     else 
     set v_done = 1; 
     end if; 

    end while; 

    -- the nice bit - insert the new values 

    insert into user_files (user_id, file_id, file_status) 
    select 
    t.user_id, t.file_id, 0 as file_status 
    from 
    tmp t 
    left outer join user_files uf on t.user_id = uf.user_id and t.file_id = uf.file_id 
    where 
    uf.user_id is null and uf.file_id is null; 

    drop temporary table if exists tmp; 

end proc_main # 

delimiter ; 

希望這有助於