95

What is a good way to save an array of data to a single mysql field?

Also once I query for that array in the mysql table, what is a good way to get it back into array form?

Is serialize and unserialize the answer?

JasonDavis
  • 48,204
  • 100
  • 318
  • 537

14 Answers14

92

There is no good way to store an array into a single field.

You need to examine your relational data and make the appropriate changes to your schema. See example below for a reference to this approach.

If you must save the array into a single field then the serialize() and unserialize() functions will do the trick. But you cannot perform queries on the actual content.

As an alternative to the serialization function there is also json_encode() and json_decode().

Consider the following array

$a = array(
    1 => array(
        'a' => 1,
        'b' => 2,
        'c' => 3
    ),
    2 => array(
        'a' => 1,
        'b' => 2,
        'c' => 3
    ),
);

To save it in the database you need to create a table like this

$c = mysql_connect($server, $username, $password);
mysql_select_db('test');
$r = mysql_query(
    'DROP TABLE IF EXISTS test');
$r = mysql_query(
    'CREATE TABLE test (
      id INTEGER UNSIGNED NOT NULL,
      a INTEGER UNSIGNED NOT NULL,
      b INTEGER UNSIGNED NOT NULL,
      c INTEGER UNSIGNED NOT NULL,
      PRIMARY KEY (id)
    )');

To work with the records you can perform queries such as these (and yes this is an example, beware!)

function getTest() {
    $ret = array();
    $c = connect();
    $query = 'SELECT * FROM test';
    $r = mysql_query($query,$c);
    while ($o = mysql_fetch_array($r,MYSQL_ASSOC)) {
        $ret[array_shift($o)] = $o;
    }
    mysql_close($c);
    return $ret;
}
function putTest($t) {
    $c = connect();
    foreach ($t as $k => $v) {
        $query = "INSERT INTO test (id,".
                implode(',',array_keys($v)).
                ") VALUES ($k,".
                implode(',',$v).
            ")";
        $r = mysql_query($query,$c);
    }
    mysql_close($c);
}

putTest($a);
$b = getTest();

The connect() function returns a mysql connection resource

function connect() {
    $c = mysql_connect($server, $username, $password);
    mysql_select_db('test');
    return $c;
}
Steve Chambers
  • 37,270
  • 24
  • 156
  • 208
Peter Lindqvist
  • 10,122
  • 3
  • 41
  • 60
27

Generally, yes, serialize and unserialize are the way to go.

If your data is something simple, though, saving as a comma-delimited string would probably be better for storage space. If you know that your array will just be a list of numbers, for example, then you should use implode/explode. It's the difference between 1,2,3 and a:3:{i:0;i:1;i:1;i:2;i:2;i:3;}.

If not, then serialize and unserialize work for all cases.

Matchu
  • 83,922
  • 18
  • 153
  • 160
  • 24
    Since you're here, reader, I'm just going to take the time to announce that I've since discovered, through years of experience, that this is really not the way to go. The accepted answer is a much stronger approach. – Matchu Apr 01 '12 at 03:50
  • 4
    Sine you're here, reader I'm going to share with you that it simply depends on your requirements. If you have no need to query by your array values and need something that is very FAST you can safely store your data like this in a single field (which is what the question clearly stated), slap a primary key on it and off you go. If you wonder what the application is: pushing data into a que that gets cron'd every 5 mins. Another cron creates the arrays which takes much more time. The que fetches the computed data and passes it to a 3rd party API. No better way of doing it. – Rid Iculous Jul 07 '15 at 02:08
  • 1
    @RidIculous I'm confused, are you talking about your own personal application or the application which led to the question being asked? – Peter Lindqvist Jul 07 '15 at 11:54
  • 1
    Whilst that is irrelevant to the premise of my statement the prefix "If you wonder what the application is" should provide clarity. – Rid Iculous Dec 15 '15 at 04:37
12

Just use the serialize PHP function:

<?php
$myArray = array('1', '2');
$seralizedArray = serialize($myArray);
?>

However, if you are using simple arrays like that you might as well use implode and explode.Use a blank array instead of new.

Basil
  • 3
  • 3
user240609
  • 1,060
  • 10
  • 17
10

Serialize/Unserialize array for storage in a DB

Visit http://php.net/manual/en/function.serialize.php

From the PHP Manual:

Look under "Return" on the page

Returns a string containing a byte-stream representation of value that can be stored anywhere.

Note that this is a binary string which may include null bytes, and needs to be stored and handled as such. For example, serialize() output should generally be stored in a BLOB field in a database, rather than a CHAR or TEXT field.

Note: If you want to store html into a blob, be sure to base64 encode it or it could break the serialize function.

Example encoding:

$YourSerializedData = base64_encode(serialize($theHTML));

$YourSerializedData is now ready to be stored in blob.

After getting data from blob you need to base64_decode then unserialize Example decoding:

$theHTML = unserialize(base64_decode($YourSerializedData));
Rohan Kumar
  • 40,431
  • 11
  • 76
  • 106
