120

It appears that MySQL doesn't have array variables. What should I use instead?


There seem to be two alternatives suggested: A set-type scalar and temporary tables. The question I linked to suggests the former. But is it good practice to use these instead of array variables? Alternatively, if I go with sets, what would be the set-based idiom equivalent to foreach?

Community
  • 1
  • 1
einpoklum
  • 118,144
  • 57
  • 340
  • 684

24 Answers24

98

Well, I've been using temporary tables instead of array variables. Not the greatest solution, but it works.

Note that you don't need to formally define their fields, just create them using a SELECT:

DROP TEMPORARY TABLE IF EXISTS my_temp_table;
CREATE TEMPORARY TABLE my_temp_table
    SELECT first_name FROM people WHERE last_name = 'Smith';

(See also Create temporary table from select statement without using Create Table.)

einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • 1
    Ohhh :o I didn't know SQL had this!! The tables are only alive for the scope of al queries being run. NEAT! – Igbanam Dec 17 '14 at 10:51
  • 2
    @Yasky, That's provided you do not reuse connection. Because indeed it will last for the **entire** session. – Pacerier Apr 16 '15 at 06:07
  • And you can't reuse a temporary table. So it's not very useful. – John May 20 '15 at 18:18
  • @John: How do you mean? – einpoklum May 20 '15 at 19:19
  • 1
    @einpoklum - https://dev.mysql.com/doc/refman/5.0/en/temporary-table-problems.html – John May 29 '15 at 19:13
  • 4
    @John: Yeah, well, you _can_ reuse it, but not in the same query. – einpoklum May 29 '15 at 23:58
  • @einpoklum. No, unfortunately that did not work for me. I was trying two separate queries, which was the whole point of making a temporary table. The other funny part to me, was that the user has to have insert rights on the db for a temporary table, so the whole thing is a big hassle for seemingly no benefit (to me). I ended up just making a normal table. – John Jun 01 '15 at 16:29
  • 1
    If you are reusing connections, you generally should DROP TEMPORARY TABLE IF EXISTS my_temp_table; before creating it. – Aurast Nov 17 '20 at 17:33
49

You can achieve this in MySQL using WHILE loop:

SET @myArrayOfValue = '2,5,2,23,6,';

WHILE (LOCATE(',', @myArrayOfValue) > 0)
DO
    SET @value = ELT(1, @myArrayOfValue);
    SET @myArrayOfValue= SUBSTRING(@myArrayOfValue, LOCATE(',',@myArrayOfValue) + 1);

    INSERT INTO `EXEMPLE` VALUES(@value, 'hello');
END WHILE;

EDIT: Alternatively you can do it using UNION ALL:

INSERT INTO `EXEMPLE`
(
 `value`, `message`
)
(
 SELECT 2 AS `value`, 'hello' AS `message`
 UNION ALL
 SELECT 5 AS `value`, 'hello' AS `message`
 UNION ALL
 SELECT 2 AS `value`, 'hello' AS `message`
 UNION ALL
 ...
);
Omesh
  • 27,801
  • 6
  • 42
  • 51
43

Try using FIND_IN_SET() function of MySql e.g.

SET @c = 'xxx,yyy,zzz';

SELECT * from countries 
WHERE FIND_IN_SET(countryname,@c);

Note: You don't have to SET variable in StoredProcedure if you are passing parameter with CSV values.

Himalaya Garg
  • 1,525
  • 18
  • 23
  • Beware of the length limits, which can be quite low: https://stackoverflow.com/q/2567000/1333493 – Nemo Jan 08 '18 at 07:24
  • I like this answer because I used in combination with a delete query SET @Ids = 'e6cf8a49-0143-4286-9528-819ccd951c9e,cc34bde0-e361-4e57-a51c-ebdac0cd4bd6'; DELETE FROM my_table WHERE find_in_set(id, @Ids); – Francesco Sep 05 '22 at 10:29
33

Nowadays using a JSON array would be an obvious answer.

Since this is an old but still relevant question I produced a short example. JSON functions are available since mySQL 5.7.x / MariaDB 10.2.3

I prefer this solution over ELT() because it's really more like an array and this 'array' can be reused in the code.

But be careful: It (JSON) is certainly much slower than using a temporary table. Its just more handy. imo.

Here is how to use a JSON array:

