SQL split function

Posted on 9th of March 2009

Every time I need to work with SQL, it never ceases to amaze. The language is simply such an abortion in terms of development enviroments and simple programmer usability. Naturally, alot of this stems from my inexperience with the language. Mostly this post is just my own personal gripes with about SQL.

So, at work I find that I need a function which takes a variable number of GUIDs, and presents me with a compounded status integer, pulling status indicators for each GUID, and producing a single status. Should be simple right?

First off, I need this to be a function, so I can use it in SELECT constructs for a view. Why SQL has these random limitations on what can appear where, I’ll never know, but there it is. Then, the wild notion that I could pass in a variable number of GUIDs is killed fairly off quickly as SQL doesn’t support variadic functions.

So ok, I need to pass in the GUIDs in a single data structure. Of course, I know right off the bat, that I can’t pass tables (<sarcasm>why would anyone wanna do that anyway?</sarcasm>), so we’ll just pack a string with the GUIDs I need. I’ll live with myFunction("guid1,guid2,guid3"). So taking a look over the extremely rich string function library in SQL, I notice there’s no split function. So I need to write that first.

Writing an SQL string split function

So let’s just lay it out there. In all it’s glory.

CREATE FUNCTION dbo.Split (@String VARCHAR(500), @Delimeter CHAR(1))
RETURNS @Strings TABLE (String VARCHAR(500))
AS
BEGIN
    DECLARE @Position INT,
            @Next INT,
            @DelimeterWidth INT,
            @Substring VARCHAR(500)

    SET @Position = 1
    SET @Next = 1 -- set to 1, just to get past initial while cond
    SET @DelimeterWidth = LEN(@Delimeter)

    WHILE @Next > 0
    BEGIN
        SET @Next = CHARINDEX(@Delimeter, @String, @Position)
        IF (@Next-@Position) >= 1
        BEGIN
            SET @Substring = SUBSTRING(@String, 
                                       @Position+1, 
                                       @Next - @Position - @DelimeterWidth)
            INSERT INTO @Strings(String) VALUES(@Substring)
        END
        SET @Position = @Next
    END

    RETURN 
END

You’ll notice this returns a table. This table is btw also the only one you have to work with, no creating temporary tables! For some reason, you’re not allowed to create tables inside functions. So once you’re past the 1-indexed strings, you’re almost there . I know that 0 versus 1 indexing is a religious war onto itself, but given Cantor’s ordinals start at 0, it does not seem entirely silly either. For a language so focused on sets, it seems a strange choice.

They phoned it in

SQL sometimes really feels like they sat down, thought about SELECT, sub-selects, joins, and the related set algebra, and decided “nice work” and phoned the rest in. Even INSERT makes no sense, why do we need to seperate the column names from the values?

INSERT INTO tbl(col1, col2, col3) VALUES(val1, val2, val3)

UPDATE does it right.

UPDATE tbl SET col1=val1, col2=val2, col3=val3

Know what’s being sold as a exciting new feature in SQL 2008? Declaring and assigning values in one line!. This is how low the bar is set. SQL is obviously not going anywhere, but I can’t for the life fathom why it has to be so abysmal at almost everything, except the little core which it does so well.

Tags: , ,

3 Responses to “SQL split function”

  1. SQL Tutorials Says:

    Does anyone know if there is another language or set of commands beside SQL for talking with databases?

    I’m working on a project and am doing some research thanks

  2. murrmax Says:

    gosh! never blame language you don’t understand – that’s really your problem, not the language one.

    may be you should use more smarter server then M$ one, e.g. PostgreSQL has never had any problems with string split function, though not included in TheHolySqlStandard
    http://www.postgresql.org/docs/current/static/functions-string.html

    then just to note about INSERT – it was done right-o, because with that syntax you can insert multiple rows instead of just one by listing them one by one delimited by commas.

    and with UPDATE you can’t update multiple rows with different search keys, so here is different syntax to remind you about it. this is arguable though, so for example MySQL has its own extension to the INSERT syntax making it look as UPDATE, just to be a bit more friendly for copy-pasters, but that’s really does add headache when trying to port backend from MySQL to PostgreSQL.

  3. chamila Says:

    Check this also:
    http://chamilaw.blogspot.com/2011/05/concatenation-in-select-and-split.html

Leave a Reply