seaBass
  • 585
  • 1
  • 6
  • 17
8

The best way, that I found to myself is save array as data string with separator characters

$array = array("value1", "value2", "value3", "...", "valuen");
$array_data = implode("array_separator", $array);

$query = "INSERT INTO my_tbl_name (id, array_data) VALUES(NULL,'" . $array_data . "');";

You can then search data, stored in your array with simple query

$query = "SELECT * FROM my_tbl_name WHERE array_data LIKE '%value3%'";

use explode() function to convert "array_data" string to array

$array = explode("array_separator", $array_data);

note that this is not working with multidimensional arrays and make sure that your "array_separator" is unique and had not exist in array values.

Be careful !!! if you just will take a form data and put in database, you will be in trap, becous the form data isn't SQL-safe ! you must handle your form value with mysql_real_escape_string or if you use MySQLi mysqli::real_escape_string or if value are integer or boolean cast (int) (boolean) on them

$number = (int)$_POST['number'];
$checked = (boolean) $_POST['checked'];

$name = mysql_real_escape_string($db_pt, $_POST['name']);
$email = mysqli_obj->real_escape_string($_POST['email']);
Harry
  • 334
  • 5
  • 12
6

As mentioned before - If you do not need to search for data within the array, you can use serialize - but this is "php only". So I would recommend to use json_decode / json_encode - not only for performance but also for readability and portability (other languages such as javascript can handle json_encoded data).

random_user_name
  • 25,694
  • 7
  • 76
  • 115
6

Serialize and unserialize are pretty common for that. You could also use JSON via json_encode and json_decode for a less PHP-specific format.

ceejayoz
  • 176,543
  • 40
  • 303
  • 368
3

Uhh, I don't know why everyone suggests serializing the array.

I say, the best way is to actually fit it into your database schema. I have no idea (and you gave no clues) about the actual semantic meaning of the data in your array, but there are generally two ways of storing sequences like that

create table mydata (
  id int not null auto_increment primary key,
  field1 int not null,
  field2 int not null,
  ...
  fieldN int not null
)

This way you are storing your array in a single row.

create table mydata (
    id int not null auto_increment primary key,
    ...
)

create table myotherdata (
    id int not null auto_increment primary key,
    mydata_id int not null,
    sequence int not null,
    data int not null
)

The disadvantage of the first method is, obviously, that if you have many items in your array, working with that table will not be the most elegant thing. It is also impractical (possible, but quite inelegant as well - just make the columns nullable) to work with sequences of variable length.

For the second method, you can have sequences of any length, but of only one type. You can, of course, make that one type varchar or something and serialize the items of your array. Not the best thing to do, but certainly better, than serializing the whole array, right?

Either way, any of this methods gets a clear advantage of being able to access an arbitrary element of the sequence and you don't have to worry about serializing arrays and ugly things like that.

As for getting it back. Well, get the appropriate row/sequence of rows with a query and, well, use a loop.. right?