SET @myjson = '["gmail.com","mail.ru","arcor.de","gmx.de","t-online.de",
                "web.de","googlemail.com","freenet.de","yahoo.de","gmx.net",
                "me.com","bluewin.ch","hotmail.com","hotmail.de","live.de",
                "icloud.com","hotmail.co.uk","yahoo.co.jp","yandex.ru"]';

SELECT JSON_LENGTH(@myjson);
-- result: 19

SELECT JSON_VALUE(@myjson, '$[0]');
-- result: gmail.com

And here a little example to show how it works in a function/procedure:

DELIMITER //
CREATE OR REPLACE FUNCTION example() RETURNS varchar(1000) DETERMINISTIC
BEGIN
  DECLARE _result varchar(1000) DEFAULT '';
  DECLARE _counter INT DEFAULT 0;
  DECLARE _value varchar(50);

  SET @myjson = '["gmail.com","mail.ru","arcor.de","gmx.de","t-online.de",
                "web.de","googlemail.com","freenet.de","yahoo.de","gmx.net",
                "me.com","bluewin.ch","hotmail.com","hotmail.de","live.de",
                "icloud.com","hotmail.co.uk","yahoo.co.jp","yandex.ru"]';

  WHILE _counter < JSON_LENGTH(@myjson) DO
    -- do whatever, e.g. add-up strings...
    SET _result = CONCAT(_result, _counter, '-', JSON_VALUE(@myjson, CONCAT('$[',_counter,']')), '#');

    SET _counter = _counter + 1;
  END WHILE;

  RETURN _result;
END //
DELIMITER ;

SELECT example();
SeparateReality
  • 880
  • 11
  • 17
  • Are you saying ELT is slower or JSON is slower ? – Kanagavelu Sugumar Jul 20 '18 at 12:56
  • 2
    @Kanagavelu Sugumar: At the time of writing JSON is definitely slower. I edited the answer to make that clearer. – SeparateReality Sep 15 '18 at 08:36
  • In MySQL 8, for the [JSON_VALUE](https://dev.mysql.com/doc/refman/8.0/en/json-search-functions.html#function_json-value) function, you can't use a variable in place of a string literal for the second argument which is the JSON path. See my alternative solution [here](https://stackoverflow.com/a/76495016/4409950). – Tyler Jun 17 '23 at 06:41
19

Dont know about the arrays, but there is a way to store comma-separated lists in normal VARCHAR column.

And when you need to find something in that list you can use the FIND_IN_SET() function.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
wormhit
  • 3,687
  • 37
  • 46
14

I know that this is a bit of a late response, but I recently had to solve a similar problem and thought that this may be useful to others.

Background

Consider the table below called 'mytable':

Starting table

The problem was to keep only latest 3 records and delete any older records whose systemid=1 (there could be many other records in the table with other systemid values)

It would be good if you could do this simply using the statement

DELETE FROM mytable WHERE id IN (SELECT id FROM `mytable` WHERE systemid=1 ORDER BY id DESC LIMIT 3)

However this is not yet supported in MySQL and if you try this then you will get an error like

...doesn't yet support 'LIMIT & IN/ALL/SOME subquery'

So a workaround is needed whereby an array of values is passed to the IN selector using variable. However, as variables need to be single values, I would need to simulate an array. The trick is to create the array as a comma separated list of values (string) and assign this to the variable as follows

SET @myvar = (SELECT GROUP_CONCAT(id SEPARATOR ',') AS myval FROM (SELECT * FROM `mytable` WHERE systemid=1 ORDER BY id DESC LIMIT 3 ) A GROUP BY A.systemid);

The result stored in @myvar is

5,6,7

Next, the FIND_IN_SET selector is used to select from the simulated array

SELECT * FROM mytable WHERE FIND_IN_SET(id,@myvar);

The combined final result is as follows:

SET @myvar = (SELECT GROUP_CONCAT(id SEPARATOR ',') AS myval FROM (SELECT * FROM `mytable` WHERE systemid=1 ORDER BY id DESC LIMIT 3 ) A GROUP BY A.systemid);
DELETE FROM mytable WHERE FIND_IN_SET(id,@myvar);

I am aware that this is a very specific case. However it can be modified to suit just about any other case where a variable needs to store an array of values.

I hope that this helps.

Clinton
  • 1,111
  • 1
  • 14
  • 21
7
DELIMITER $$
CREATE DEFINER=`mysqldb`@`%` PROCEDURE `abc`()
BEGIN
  BEGIN 
    set @value :='11,2,3,1,'; 
    WHILE (LOCATE(',', @value) > 0) DO
      SET @V_DESIGNATION = SUBSTRING(@value,1, LOCATE(',',@value)-1); 
      SET @value = SUBSTRING(@value, LOCATE(',',@value) + 1); 
      select @V_DESIGNATION;
    END WHILE;
  END;
END$$
DELIMITER ;
benomatis
  • 5,536
  • 7
  • 36
  • 59
Sagar Gangwal
  • 7,544
  • 3
  • 24
  • 38
3

Maybe create a temporary memory table with columns (key, value) if you want associative arrays. Having a memory table is the closest thing to having arrays in mysql

Pavle Lekic
  • 1,062
  • 1
  • 15
  • 28
  • Umm, I don't want associative arrays, just arrays. – einpoklum Aug 01 '13 at 13:25
  • you can use a temporary memory table with only one column and then loop thru the values using cursors, that is the closest thing to using arrays and for/while loops in a non-declarative programming language – Pavle Lekic Aug 02 '13 at 15:09
  • The language actually has this feature, i.e., there's no syntactic reason you shouldn't be able to select a vector into a variable just like you select a scalar into it. – einpoklum Aug 02 '13 at 18:30
3

Here’s how I did it.

First, I created a function that checks whether a Long/Integer/whatever value is in a list of values separated by commas:

CREATE DEFINER = 'root'@'localhost' FUNCTION `is_id_in_ids`(
        `strIDs` VARCHAR(255),
        `_id` BIGINT
    )
    RETURNS BIT(1)
    NOT DETERMINISTIC
    CONTAINS SQL
    SQL SECURITY DEFINER
    COMMENT ''
BEGIN

  DECLARE strLen    INT DEFAULT 0;
  DECLARE subStrLen INT DEFAULT 0;
  DECLARE subs      VARCHAR(255);

  IF strIDs IS NULL THEN
    SET strIDs = '';
  END IF;

  do_this:
    LOOP
      SET strLen = LENGTH(strIDs);
      SET subs = SUBSTRING_INDEX(strIDs, ',', 1);

      if ( CAST(subs AS UNSIGNED) = _id ) THEN
        -- founded
        return(1);
      END IF;

      SET subStrLen = LENGTH(SUBSTRING_INDEX(strIDs, ',', 1));
      SET strIDs = MID(strIDs, subStrLen+2, strLen);

      IF strIDs = NULL or trim(strIds) = '' THEN
        LEAVE do_this;
      END IF;

  END LOOP do_this;

   -- not founded
  return(0);

END;

So now you can search for an ID in a comma-separated list of IDs, like this:

select `is_id_in_ids`('1001,1002,1003',1002);

And you can use this function inside a WHERE clause, like this:

SELECT * FROM table1 WHERE `is_id_in_ids`('1001,1002,1003',table1_id);

This was the only way I found to pass an "array" parameter to a PROCEDURE.

TRiG
  • 10,148
  • 7
  • 57
  • 107
chuckedw
  • 648
  • 2
  • 9
  • 13
3

I'm surprised none of the answers mention ELT/FIELD.

ELT/FIELD works very similar to an array especially if you have static data.

FIND_IN_SET also works similar but doesn't have a built in complementary function but it's easy enough to write one.

mysql> select elt(2,'AA','BB','CC');
+-----------------------+
| elt(2,'AA','BB','CC') |
+-----------------------+
| BB                    |
+-----------------------+
1 row in set (0.00 sec)

mysql> select field('BB','AA','BB','CC');
+----------------------------+
| field('BB','AA','BB','CC') |
+----------------------------+
|                          2 |
+----------------------------+
1 row in set (0.00 sec)

mysql> select find_in_set('BB','AA,BB,CC');
+------------------------------+
| find_in_set('BB','AA,BB,CC') |
+------------------------------+
|                            2 |
+------------------------------+
1 row in set (0.00 sec)

mysql>  SELECT SUBSTRING_INDEX(SUBSTRING_INDEX('AA,BB,CC',',',2),',',-1);
+-----------------------------------------------------------+
| SUBSTRING_INDEX(SUBSTRING_INDEX('AA,BB,CC',',',2),',',-1) |
+-----------------------------------------------------------+
| BB                                                        |
+-----------------------------------------------------------+
1 row in set (0.01 sec)
Jongab
  • 41
  • 1
  • 3
3

Is an array variable really necessary?

I ask because I originally landed here wanting to add an array as a MySQL table variable. I was relatively new to database design and trying to think of how I'd do it in a typical programming language fashion.

But databases are different. I thought I wanted an array as a variable, but it turns out that's just not a common MySQL database practice.

Standard Practice

The alternative solution to arrays is to add an additional table, and then reference your original table with a foreign key.

As an example, let's imagine an application that keeps track of all the items every person in a household wants to buy at the store.

The commands for creating the table I originally envisioned would have looked something like this:

#doesn't work
CREATE TABLE Person(
  name VARCHAR(50) PRIMARY KEY
  buy_list ARRAY
);

I think I envisioned buy_list to be a comma-separated string of items or something like that.

But MySQL doesn't have an array type field, so I really needed something like this:

CREATE TABLE Person(
  name VARCHAR(50) PRIMARY KEY
);
CREATE TABLE BuyList(
  person VARCHAR(50),
  item VARCHAR(50),
  PRIMARY KEY (person, item),
  CONSTRAINT fk_person FOREIGN KEY (person) REFERENCES Person(name)
);

Here we define a constraint named fk_person. It says that the 'person' field in BuyList is a foreign key. In other words, it's a primary key in another table, specifically the 'name' field in the Person table, which is what REFERENCES denotes.

We also defined the combination of person and item to be the primary key, but technically that's not necessary.

Finally, if you want to get all the items on a person's list, you can run this query:

SELECT item FROM BuyList WHERE person='John';

This gives you all the items on John's list. No arrays necessary!

Community
  • 1
  • 1
kraftydevil
  • 5,144
  • 6
  • 43
  • 65
  • My accepted solution _is_ to use a temporary table. – einpoklum May 18 '20 at 17:07
  • Of course. I then included this answer for anyone like me that got to this page looking for a way to create an array type - who didn't initially understand why arrays are not a type in MySQL. It's by design it seems. The general case wasn't represented here so I included what I learned for others to understand that arrays are not typically needed. I don't expect you to select my answer. It depends on the use case. You have your accepted answer for a specific use case and I'm providing this answer for the general use case. – kraftydevil May 18 '20 at 19:58
3

This is my solution to use a variable containing a list of elements. You can use it in simple queries (no need to use store procedures or create tables).

I found somewhere else on the site the trick to use the JSON_TABLE function (it works in mysql 8, I dunno of it works in other versions).

set @x = '1,2,3,4' ;

select c.NAME
from colors c
where 
  c.COD in ( 
    select * 
    from json_table( 
      concat('[',@x,']'),
      '$[*]' columns (id int path '$') ) t ) ;

Also, you may need to manage the case of one or more variables set to empty_string. In this case I added another trick (the query does not return error even if x, y, or both x and y are empty strings):

set @x = '' ;
set @y = 'yellow' ;

select c.NAME
from colors 
where 
  if(@y = '', 1 = 1, c.NAME = @y)
  and if(@x = '', 1, c.COD) in ( 
    select * 
    from json_table(
      concat('[',if(@x = '', 1, @x),']'),
      '$[*]' columns (id int path '$') ) t) ;
Matteo
  • 31
  • 2
2

This works fine for list of values:

SET @myArrayOfValue = '2,5,2,23,6,';

WHILE (LOCATE(',', @myArrayOfValue) > 0)
DO
SET @value = ELT(1, @myArrayOfValue);
    SET @STR = SUBSTRING(@myArrayOfValue, 1, LOCATE(',',@myArrayOfValue)-1);
    SET @myArrayOfValue = SUBSTRING(@myArrayOfValue, LOCATE(',', @myArrayOfValue) + 1);

    INSERT INTO `Demo` VALUES(@STR, 'hello');
END WHILE;
Tim Tisdall
  • 9,914
  • 3
  • 52
  • 82
1

Both versions using sets didn't work for me (tested with MySQL 5.5). The function ELT() returns the whole set. Considering the WHILE statement is only avaible in PROCEDURE context i added it to my solution:

DROP PROCEDURE IF EXISTS __main__;

DELIMITER $
CREATE PROCEDURE __main__()
BEGIN
    SET @myArrayOfValue = '2,5,2,23,6,';

    WHILE (LOCATE(',', @myArrayOfValue) > 0)
    DO
        SET @value = LEFT(@myArrayOfValue, LOCATE(',',@myArrayOfValue) - 1);    
        SET @myArrayOfValue = SUBSTRING(@myArrayOfValue, LOCATE(',',@myArrayOfValue) + 1);
    END WHILE;
END;
$
DELIMITER ;

CALL __main__;

To be honest, i don't think this is a good practice. Even if its realy necessary, this is barely readable and quite slow.

jmmeier
  • 63
  • 4
1

Isn't the point of arrays to be efficient? If you're just iterating through values, I think a cursor on a temporary (or permanent) table makes more sense than seeking commas, no? Also cleaner. Lookup "mysql DECLARE CURSOR".

For random access a temporary table with numerically indexed primary key. Unfortunately the fastest access you'll get is a hash table, not true random access.

Amaigus
  • 19
  • 1
1

Another way to see the same problem. Hope helpfull

DELIMITER $$
CREATE PROCEDURE ARR(v_value VARCHAR(100))
BEGIN

DECLARE v_tam VARCHAR(100);
DECLARE v_pos VARCHAR(100);

CREATE TEMPORARY TABLE IF NOT EXISTS split (split VARCHAR(50));

SET v_tam = (SELECT (LENGTH(v_value) - LENGTH(REPLACE(v_value,',',''))));
SET v_pos = 1;

WHILE (v_tam >= v_pos)
DO
    INSERT INTO split 
    SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(v_value,',',v_pos),',', -1);
    SET v_pos = v_pos + 1;
