Skip to content

Instantly share code, notes, and snippets.

@georgepsarakis
Created March 3, 2013 21:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save georgepsarakis/5078273 to your computer and use it in GitHub Desktop.
Save georgepsarakis/5078273 to your computer and use it in GitHub Desktop.
Split (explode) function for MySQL. Simple version requires 3 arguments, S (the delimited string), DELIM (delimiter) and S_INDEX the index of the instance of substring between delimiters. The LTSPLIT, RTSPLIT & TSPLIT wrappers perform trimming on the returned substring, on leading, trailing & both characters respectively.
DROP FUNCTION IF EXISTS SPLIT;
DROP FUNCTION IF EXISTS _SPLIT;
DROP FUNCTION IF EXISTS RTSPLIT;
DROP FUNCTION IF EXISTS LTSPLIT;
DELIMITER //
-- Simple Split (no trim)
CREATE FUNCTION SPLIT(S CHAR(255), DELIM VARCHAR(30), S_INDEX TINYINT UNSIGNED) RETURNS VARCHAR(255)
BEGIN
RETURN _SPLIT(S, DELIM, S_INDEX, '', 0);
END//
-- Left-Trim Split
CREATE FUNCTION LTSPLIT(S CHAR(255), DELIM VARCHAR(30), S_INDEX TINYINT UNSIGNED, TRIM_CHARS VARCHAR(10)) RETURNS VARCHAR(255)
BEGIN
RETURN _SPLIT(S, DELIM, S_INDEX, TRIM_CHARS, 1);
END//
-- Right-Trim Split
CREATE FUNCTION RTSPLIT(S CHAR(255), DELIM VARCHAR(30), S_INDEX TINYINT UNSIGNED, TRIM_CHARS VARCHAR(10)) RETURNS VARCHAR(255)
BEGIN
RETURN _SPLIT(S, DELIM, S_INDEX, TRIM_CHARS, 2);
END//
-- Both-Trim Split
CREATE FUNCTION TSPLIT(S CHAR(255), DELIM VARCHAR(30), S_INDEX TINYINT UNSIGNED, TRIM_CHARS VARCHAR(10)) RETURNS VARCHAR(255)
BEGIN
RETURN _SPLIT(S, DELIM, S_INDEX, TRIM_CHARS, 0);
END//
CREATE FUNCTION _SPLIT(S CHAR(255), DELIM VARCHAR(30), S_INDEX TINYINT UNSIGNED, TRIM_CHARS VARCHAR(10), TRIM_TYPE TINYINT UNSIGNED)
RETURNS VARCHAR(255)
BEGIN
DECLARE L_INDEX TINYINT UNSIGNED DEFAULT 0;
DECLARE L_INDEX_2 TINYINT UNSIGNED DEFAULT 0;
DECLARE L_COUNTER TINYINT UNSIGNED DEFAULT 0;
DECLARE S_RETURN VARCHAR(255) DEFAULT '';
IF S_INDEX <= 0 THEN
RETURN '';
END IF;
SET @L_INDEX = LOCATE(DELIM, S);
SET @L_INDEX_2 = 0;
SET @L_COUNTER = 1;
IF ( @L_INDEX > 0 ) THEN
WHILE ( S_INDEX > 1 ) AND ( @L_COUNTER < S_INDEX ) DO
IF @L_INDEX > 0 THEN
SET @L_INDEX_2 = @L_INDEX;
END IF;
SET @L_INDEX = LOCATE(DELIM, S, @L_INDEX + 1);
SET @L_COUNTER = @L_COUNTER + 1;
END WHILE;
SET @DELIMITER_ADJUST = -1;
IF @L_INDEX = 0 THEN
SET @L_INDEX = LENGTH(s);
SET @DELIMITER_ADJUST = 0;
END IF;
SET @S_RETURN = SUBSTRING(S, @L_INDEX_2 + 1, @L_INDEX - @L_INDEX_2 + @DELIMITER_ADJUST);
IF TRIM_CHARS != '' THEN
CASE TRIM_TYPE
WHEN 1 THEN
SET @S_RETURN = TRIM(LEADING TRIM_CHARS FROM @S_RETURN);
WHEN 2 THEN
SET @S_RETURN = TRIM(TRAILING TRIM_CHARS FROM @S_RETURN);
ELSE
SET @S_RETURN = TRIM(BOTH TRIM_CHARS FROM @S_RETURN);
END CASE;
END IF;
RETURN @S_RETURN;
ELSE
RETURN 0;
END IF;
END //
DELIMITER ;
@georgepsarakis
Copy link
Author

Using the SUBSTRING_INDEX this would definitely be easier, omitting the WHILE loop, but where would be the fun in that?

Seriously, it is mainly for educational purposes (for myself first of all), exploring stored functions capabilities and language specifics.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment