Here's an approach tested with PostgreSQL and verified to work. It's a bit tortured, so performance might be ... interesting.
CREATE AGGREGATE array_cat_agg (
BASETYPE = anyarray,
SFUNC = array_cat,
STYPE = anyarray
);
SELECT array_to_string(array_cat_agg(a), ' ')
FROM regexp_matches('234kjh23ljkgh34klj2345klj', '(\D*)(\d*)', 'g') x(a);
We need array_cat_agg
because regular array_agg
can't aggregate arrays of arrays.
Alternately, a form of @davidrac's approach that'll work with PostgreSQL and probably perform significantly better (though I haven't tested) is:
SELECT regexp_replace(
regexp_replace(
'234kjh23ljkgh34klj2345klj', '(\d)(\D)', '\1 \2', 'g'
), '(\D)(\d)', '\1 \2', 'g');
This is executing the replacement in two passes. First it's inserting a space where series of digits end and series of non-digits begin. Then in another pass it's inserting spaces where series of non-digits end and series of digits begin.
Update: Here's an improved formulation:
SELECT trim(regexp_replace('234kjh23ljkgh34klj2345klj', '(?!\d)(\D+)|(?!\D)(\d+)', '\1\2 ', 'g'));