END WHILE;

SELECT * FROM split;

DROP TEMPORARY TABLE split;

END$$


CALL ARR('1006212,1006404,1003404,1006505,444,');
  • Actually, it isn't clear what you're saying here. This question from 7 years ago has several relevant answers. Consider removing your answer or explaining what you're trying to tell us directly/generally rather than through an example. – einpoklum Sep 27 '19 at 22:49
1

If we have one table like that

mysql> select * from user_mail;
+------------+-------+
| email      | user | 
+------------+-------+-
| email1@gmail |     1 | 
| email2@gmail |     2 |
+------------+-------+--------+------------+

and the array table:

mysql> select * from user_mail_array;
+------------+-------+-------------+
| email      | user | preferences |
+------------+-------+-------------+
| email1@gmail |     1 |           1 |
| email1@gmail |     1 |           2 |
| email1@gmail |     1 |           3 |
| email1@gmail |     1 |           4 |
| email2@gmail |     2 |           5 |
| email2@gmail |     2 |           6 |

We can select the rows of the second table as one array with CONCAT function:

mysql> SELECT t1.*, GROUP_CONCAT(t2.preferences) AS preferences
     FROM user_mail t1,user_mail_array t2
       where t1.email=t2.email and t1.user=t2.user
     GROUP BY t1.email,t1.user;

