MySQL儲存過程中處理陣列 UDF程式碼分享

神諭丶發表於2015-12-01
在儲存過程中,傳入的引數經常可能會有陣列,而mysql沒有自帶處理陣列的方法或函式。

需求是這樣的:
傳入陣列形如:【aaa|bbb|ccc】
返回值形如:【aaa】、【bbb】、【ccc】


自己寫了一個自定義函式來完成上述需求:

使用例子:
  1. mysql> select FUN_GET_ELEMENT('第一個|第二個|第三個', '|', -1);
  2. +------------------------------------------------------------------------------+
  3. | FUN_GET_ELEMENT('第一個|第二個|第三個', '|', -1)                               |
  4. +------------------------------------------------------------------------------+
  5. | 上越界                                                                        |
  6. +------------------------------------------------------------------------------+
  7. 1 row in set (0.00 sec)
  8. mysql> select FUN_GET_ELEMENT('第一個|第二個|第三個', '|', 0);
  9. +------------------------------------------------------------------------------+
  10. | FUN_GET_ELEMENT('第一個|第二個|第三個', '|', 0)                               |
  11. +------------------------------------------------------------------------------+
  12. | 第一個                                                                       |
  13. +------------------------------------------------------------------------------+
  14. 1 row in set (0.00 sec)
  15. mysql> select FUN_GET_ELEMENT('第一個|第二個|第三個', '|', 1);
  16. +-----------------------------------------------------------------------------+
  17. | FUN_GET_ELEMENT('第一個|第二個|第三個', '|', 1)                               |
  18. +-----------------------------------------------------------------------------+
  19. | 第二個                                                                       |
  20. +-----------------------------------------------------------------------------+
  21. 1 row in set (0.01 sec)
  22. mysql> select FUN_GET_ELEMENT('第一個|第二個|第三個', '|', 2);
  23. +-----------------------------------------------------------------------------+
  24. | FUN_GET_ELEMENT('第一個|第二個|第三個', '|', 2)                               |
  25. +-----------------------------------------------------------------------------+
  26. | 第三個                                                                       |
  27. +-----------------------------------------------------------------------------+
  28. 1 row in set (0.00 sec)
  29. mysql> select FUN_GET_ELEMENT('第一個/第二個/第三個', '/', 5);
  30. +-----------------------------------------------------------------------------+
  31. | FUN_GET_ELEMENT('第一個/第二個/第三個', '/', 5)                               |
  32. +-----------------------------------------------------------------------------+
  33. | 下越界                                                                       |
  34. +-----------------------------------------------------------------------------+
  35. 1 row in set (0.00 sec)

其中傳入的值有三個:
第一個是要處理的陣列,
第二個是陣列內元素與元素的分隔符,比如 | /
第三個是要取出的元素索引,比如,0為第一個元素,1為第二個元素,以此類推,若輸入的索引沒有值,則返回上越界或下越界

FUN_GET_ELEMENT函式定義:

  1. DROP FUNCTION IF EXISTS FUN_GET_ELEMENT;

  2. delimiter ;;

  3. CREATE FUNCTION `FUN_GET_ELEMENT`(
  4.     `mainstring` varchar(1024) CHARSET utf8,
  5.     `mark` varchar(4) CHARSET utf8,
  6.     `count` int
  7.     )
  8.     RETURNS varchar(65) CHARSET utf8

  9. BEGIN

  10.     DECLARE v_string varchar(1024) CHARSET utf8 DEFAULT mainstring;
  11.     DECLARE v_element varchar(64) CHARSET utf8;
  12.     DECLARE i int DEFAULT 0;

  13.     IF(count > 0 and count <= FUN_GET_COUNT(mainstring, mark)) THEN
  14.         
  15.         WHILE(i < count) DO
  16.             
  17.             SET v_string = SUBSTRING(v_string, INSTR(v_string, mark) + 1, CHAR_LENGTH(v_string)) 
  18.             SET i = i + 1;
  19.         
  20.         END WHILE;
  21.     
  22.     END IF;
  23.     
  24.     IF(count < 0) THEN

  25.         SET v_element = '上越界';

  26.     ELSEIF (count < FUN_GET_COUNT(mainstring, mark)) THEN

  27.         SET v_element = SUBSTRING(v_string, 1, INSTR(v_string, mark) - 1);

  28.     ELSEIF (count = FUN_GET_COUNT(mainstring, mark)) THEN

  29.         SET v_element = v_string;

  30.     ELSE

  31.          SET v_element = '下越界';

  32.     END IF;

  33. RETURN(v_element);

  34. END;;

  35. delimiter ;

