MySQL에 PHP 배열을 저장 하시겠습니까?


88

단일 mysql 필드에 데이터 배열을 저장하는 좋은 방법은 무엇입니까?

또한 mysql 테이블에서 해당 배열을 쿼리하면 배열 형식으로 되 돌리는 좋은 방법은 무엇입니까?

대답을 직렬화하고 직렬화 해제합니까?

답변:


87

단일 필드에 배열을 저장하는 좋은 방법 은 없습니다 .

관계형 데이터를 검사하고 스키마를 적절하게 변경해야합니다. 이 접근 방식에 대한 참조는 아래 예를 참조하십시오.

배열을 단일 필드에 저장 해야하는 경우 serialize()unserialize()함수가 트릭을 수행합니다. 그러나 실제 콘텐츠에 대해서는 쿼리를 수행 할 수 없습니다.

직렬화 기능의 대안으로 json_encode()json_decode().

다음 배열을 고려하십시오.

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

데이터베이스에 저장하려면 다음과 같은 테이블을 만들어야합니다.

$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)
    )');

레코드로 작업하려면 다음과 같은 쿼리를 수행 할 수 있습니다 (예, 이것은 예입니다.주의하십시오!)

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();

connect()함수는 mysql 연결 리소스를 반환합니다.

function connect() {
    $c = mysql_connect($server, $username, $password);
    mysql_select_db('test');
    return $c;
}

26

일반적으로 예, 직렬화 및 직렬화 해제가 갈 길입니다.

하지만 데이터가 단순한 경우 쉼표로 구분 된 문자열로 저장하는 것이 저장 공간에 더 적합 할 것입니다. 예를 들어 배열이 숫자 목록 일 뿐이라는 것을 알고 있다면 implode / explode를 사용해야합니다. 1,2,3과 의 차이 a:3:{i:0;i:1;i:1;i:2;i:2;i:3;}입니다.

그렇지 않은 경우 모든 경우에 대해 직렬화 및 직렬화 해제 작업을 수행하십시오.


23
독자 여러분, 여기 계시기 때문에 저는 수년간의 경험을 통해 이것이 정말로 갈 길이 아님을 발견했습니다. 허용되는 대답은 훨씬 더 강력한 접근 방식입니다.
Matchu

4
Sine you 're here, 독자 여러분의 요구 사항에 따라 달라진다는 사실을 여러분과 공유하겠습니다. 어레이 값으로 쿼리 할 필요가없고 매우 빠른 것이 필요한 경우 이와 같은 데이터를 단일 필드에 안전하게 저장하고 (질문이 명확하게 언급 한 내용 임) 기본 키를 치고 나가면됩니다. . 애플리케이션이 무엇인지 궁금하다면 5 분마다 크론이 생성되는 큐에 데이터를 푸시합니다. 또 다른 크론은 훨씬 더 많은 시간이 걸리는 배열을 만듭니다. 쿼리는 계산 된 데이터를 가져 와서 타사 API에 전달합니다. 더 좋은 방법은 없습니다.
Iculous 없애

1
@RidIculous 혼란 스럽습니다. 자신의 개인 응용 프로그램 또는 질문을 받게 된 응용 프로그램에 대해 이야기하고 있습니까?
피터 고 Lindqvist

1
내 진술의 전제와는 무관하지만 "어플리케이션이 무엇인지 궁금하다면"접두사가 명확성을 제공해야합니다.
Iculous 없애

10

직렬화 PHP 함수를 사용하십시오.

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

그러나 이와 같은 간단한 배열을 사용하는 경우 implode 및 explode를 사용하는 것이 좋습니다. new 대신 빈 배열을 사용하십시오.


9

DB에 저장하기 위해 어레이 직렬화 / 직렬화 해제

http://php.net/manual/en/function.serialize.php를 방문 하십시오.

PHP 매뉴얼에서 :

페이지의 "반품"을보십시오.

어디에나 저장할 수있는 값의 바이트 스트림 표현을 포함하는 문자열을 반환합니다.

이것은 널 바이트를 포함 할 수있는 2 진 문자열이며 저장 및 처리해야합니다. 예를 들어, serialize () 출력은 일반적으로 CHAR 또는 TEXT 필드가 아닌 데이터베이스의 BLOB 필드에 저장되어야합니다.

참고 : html을 blob에 저장하려면 base64로 인코딩해야합니다. 그렇지 않으면 직렬화 기능이 중단 될 수 있습니다.

인코딩 예 :

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

