[adsense id=”0514458240″ width=”468″ height=”60″]
It should be noted that anyone who needs this type of solution should look closely at their data model and have this corrected.
A question was raised where a field in the table contains a comma separated list of entries. These entries should be accessible. Through a set of queries. Let us call these comma separated values attributes. The data model should consist of a separate table with a unique identifier and the various attributes in question. But for argument sake let us imagine that this is not available and that we need to generate a temporary table consisting of these attribute values.
mysql> create table data (id int auto_increment primary key, attributes varchar(255)); Query OK, 0 rows affected (0.02 sec) mysql> insert into data(attributes) values ('One,Two,Three,Four'),('a,b,c,d,e'),('Dog,Cat,Horse'); Query OK, 3 rows affected (0.00 sec) Records: 3 Duplicates: 0 Warnings: 0 mysql> select * from data; +----+--------------------+ | id | attributes | +----+--------------------+ | 1 | One,Two,Three,Four | | 2 | a,b,c,d,e | | 3 | Dog,Cat,Horse | +----+--------------------+ 3 rows in set (0.00 sec)
Let us now create a stored procedure which takes each of these records and adds them to a temporary table that we have created.
drop procedure if exists sp_data; delimiter $$ create procedure sp_data() begin declare done int default 0; declare lattributes varchar(255); declare lid integer; declare idx integer; declare cdata cursor for select id, attributes from data; declare continue handler for not found set done := 1; create temporary table if not exists tdata(id int, attribute varchar(100)); open cdata; read_loop: loop fetch cdata into lid, lattributes; if done then leave read_loop; end if; attr_loop: loop set idx := locate(',', lattributes); if idx > 0 then set @lattribute := substring(lattributes, 1, idx-1); else set @lattribute := lattributes; end if; INSERT INTO tdata(id, attribute) VALUES (lid, @lattribute); if idx = 0 then leave attr_loop; end if; set lattributes := trim(substring(lattributes, idx+1)); end loop; end loop; end; $$ delimiter ;
As we have a temporary table the results are only visible for the duration of the session. Afterwhich these are removed by the MySQL server.
Calling this function on this table we get:
mysql> select * from tdata; ERROR 1146 (42S02): Table 'test.tdata' doesn't exist mysql> call sp_data; Query OK, 1 row affected (0.00 sec) mysql> select * from data; +----+--------------------+ | id | attributes | +----+--------------------+ | 1 | One,Two,Three,Four | | 2 | a,b,c,d,e | | 3 | Dog,Cat,Horse | +----+--------------------+ 3 rows in set (0.00 sec) mysql> select * from tdata; +------+-----------+ | id | attribute | +------+-----------+ | 1 | One | | 1 | Two | | 1 | Three | | 1 | Four | | 2 | a | | 2 | b | | 2 | c | | 2 | d | | 2 | e | | 3 | Dog | | 3 | Cat | | 3 | Horse | +------+-----------+ 12 rows in set (0.00 sec)
One response to “MySQL – Splitting fields”
[…] data model. As an exercise I have put together some code and explanation on how this can be done here __________________ Ronan Cashell Senior Oracle/MySQL DBA […]