26

I looking for a function like regexp_split_to_table, but our db is version 8.2.9, so it doesn't have it. I'm really only splitting on a space, so a string like

how now brown cow

would return

+------+
|Column|
+------+
|how   | 
|now   | 
|brown | 
|cow   |
+------+

is there a simple function that can handle this, or something I have to write myself?

1
  • regexp_split_to_table was introduced in 8.3, so you were just shy of having the feature :- ( Commented Dec 5, 2022 at 21:13

2 Answers 2

52

You can split an array to a resultset by using the unnest function, and you can turn a string literal into an array by using the string_to_array function. Combine both and you get this:

alvherre=# select unnest(string_to_array('the quick lazy fox', ' '));
 unnest 
--------
 the
 quick
 lazy
 fox
(4 filas)

Since 8.2 does not have UNNEST, you can write it in PostgreSQL like this:

create or replace function unnest(anyarray) returns setof anyelement
language sql as $$
   select $1[i] from generate_series(array_lower($1, 1),
                                     array_upper($1, 1)) as i;
$$; 
Sign up to request clarification or add additional context in comments.

Comments

3

I think you'll have to RETURNS SET or RETURNS TABLE yourself.

Updated answer: using PL/pgSQL:

pg=> CREATE OR REPLACE FUNCTION string_to_rows(text) RETURNS SETOF TEXT AS $$ 
  DECLARE
    elems text[];      
  BEGIN
    elems := string_to_array($1, ' ');
    FOR i IN array_lower(elems, 1) .. array_upper(elems, 1) LOOP
      RETURN NEXT elems[i];
    END LOOP;
    RETURN;
  END
$$ LANGUAGE 'plpgsql';
CREATE FUNCTION

pg=> SELECT "Column" FROM string_to_rows('how now brown cow') d("Column");
 Column 
--------
 how
 now
 brown
 cow
(4 rows)

Original answer: using PL/perl:

pg=> CREATE LANGUAGE plperl; 
CREATE LANGUAGE

pg=> CREATE FUNCTION psplit_to_rows(text) RETURNS SETOF TEXT AS $$
pg$>   for my $t (split ' ', $_[0]) { return_next $t; }
pg$>   undef;
pg$> $$ LANGUAGE plperl;
CREATE FUNCTION

pg=> SELECT "Column" FROM psplit_to_rows('how now brown cow') d("Column");
 Column 
--------
 how
 now
 brown
 cow
(4 rows)

Obviously you can extend this to handle a delimiter of your choosing, etc. (Note, I'm not sure if you really wanted that column named "Column", requiring identifier quoting to avoid keyword clash, but, there you are.)

3 Comments

I don't have plperl to work with, can this easily be done w/ plpgsql?
@pilcrow, Your function works great, but I'm having a problem when I try to execute a query like [select string_to_rows(column) from table]. Keeps giving me the error: ERROR: set-valued function called in context that cannot accept a set. Looking around online I see I need to call like [select * from string_to_rows(text)]. Is it possible to call this function and pass in a set? ie [select * from string_to_rows(select col from table)].
@veilig, you're trying to put a set or table into a SQL scalar context. A separate question, showing us what data you're starting with and what result set you want, is, I think, appropriate.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.