$YourSerializedData 이제 blob에 저장할 준비가되었습니다.

blob에서 데이터를 가져온 후에는 base64_decode를 수행 한 다음 예제 디코딩을 직렬화 해제해야합니다.

$theHTML = unserialize(base64_decode($YourSerializedData));

8

내가 찾은 가장 좋은 방법은 분리 문자가있는 데이터 문자열로 배열을 저장하는 것입니다.

$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 . "');";

그런 다음 간단한 쿼리로 배열에 저장된 데이터를 검색 할 수 있습니다.

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

explode () 함수를 사용하여 "array_data"문자열을 배열로 변환

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

이것은 다차원 배열에서 작동하지 않으며 "array_separator"가 고유하고 배열 값에 존재하지 않았는지 확인하십시오.

조심해 !!! 양식 데이터를 가져 와서 데이터베이스에 넣으면 양식 데이터가 SQL에 안전하지 않기 때문에 함정에 빠질 것입니다! mysql_real_escape_string 을 사용하거나 MySQLi mysqli :: real_escape_string을 사용 하거나 값이 정수 또는 부울 캐스트 (int) (부울) 인 경우 양식 값을 처리해야 합니다.

$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']);

제 경우에는 이것이 제게 최선의 선택이라고 생각합니다.
Imtiaz 2014

6

직렬화 및 직렬화 해제는 매우 일반적입니다. 덜 PHP 특정 형식의 경우 json_encode 및 json_decode를 통해 JSON을 사용할 수도 있습니다.


5

앞서 언급했듯이-배열 내에서 데이터를 검색 할 필요가없는 경우 직렬화를 사용할 수 있지만 이것은 "php 전용"입니다. 따라서 성능뿐만 아니라 가독성과 이식성 을 위해 json_decode / json_encode 를 사용하는 것이 좋습니다 (JavaScript와 같은 다른 언어는 json_encoded 데이터를 처리 할 수 ​​있음).


3

어, 모든 사람들이 어레이 직렬화를 제안하는 이유를 모르겠습니다.

가장 좋은 방법은 실제로 데이터베이스 스키마에 맞추는 것입니다. 배열에있는 데이터의 실제 의미 론적 의미에 대해 전혀 알지 못합니다 (단서도 제공하지 않음).하지만 일반적으로 이와 같은 시퀀스를 저장하는 두 가지 방법이 있습니다.

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

이런 식으로 배열을 단일 행에 저장합니다.

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
)

첫 번째 방법의 단점은 분명히 배열에 많은 항목이있는 경우 해당 테이블로 작업하는 것이 가장 우아하지 않다는 것입니다. 가변 길이의 시퀀스로 작업하는 것도 비실용적입니다 (가능하지만 매우 부적절합니다. 열을 nullable로 설정).

두 번째 방법의 경우 길이에 상관없이 한 가지 유형의 시퀀스를 가질 수 있습니다. 물론 하나의 유형을 varchar 또는 다른 유형으로 만들고 배열의 항목을 직렬화 할 수 있습니다. 최선의 방법은 아니지만 전체 배열을 직렬화하는 것보다 확실히 낫습니다.

어느 쪽이든,이 메서드는 시퀀스의 임의의 요소에 액세스 할 수 있다는 분명한 이점을 얻습니다. 배열 직렬화 및 그와 같은 추악한 일에 대해 걱정할 필요가 없습니다.

그것을 되 찾는 것에 관해서. 글쎄, 질의로 적절한 행 / 시퀀스를 얻고 루프를 사용하라 .. 맞지?


때로는 배열이 실제로 적절합니다. 첫 번째 개체의 속성으로 만 액세스하려는 경우 의미가 있습니다.
Matchu 2009

1
나는 가장 심각한 용어에 동의하지 않습니다 . 관계형 데이터베이스에 임의의 구조화되지 않은 (php "배열"은 실제로는 배열이 아닙니다. 맞습니까?) 유형이 지정되지 않은 데이터 덩어리를 저장하는 것이 다소 부적절 해 보입니다 . 배열에 문자열이있을 수 있다면 어쨌든 구분 기호로 무엇을 사용할 것입니까? 이것은 여러 가지 방법으로 문제를 요청하는 것입니다. 99,9 %의 경우에는 또 다른 더 자연스러운 방법이 있습니다. 나는 여기서 거친 추측을하고 질문자의 경우가 나머지 0.1 %에 속하지 않는다고 제안 할 것입니다.
shylent