+------------+-------+--------+------------+-------------+
| email      | user | preferences |
+------------+-------+--------+------------+-------------+
|email1@gmail |     1 | 1,3,2,4     |
|email2@gmail |     2 | 5,6         |
+------------+-------+--------+------------+-------------+
aitor
  • 61
  • 3
0

In MYSQL version after 5.7.x, you can use JSON type to store an array. You can get value of an array by a key via MYSQL.

Dimitar
  • 4,402
  • 4
  • 31
  • 47
nick darn
  • 1
  • 1
0

Inspired by the function ELT(index number, string1, string2, string3,…),I think the following example works as an array example:

set @i := 1;
while @i <= 3
do
  insert into table(val) values (ELT(@i ,'val1','val2','val3'...));
set @i = @i + 1;
end while;

Hope it help.

edward
  • 1
  • 1
0

Here is an example for MySQL for looping through a comma delimited string.

DECLARE v_delimited_string_access_index INT;
DECLARE v_delimited_string_access_value VARCHAR(255);
DECLARE v_can_still_find_values_in_delimited_string BOOLEAN;

SET v_can_still_find_values_in_delimited_string = true;
SET v_delimited_string_access_index = 0;
WHILE (v_can_still_find_values_in_delimited_string) DO
  SET v_delimited_string_access_value = get_from_delimiter_split_string(in_array, ',', v_delimited_string_access_index); -- get value from string
  SET v_delimited_string_access_index = v_delimited_string_access_index + 1;
  IF (v_delimited_string_access_value = '') THEN
    SET v_can_still_find_values_in_delimited_string = false; -- no value at this index, stop looping
  ELSE
    -- DO WHAT YOU WANT WITH v_delimited_string_access_value HERE
  END IF;