上述UDF呼叫了另外一個函FUN_GET_COUNT()這一個同樣也是自定義的。
用於獲取傳入的字串陣列的最大索引(元素數目-1)

該函式使用例子:
  1. mysql> select FUN_GET_COUNT('a|b|c','|');
  2. +----------------------------+
  3. | FUN_GET_COUNT('a|b|c','|') |
  4. +----------------------------+
  5. | 2                          |
  6. +----------------------------+
  7. 1 row in set (0.00 sec)


FUN_GET_COUNT定義:
  1. DROP FUNCTION IF EXISTS FUN_GET_COUNT;

  2. delimiter ;;

  3. CREATE FUNCTION `FUN_GET_COUNT`(
  4.     `mainstring` varchar(1024) CHARSET utf8,
  5.     `mark` varchar(200) CHARSET utf8
  6.     ) RETURNS int

  7. BEGIN
  8.     
  9.     DECLARE i int;
  10.     
  11.     SET i = (CHAR_LENGTH(mainstring) - CHAR_LENGTH(REPLACE(mainstring, mark, ''))) / CHAR_LENGTH(mark);
  12.     
  13.     RETURN i;

  14. END;;

  15. delimiter ;

(當然也可以將兩個UDF合併在一起。)


在儲存過程中使用起來也是十分方便:

  1. DROP PROCEDURE IF EXISTS PROC_TEST;

  2. delimiter ;;

  3. CREATE PROCEDURE `PROC_TEST`(
  4.     `text` varchar(64) CHARSET utf8
  5.     )

  6. BEGIN
  7.     
  8.     DECLARE v_text varchar(64) CHARSET utf8 DEFAULT text;
  9.     DECLARE v_element varchar(16) CHARSET utf8;
  10.     DECLARE v_element_count int DEFAULT 0;
  11.     DECLARE i int DEFAULT 0;

  12.     IF LENGTH(text) > 0 THEN

  13.         SET v_element_count = FUN_GET_COUNT(v_text, '|');
  14.         
  15.         WHILE (i <= v_element_count) DO

  16.             SET v_element = FUN_GET_ELEMENT(v_text, '|', i);
  17.             SELECT v_element;
  18.             SET i = i + 1;    

  19.         END WHILE;

  20.     END IF;

  21. END;;

  22. delimiter ;


陣列預設為字串陣列,若為數值陣列,則可在最後返回值通過系統函數CONVERT()轉換。
  1. mysql> SELECT CONVERT('1', SIGNED);
  2. +----------------------+
  3. | CONVERT('1', SIGNED) |
  4. +----------------------+
  5. | 1                    |
  6. +----------------------+
  7. 1 row in set (0.00 sec)


測試上述procedure:
  1. mysql> CALL PROC_TEST('test1|test2');
  2. +-----------+
  3. | v_element |
  4. +-----------+
  5. | test1     |
  6. +-----------+
  7. 1 row in set (0.00 sec)

  8. +-----------+
  9. | v_element |
  10. +-----------+
  11. | test2     |
  12. +-----------+
  13. 1 row in set (0.00 sec)

  14. Query OK, 0 rows affected (0.00 sec)


作者公眾號(持續更新)

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29773961/viewspace-1850718/,如需轉載,請註明出處,否則將追究法律責任。

相關文章