2
사실 때로는 DB의 필드에 배열을 저장하는 것이 매우 적절합니다. 예는 시스템 플러그인 및 모듈이 분류 된 설정을 저장할 수있는 글로벌 '변수'테이블과 같은 메타 데이터입니다. 임의의 '세션'데이터를 저장하는 테이블은 키 / 값의 연관 배열을 보유하는 필드를 사용하여 가장 잘 구현 될 수 있습니다. 직렬화 및 직렬화 해제 (정답)는 구분 기호를 처리합니다. 워드 프레스 또는 드루팔 같은 몇 가지 성공 및 인기있는 오픈 소스 프로젝트의 일부를 확인 - 당신은 그 배열은 때때로이 같은 DB에 저장되어 보자
스콧 Evernden을

@Scott Evernden : 결국 당신이 옳다고 생각합니다. php는 내 "주요"언어가 아니므로 데이터베이스 설계 관점에서 솔루션을 판단했습니다. 설명하는 것이 실제로 그러한 일을 수행하는 일반적인 방법 (php)이라면 그렇게하세요. 그래도 나를 좋아하지 않습니다 :)
shylent

5
DB의 필드에 배열을 저장하는 것은 결코 적절하지 않습니다. 그것은 네 번째 정상 형태, 세 번째 정상 형태 또는 심지어 두 번째 정상 형태의 위반이 아닙니다. 그것은 첫 번째 정상 형태의 위반입니다. 첫 번째 정상 양식도 고수 할 수 없다면 신청서에 심각한 문제가있는 것입니다. Drupal과 Wordpress에 해당됩니다. 만약 그들이 그렇게한다면 그것은 확실히 그들의 앱의 측면이 잘 설계 되었기 때문이 아닙니다. 나는 마지막 직장에서이 논쟁을했고, XCart가이 말도 안되는 일을하고 있었기 때문에 가능해야했던 무언가를 만들었습니다.
Dexygen 2009

2

배열을 json으로 저장할 수 있습니다.
json 데이터 유형에 대한 문서가 있습니다. https://dev.mysql.com/doc/refman/5.7/en/json.html
이것이 최상의 솔루션이라고 생각하며 미친 기능을 피하여 코드를 더 읽기 쉽게 유지하는 데 도움이 될 것입니다. .
나는 이것이 당신에게 도움이 될 것으로 기대합니다.


0

예, 직렬화 / 직렬화 해제는 많은 오픈 소스 프로젝트에서 가장 많이 본 것입니다.


0

개별 배열 항목에 포함되지 않을 것으로 알고있는 문자로 implode / explode를 사용하는 것이 좋습니다. 그런 다음 SQL에 문자열로 저장하십시오.


3
이 질문은 3 년 전에 제기되었으며 대답이 허용되었습니다. 새로운 질문이나 답변이없는 질문에 답변하는 것이 더 도움이 될 수 있습니다.
MDrollette 2012-06-24

0

implode 함수를 확인하십시오. 값이 배열에 있으므로 배열의 값을 테이블에 삽입하는 mysql 쿼리에 넣으려고합니다.

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

배열의 값이 텍스트 값이면 따옴표를 추가해야합니다.

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

mysql_query($query);

또한 중복 값을 원하지 않는 경우 "INto"를 "IGNORE"로 전환하면 고유 한 값만 테이블에 삽입됩니다.


기본 키가 있으면 어쨌든 INSERT INTO로 중복되지 않습니다. 기본 키나 인덱스가없는 경우 IGNORE는 아무런 차이가 없습니다.
Peter Lindqvist

0

직렬화 된 객체 (array)를 mysql에 삽입 serialize($object)할 수 있습니다. 예를 들면 객체 예를 unserize 할 수 있습니다.unserialize($object)


-5

데이터베이스에 저장하는 대신 파일에 저장 한 다음 나중에 호출하십시오.

많은 PHP 앱 (예 : sugarcrm)은 var_export를 사용하여 배열의 모든 데이터를 파일에 에코하는 것입니다. 이것은 내 구성 데이터를 저장하는 데 사용하는 것입니다.

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

이것이 데이터를 저장하는 더 좋은 방법이라고 생각합니다!


반드시 더 나은 것은 아니지만 다른 방법입니다.
Peter Lindqvist

과연. 파일에 액세스하는 것이 데이터베이스를 쿼리하여 배열 데이터를 검색 한 다음 배열을 초기화하는 것보다 훨씬 쉽다고 생각합니다. 이렇게하면 파일을 포함하기 만하면 완료됩니다.
AntonioCS
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.