END WHILE;

this uses the get_from_delimiter_split_string function defined here: https://stackoverflow.com/a/59666211/3068233

Ulad Kasach
  • 11,558
  • 11
  • 61
  • 87
-2

I Think I can improve on this answer. Try this:

The parameter 'Pranks' is a CSV. ie. '1,2,3,4.....etc'

CREATE PROCEDURE AddRanks(
IN Pranks TEXT
)
BEGIN
  DECLARE VCounter INTEGER;
  DECLARE VStringToAdd VARCHAR(50);
  SET VCounter = 0;
  START TRANSACTION;
  REPEAT
    SET VStringToAdd = (SELECT TRIM(SUBSTRING_INDEX(Pranks, ',', 1)));
    SET Pranks = (SELECT RIGHT(Pranks, TRIM(LENGTH(Pranks) - LENGTH(SUBSTRING_INDEX(Pranks, ',', 1))-1)));
    INSERT INTO tbl_rank_names(rank)
    VALUES(VStringToAdd);
    SET VCounter = VCounter + 1;
  UNTIL (Pranks = '')
  END REPEAT;
  SELECT VCounter AS 'Records added';
  COMMIT;
END;

This method makes the searched string of CSV values progressively shorter with each iteration of the loop, which I believe would be better for optimization.

user2288580
  • 2,210
  • 23
  • 16
-2

I would try something like this for multiple collections. I'm a MySQL beginner. Sorry about the function names, couldn't decide on what names would be best.

delimiter //

drop  procedure init_
//
create procedure init_()
begin
  CREATE TEMPORARY TABLE if not exists 
    val_store(  
    realm  varchar(30) 
    ,  id  varchar(30) 
    ,  val   varchar(255) 
    ,  primary key ( realm , id )
    );
end;
//

drop function if exists get_
//
create function get_( p_realm varchar(30) , p_id varchar(30) )
  returns varchar(255)
  reads sql data
begin 
  declare ret_val varchar(255);
  declare continue handler for 1146 set ret_val = null;
  select val into ret_val from val_store where id = p_id;
  return ret_val;
end;
//

drop procedure if exists set_
//
create procedure set_( p_realm varchar(30) , p_id varchar(30) , p_val varchar(255) )
begin
  call init_(); 
  insert into val_store (realm,id,val) values (p_realm , p_id , p_val) on duplicate key update val = p_val;
end;
//

drop   procedure if exists remove_
//
create procedure remove_( p_realm varchar(30) , p_id varchar(30) )
begin
  call init_();
  delete from val_store where realm = p_realm and id = p_id;
end;
//

drop   procedure if exists erase_
//
create procedure erase_( p_realm varchar(30) ) 
begin
  call init_();
  delete from val_store where realm = p_realm;
end;
//

call set_('my_array_table_name','my_key','my_value');

select get_('my_array_table_name','my_key');
Dave
  • 1
  • 3
  • I think I understand what you're suggesting, but this is quite unwieldy and probably also incredibly slow... – einpoklum Jan 24 '19 at 21:18
  • I can't endorse or dismiss it without stress testing it. It is basically a primary key lookup and insertion on a temporary table (or normal table). I will use it until I run into problems or find a better way; but I do weird things like write compilers and games completely in Oracle PL/SQL. – Dave Jan 25 '19 at 14:12
-3

Rather than Saving data as a array or in one row only you should be making diffrent rows for every value received. This will make it much simpler to understand rather than putting all together.

-7

Have you tried using PHP's serialize()? That allows you to store the contents of a variable's array in a string PHP understands and is safe for the database (assuming you've escaped it first).

$array = array(
    1 => 'some data',
    2 => 'some more'
);

//Assuming you're already connected to the database
$sql = sprintf("INSERT INTO `yourTable` (`rowID`, `rowContent`) VALUES (NULL, '%s')"
     ,  serialize(mysql_real_escape_string($array, $dbConnection)));
mysql_query($sql, $dbConnection) or die(mysql_error());

You can also do the exact same without a numbered array

$array2 = array(
    'something' => 'something else'
);

or

$array3 = array(
    'somethingNew'
);