Как выполнить одну и ту же хранимую процедуру несколько раз в MySQL или PHP? - PullRequest
1 голос
/ 27 марта 2011

В моем предыдущем вопросе . У меня есть решение проверить, какие данные были продублированы перед вставкой данных. Это хранимая процедура MySQL для проверки данных:

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'),...

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

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

Вызывает только первую строку хранимой процедуры.

Итак, как я могу проверить все записи в одном запросе одновременно!>

Большое спасибо !!

1 Ответ

0 голосов
/ 27 марта 2011

Может быть сделано с использованием хранимой процедуры с одним вызовом, но из-за того, что mysql не поддерживает параметры массива, это немного уродливо, так как мы должны передать через запятую строку user_id; file_id tokens. Единственная альтернатива - многократный вызов хранимой процедуры.

Полный скрипт здесь: 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 ;

Надеюсь, это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...