shylent
  • 10,076
  • 6
  • 38
  • 55
  • Sometimes an array really is appropriate. If you're only going to access it as an attribute of the first object, then it makes sense. – Matchu Dec 30 '09 at 04:58
  • 1
    I have to disagree in the most severe terms - it seems rather inappropriate for me to store random, unstructured (php "arrays" are not actually arrays at all, right?), untyped blobs of data in a *relational database*. What are you going to use for a separator anyway, if your array might have any strings in it? This is just asking for trouble in many different ways. In 99,9% of cases, there is another, more natural way. I'll make a wild guess here and suggest, that the questioner's case doesn't fall into the remaining 0.1%. – shylent Dec 30 '09 at 05:04
  • 2
    Actually, sometimes it is very appropriate to store an array in a field in a DB. Example would be metadata like a global 'variables' table into which a systems plugins & modules can store their assorted settings. a table that stores arbitrary 'session' data might be best implemented using a field that holds an associative array of keys/values. serialize and unserialize (which is the correct answer) take care of separators. check some of the several successful & popular open source projects, like WordPress or Drupal - and you'll see that arrays are sometimes stored in the DB like this – Scott Evernden Dec 30 '09 at 06:56
  • @Scott Evernden: I guess you are right after all. php is not my "main" language, so I was judging the solution from the database design perspective. If what you describe is really the common way to do such things (in php), then so be it. Doesn't make me like it though :) – shylent Dec 30 '09 at 07:09
  • Just because someone does it and it can be done doesn't mean that it's a good thing to do. – Peter Lindqvist Dec 30 '09 at 07:55
  • 5
    It is NEVER appropriate to store an array in a field in a DB. It is a violation not of fourth normal form, third normal form or even second normal form: it is a VIOLATION OF FIRST NORMAL FORM. If you cannot adhere even to first normal form there is something seriously wrong with your application. That goes for Drupal and Wordpress; if they do this it certainly isn't because that facet of their apps are well designed.. I had this argument at my last job, and because XCart was doing this nonsense it made something that should have been possible, extremely difficult instead. – Dexygen Dec 30 '09 at 08:10
  • Thanks a lot for the support, George Jempty. This is **exactly** the point I've been trying to make, rather unsuccessfully, though, it seems. – shylent Dec 30 '09 at 08:24
  • Just several thoughts. Normalization is good, for relational database. And also, de-normalization is part of the software development process, for performance issues. Sometimes you can use your RDBMS as a NoSQL DB, for key/value storing. Several software development projects does that. – Luis Lobo Borobia Feb 21 '11 at 01:42
  • @George Jempty: I disagree with this. You should store things in such a way as they preserve their meaning. A string is just an array of characters. But we store the entire array as a string because that is how we will always use that particular array. There is no reason to access pieces of it. Likewise if we have an associative array such that it will only be loaded and edited as a whole, it could be argued to be in 1NF because the array is atomic in this context. It is the smallest piece of data we work on in the database. So it is occasionally (but rarely) appropriate. – Justin Nov 09 '13 at 06:08
  • @Justin Then you disagree with everybody who knows anything about databases, including Messrs. Codd & Date. – Dexygen Nov 11 '13 at 00:51
  • @George: Read Date on Databases pp 112. He explicitly says there are situations in which a set is an appropriate thing to store as a value in a table and that it can be considered in 1NF. "such a set is indeed a single value: a set value, to be sure, but a set is still, at a certain level of abstraction, a single value." ... "the notion that a set can legitimately be regarded as a single value underpinned Codd's original definition of 1NF .. that definition was expressed in terms of 'domains [that have values that] are themselves sets'". – Justin Nov 11 '13 at 06:23
  • @Justin very interesting thanks guess I was under-informed and over-dogmatic – Dexygen Nov 11 '13 at 12:32
  • @George: You are welcome! Your advice is generally sound, and honestly what I tell my Into to Databases students as exceptions are quite rate. And I think Codd may be on your side. But it is not a settled issue one way or the other. – Justin Nov 11 '13 at 18:45
  • @ George - If you're ever faced with the challenge of shifting very large amounts of data between APIs and have to take computation time and bandwidth limitations into account you'll find that the only way is to pre-compute your data and store the result intermittently in the format the receiving API expects. In particular if the number and/or keys of elements of the array expected varies or is unknown. Ergo: NEVER say never :oP – Rid Iculous Aug 24 '15 at 23:55
2

You can save your array as a json.
there is documentation for json data type: https://dev.mysql.com/doc/refman/5.7/en/json.html
I think this is the best solution, and will help you maintain your code more readable by avoiding crazy functions.
I expect this is helpful for you.

Roberto Murguia
  • 357
  • 1
  • 2
  • 13
0

I would suggest using implode/explode with a character that you know will not be contained in any of the individual array items. Then store it in SQL as a string.

  • 3
    This question was asked 3 years ago and has an accepted answer. You might find it more helpful to answer newer questions or questions with no answers. – MDrollette Jun 24 '12 at 21:08
0

Yup, serialize/unserialize is what I've seen the most in many open source projects.

Eduardo
  • 7,631
  • 2
  • 30
  • 31
0

check out the implode function, since the values are in an array, you want to put the values of the array into a mysql query that inserts the values into a table.

$query = "INSERT INto hardware (specifications) VALUES (".implode(",",$specifications).")";

If the values in the array are text values, you will need to add quotes

$query = "INSERT INto hardware (specifications) VALUES ("'.implode("','",$specifications)."')";

mysql_query($conn,$query);

Also, if you don't want duplicate values, switch the "INto" to "IGNORE" and only unique values will be inserted into the table.

UPDATE

Warning This extension was deprecated in PHP 5.5.0, and it was removed in PHP 7.0.0. Instead, the MySQLi or PDO_MySQL extension should be used. See also MySQL: choosing an API guide. Alternatives to this function include:

mysqli_query

PDO::query()

WardNsour
  • 313
  • 1
  • 2
  • 16
  • If you have a primary key, you get no duplicates with INSERT INTO anyway. If you don't have a primary key or an index the IGNORE does not make any difference. – Peter Lindqvist Dec 30 '09 at 08:38
0

you can insert serialized object ( array ) to mysql , example serialize($object) and you can unserize object example unserialize($object)

Vildan Bina
  • 309
  • 3
  • 11
-5

Instead of saving it to the database, save it to a file and then call it later.

What many php apps do (like sugarcrm) is to just use var_export to echo all the data of the array to a file. This is what I use to save my configurations data:

private function saveConfig() {
    file_put_contents($this->_data['pathtocompileddata'],'<?php' . PHP_EOL . '$acs_confdata = ' . var_export($this->_data,true) . ';');        
}

I think this is a better way to save your data!

AntonioCS
  • 8,335
  • 18
  • 63
  • 92
  • It's another way, not necessarily better. – Peter Lindqvist Dec 30 '09 at 08:30
  • Indeed. I just think that accessing the file is much easier than querying the database to retrieve the array data and then initialize the array. This way you just include the file and it's done. – AntonioCS Dec 30 '09 at 10:12