복붙노트

PDO Prepared 단일 쿼리에서 여러 행을 삽입합니다.

PHP

PDO Prepared 단일 쿼리에서 여러 행을 삽입합니다.

나는 현재 MySQL에서이 유형의 SQL을 사용하여 하나의 단일 쿼리에 여러 행의 값을 삽입합니다.

INSERT INTO `tbl` (`key1`,`key2`) VALUES ('r1v1','r1v2'),('r2v1','r2v2'),...

PDO에 대한 판독 결과에서 사용 준비 문은 정적 쿼리보다 향상된 보안을 제공합니다.

따라서 준비된 문을 사용하여 "하나의 쿼리를 사용하여 여러 행의 값 삽입"을 생성 할 수 있는지 여부를 알고 싶습니다.

그렇다면 어떻게 구현할 수 있습니까?

해결법

  1. ==============================

    1.

    PDO 준비 문으로 여러 값 삽입

    하나의 execute 문에 여러 값 삽입. 왜이 페이지에 따르면 일반 삽입보다 빠르기 때문입니다.

    $datafields = array('fielda', 'fieldb', ... );
    
    $data[] = array('fielda' => 'value', 'fieldb' => 'value' ....);
    $data[] = array('fielda' => 'value', 'fieldb' => 'value' ....);
    

    더 많은 데이터 값 또는 데이터를 채우는 루프가있을 수 있습니다.

    준비된 삽입물을 사용하면 삽입하려는 필드와 해당 필드를 만들 필드 수를 알아야합니다. 자리 표시자를 사용하여 매개 변수를 바인딩합니다.

    insert into table (fielda, fieldb, ... ) values (?,?...), (?,?...)....
    

    그것은 기본적으로 우리가 insert 문을 어떻게 보이게 할 것인가입니다.

    자, 코드 :

    function placeholders($text, $count=0, $separator=","){
        $result = array();
        if($count > 0){
            for($x=0; $x<$count; $x++){
                $result[] = $text;
            }
        }
    
        return implode($separator, $result);
    }
    
    $pdo->beginTransaction(); // also helps speed up your inserts.
    $insert_values = array();
    foreach($data as $d){
        $question_marks[] = '('  . placeholders('?', sizeof($d)) . ')';
        $insert_values = array_merge($insert_values, array_values($d));
    }
    
    $sql = "INSERT INTO table (" . implode(",", $datafields ) . ") VALUES " .
           implode(',', $question_marks);
    
    $stmt = $pdo->prepare ($sql);
    try {
        $stmt->execute($insert_values);
    } catch (PDOException $e){
        echo $e->getMessage();
    }
    $pdo->commit();
    

    내 테스트에서 여러 개의 인서트를 사용하고 단일 값으로 일반 인서트 된 인서트를 사용하는 경우 1 초의 차이가있었습니다.

  2. ==============================

    2.

    Balagtas 씨와 같은 대답, 약간 더 명확하게 ...

    최근 버전의 MySQL과 PHP PDO는 다중 행 INSERT 문을 지원합니다.

    SQL은 INSERT 할 3 열 테이블을 가정하고 이와 같이 보입니다.

    INSERT INTO tbl_name
                (colA, colB, colC)
         VALUES (?, ?, ?), (?, ?, ?), (?, ?, ?) [,...]
    

    DUPLICATE KEY UPDATE는 다중 행 INSERT가있는 경우에도 예상대로 작동합니다. 추가 :

    ON DUPLICATE KEY UPDATE colA = VALUES(colA), colB = VALUES(colB), colC = VALUES(colC)
    

    PHP 코드는 일반적인 $ pdo-> prepare ($ qry) 및 $ stmt-> execute ($ params) PDO 호출을 따릅니다.

    $ params는 INSERT에 전달할 모든 값의 1 차원 배열입니다.

    위의 예에서는 9 개의 요소를 포함해야합니다. PDO는 모든 3 세트를 단일 행의 값으로 사용합니다. (각 3 열 3 행 = 9 요소 배열 삽입

    아래의 코드는 효율성이 아닌 명확성을 위해 작성되었습니다. PHP 배열 _ * () 함수를 사용하여 원하는 경우 데이터를보다 잘 맵핑하거나 처리 할 수 ​​있습니다. 트랜잭션을 사용할 수 있는지 여부는 MySQL 테이블 유형에 따라 다릅니다.

    가정 :

    // setup data values for PDO
    // memory warning: this is creating a copy all of $dataVals
    $dataToInsert = array();
    
    foreach ($dataVals as $row => $data) {
        foreach($data as $val) {
            $dataToInsert[] = $val;
        }
    }
    
    // (optional) setup the ON DUPLICATE column names
    $updateCols = array();
    
    foreach ($colNames as $curCol) {
        $updateCols[] = $curCol . " = VALUES($curCol)";
    }
    
    $onDup = implode(', ', $updateCols);
    
    // setup the placeholders - a fancy way to make the long "(?, ?, ?)..." string
    $rowPlaces = '(' . implode(', ', array_fill(0, count($colNames), '?')) . ')';
    $allPlaces = implode(', ', array_fill(0, count($dataVals), $rowPlaces));
    
    $sql = "INSERT INTO $tblName (" . implode(', ', $colNames) . 
        ") VALUES " . $allPlaces . " ON DUPLICATE KEY UPDATE $onDup";
    
    // and then the PHP PDO boilerplate
    $stmt = $pdo->prepare ($sql);
    
    try {
       $stmt->execute($dataToInsert);
    } catch (PDOException $e){
       echo $e->getMessage();
    }
    
    $pdo->commit();
    
  3. ==============================

    3.

    그게 가치있는 일인가, 나는 많은 사용자가 선택한 대답대로 단일 문자열 쿼리로 구축하는 대신 INSERT 문을 반복하는 것이 좋습니다 것을 보았습니다. 필자는 단지 두 개의 필드와 아주 기본적인 insert 문으로 간단한 테스트를하기로 결정했다.

    <?php
    require('conn.php');
    
    $fname = 'J';
    $lname = 'M';
    
    $time_start = microtime(true);
    $stmt = $db->prepare('INSERT INTO table (FirstName, LastName) VALUES (:fname, :lname)');
    
    for($i = 1; $i <= 10; $i++ )  {
        $stmt->bindParam(':fname', $fname);
        $stmt->bindParam(':lname', $lname);
        $stmt->execute();
    
        $fname .= 'O';
        $lname .= 'A';
    }
    
    
    $time_end = microtime(true);
    $time = $time_end - $time_start;
    
    echo "Completed in ". $time ." seconds <hr>";
    
    $fname2 = 'J';
    $lname2 = 'M';
    
    $time_start2 = microtime(true);
    $qry = 'INSERT INTO table (FirstName, LastName) VALUES ';
    $qry .= "(?,?), ";
    $qry .= "(?,?), ";
    $qry .= "(?,?), ";
    $qry .= "(?,?), ";
    $qry .= "(?,?), ";
    $qry .= "(?,?), ";
    $qry .= "(?,?), ";
    $qry .= "(?,?), ";
    $qry .= "(?,?), ";
    $qry .= "(?,?)";
    
    $stmt2 = $db->prepare($qry);
    $values = array();
    
    for($j = 1; $j<=10; $j++) {
        $values2 = array($fname2, $lname2);
        $values = array_merge($values,$values2);
    
        $fname2 .= 'O';
        $lname2 .= 'A';
    }
    
    $stmt2->execute($values);
    
    $time_end2 = microtime(true);
    $time2 = $time_end2 - $time_start2;
    
    echo "Completed in ". $time2 ." seconds <hr>";
    ?>
    

    전반적인 쿼리 자체는 밀리 초 또는 그 이하가 걸렸지 만 후자 (단일 문자열) 쿼리는 일관되게 8 배 이상 빠릅니다. 이것이 더 많은 열에 수천 개의 행을 가져온 것을 반영하기 위해 만들어진 것이라면 그 차이는 엄청날 수 있습니다.

  4. ==============================

    4.

    Herbert Balagtas의 Accepted Answer는 $ 데이터 배열이 작을 때 잘 작동합니다. 큰 $ 데이터 배열을 사용하면 array_merge 함수가 너무 느려집니다. $ data 배열을 생성하기위한 테스트 파일은 28 cols이고 약 80,000 라인이다. 마지막 스크립트는 41 초가 걸렸습니다.

    array_push ()를 사용하여 array_merge () 대신 $ insert_values를 작성하면 실행 시간이 0.41 초인 100 배속으로 향상되었습니다.

    문제가되는 array_merge () :

    $insert_values = array();
    
    foreach($data as $d){
     $question_marks[] = '('  . placeholders('?', sizeof($d)) . ')';
     $insert_values = array_merge($insert_values, array_values($d));
    }
    

    array_merge ()의 필요성을 없애기 위해 대신 다음 두 배열을 작성할 수 있습니다.

    //Note that these fields are empty, but the field count should match the fields in $datafields.
    $data[] = array('','','','',... n ); 
    
    //getting rid of array_merge()
    array_push($insert_values, $value1, $value2, $value3 ... n ); 
    

    이 배열은 다음과 같이 사용할 수 있습니다.

    function placeholders($text, $count=0, $separator=","){
        $result = array();
        if($count > 0){
            for($x=0; $x<$count; $x++){
                $result[] = $text;
            }
        }
    
        return implode($separator, $result);
    }
    
    $pdo->beginTransaction();
    
    foreach($data as $d){
     $question_marks[] = '('  . placeholders('?', sizeof($d)) . ')';
    }
    
    $sql = "INSERT INTO table (" . implode(",", array_keys($datafield) ) . ") VALUES " . implode(',', $question_marks);
    
    $stmt = $pdo->prepare ($sql);
    try {
        $stmt->execute($insert_values);
    } catch (PDOException $e){
        echo $e->getMessage();
    }
    $pdo->commit();
    
  5. ==============================

    5.

    그것은 단순히 준비된 문장을 사용하는 방식이 아닙니다.

    하나의 준비된 명령문을 여러 매개 변수로 여러 번 실행할 수 있기 때문에 쿼리 당 하나의 행을 삽입해도 무방합니다. 사실 그것은 당신에게 효율적이고 안전하고 편안한 방식으로 많은 수의 행을 삽입 할 수 있기 때문에 가장 큰 장점 중 하나입니다.

    따라서 적어도 고정 된 수의 행에 대해 제안하는 체계를 구현하는 것이 가능할 수도 있지만 이것이 실제로 원하는 바가 거의 없음을 거의 보장합니다.

  6. ==============================

    6.

    가능한 두 가지 접근법 :

    $stmt = $pdo->prepare('INSERT INTO foo VALUES(:v1_1, :v1_2, :v1_3),
        (:v2_1, :v2_2, :v2_3),
        (:v2_1, :v2_2, :v2_3)');
    $stmt->bindValue(':v1_1', $data[0][0]);
    $stmt->bindValue(':v1_2', $data[0][1]);
    $stmt->bindValue(':v1_3', $data[0][2]);
    // etc...
    $stmt->execute();
    

    또는:

    $stmt = $pdo->prepare('INSERT INTO foo VALUES(:a, :b, :c)');
    foreach($data as $item)
    {
        $stmt->bindValue(':a', $item[0]);
        $stmt->bindValue(':b', $item[1]);
        $stmt->bindValue(':c', $item[2]);
        $stmt->execute();
    }
    

    모든 행에 대한 데이터가 단일 배열에 있다면 두 번째 솔루션을 사용합니다.

  7. ==============================

    7.

    더 짧은 대답 : 열에 의해 정렬 된 데이터 배열을 평평하게하십시오.

    //$array = array( '1','2','3','4','5', '1','2','3','4','5');
    $arCount = count($array);
    $rCount = ($arCount  ? $arCount - 1 : 0);
    $criteria = sprintf("(?,?,?,?,?)%s", str_repeat(",(?,?,?,?,?)", $rCount));
    $sql = "INSERT INTO table(c1,c2,c3,c4,c5) VALUES$criteria";
    

    1,000 개 정도의 레코드를 삽입 할 때 필요한 모든 레코드를 삽입하려면 모든 레코드를 루프 할 필요가 없습니다.

  8. ==============================

    8.

    다음은 내가 퍼지 옵션을 사용하여 여러 삽입 작업을 수행 한 클래스입니다.

    <?php
    
    /**
     * $pdo->beginTransaction();
     * $pmi = new PDOMultiLineInserter($pdo, "foo", array("a","b","c","e"), 10);
     * $pmi->insertRow($data);
     * ....
     * $pmi->insertRow($data);
     * $pmi->purgeRemainingInserts();
     * $pdo->commit();
     *
     */
    class PDOMultiLineInserter {
        private $_purgeAtCount;
        private $_bigInsertQuery, $_singleInsertQuery;
        private $_currentlyInsertingRows  = array();
        private $_currentlyInsertingCount = 0;
        private $_numberOfFields;
        private $_error;
        private $_insertCount = 0;
    
        function __construct(\PDO $pdo, $tableName, $fieldsAsArray, $bigInsertCount = 100) {
            $this->_numberOfFields = count($fieldsAsArray);
            $insertIntoPortion = "INSERT INTO `$tableName` (`".implode("`,`", $fieldsAsArray)."`) VALUES";
            $questionMarks  = " (?".str_repeat(",?", $this->_numberOfFields - 1).")";
    
            $this->_purgeAtCount = $bigInsertCount;
            $this->_bigInsertQuery    = $pdo->prepare($insertIntoPortion.$questionMarks.str_repeat(", ".$questionMarks, $bigInsertCount - 1));
            $this->_singleInsertQuery = $pdo->prepare($insertIntoPortion.$questionMarks);
        }
    
        function insertRow($rowData) {
            // @todo Compare speed
            // $this->_currentlyInsertingRows = array_merge($this->_currentlyInsertingRows, $rowData);
            foreach($rowData as $v) array_push($this->_currentlyInsertingRows, $v);
            //
            if (++$this->_currentlyInsertingCount == $this->_purgeAtCount) {
                if ($this->_bigInsertQuery->execute($this->_currentlyInsertingRows) === FALSE) {
                    $this->_error = "Failed to perform a multi-insert (after {$this->_insertCount} inserts), the following errors occurred:".implode('<br/>', $this->_bigInsertQuery->errorInfo());
                    return false;
                }
                $this->_insertCount++;
    
                $this->_currentlyInsertingCount = 0;
                $this->_currentlyInsertingRows = array();
            }
            return true;
        }
    
        function purgeRemainingInserts() {
            while ($this->_currentlyInsertingCount > 0) {
                $singleInsertData = array();
                // @todo Compare speed - http://www.evardsson.com/blog/2010/02/05/comparing-php-array_shift-to-array_pop/
                // for ($i = 0; $i < $this->_numberOfFields; $i++) $singleInsertData[] = array_pop($this->_currentlyInsertingRows); array_reverse($singleInsertData);
                for ($i = 0; $i < $this->_numberOfFields; $i++) array_unshift($singleInsertData, array_pop($this->_currentlyInsertingRows));
    
                if ($this->_singleInsertQuery->execute($singleInsertData) === FALSE) {
                    $this->_error = "Failed to perform a small-insert (whilst purging the remaining rows; the following errors occurred:".implode('<br/>', $this->_singleInsertQuery->errorInfo());
                    return false;
                }
                $this->_currentlyInsertingCount--;
            }
        }
    
        public function getError() {
            return $this->_error;
        }
    }
    
  9. ==============================

    9.

    여기에 간단한 접근 방식이 있습니다.

        $values = array();
        foreach($workouts_id as $value){
          $_value = "(".$value.",".$plan_id.")";
          array_push($values,$_value);
        }
        $values_ = implode(",",$values);
    
        $sql = "INSERT INTO plan_days(id,name) VALUES" . $values_."";
        $stmt = $this->conn->prepare($sql);
        $stmt->execute();
    
  10. ==============================

    10.

    이것이 내가 그랬던 방법이다 :

    먼저 사용할 컬럼 이름을 정의하거나 비워두면 pdo는 테이블의 모든 컬럼을 사용한다고 가정합니다.이 경우 테이블에 표시된 순서대로 행 값을 알려 주어야합니다 .

    $cols = 'name', 'middleName', 'eMail';
    $table = 'people';
    

    자, 이미 준비된 2 차원 배열을 가지고 있다고 가정하십시오. 그것을 반복하고 다음과 같이 행 값을 사용하여 문자열을 구성하십시오.

    foreach ( $people as $person ) {
    if(! $rowVals ) {
    $rows = '(' . "'$name'" . ',' . "'$middleName'" . ',' .           "'$eMail'" . ')';
    } else { $rowVals  = '(' . "'$name'" . ',' . "'$middleName'" . ',' . "'$eMail'" . ')';
    }
    

    자, 방금 $ 행이 정의되어 있는지 확인한 다음, $ 행이 아직 정의되어 있지 않은 경우 행의 값과 필요한 SQL 구문을 작성하여 유효한 명령문이되도록하십시오. 문자열은 큰 따옴표와 작은 따옴표로 묶어야하므로 즉시 인식됩니다.

    남은 일은 다음과 같이 명령문을 준비하고 실행하는 것입니다.

    $stmt = $db->prepare ( "INSERT INTO $table $cols VALUES $rowVals" );
    $stmt->execute ();
    

    지금까지 최대 2000 개의 행으로 테스트되었으며 실행 시간은 암울합니다. 더 많은 테스트를하고 더 기여할만한 것을 얻을 수 있도록 여기로 돌아올 것입니다.

    문안 인사.

  11. ==============================

    11.

    아직 제안되지 않았기 때문에, LOAD DATA INFILE이 인덱싱을 비활성화하고 모든 데이터를 삽입 한 다음 인덱스를 다시 활성화 할 때 데이터를로드하는 가장 빠른 방법 인 것처럼 확신합니다.

    csv로 데이터를 저장하는 것은 fputcsv를 염두에두면 꽤 사소한 일입니다. MyISAM은 가장 빠르지 만 여전히 InnoDB에서 큰 성능을 얻습니다. 다른 단점이 있습니다. 그렇지만 많은 양의 데이터를 삽입하고 100 행 미만으로 신경 쓸 필요는 없습니다.

  12. ==============================

    12.

    낡은 질문이 모든 도움을 많이 주었지만 내 솔루션은 내 자신의 DbContext 클래스 내에서 작동합니다. $ rows 매개 변수는 단순히 행 또는 모델을 나타내는 연관 배열의 배열입니다. field name => insert value.

    모델을 사용하는 패턴을 사용하면 모델 데이터를 배열로 전달할 때 멋지게 잘 맞습니다. 예를 들어 모델 클래스 내의 ToRowArray 메소드에서 말하십시오.

    public function InsertRange($tableName, $rows)
    {
        // Get column list
        $columnList = array_keys($rows[0]);
        $numColumns = count($columnList);
        $columnListString = implode(",", $columnList);
    
        // Generate pdo param placeholders
        $placeHolders = array();
    
        foreach($rows as $row)
        {
            $temp = array();
    
            for($i = 0; $i < count($row); $i++)
                $temp[] = "?";
    
            $placeHolders[] = "(" . implode(",", $temp) . ")";
        }
    
        $placeHolders = implode(",", $placeHolders);
    
        // Construct the query
        $sql = "insert into $tableName ($columnListString) values $placeHolders";
        $stmt = $this->pdo->prepare($sql);
    
        $j = 1;
        foreach($rows as $row)
        {
            for($i = 0; $i < $numColumns; $i++)
            {
                $stmt->bindParam($j, $row[$columnList[$i]]);
                $j++;
            }
        }
    
        $stmt->execute();
    }
    
  13. ==============================

    13.

    이 함수를 사용하면 단일 쿼리에 여러 행을 삽입 할 수 있습니다.

    function insertMultiple($query,$rows) {
        if (count($rows)>0) {
            $args = array_fill(0, count($rows[0]), '?');
    
            $params = array();
            foreach($rows as $row)
            {
                $values[] = "(".implode(',', $args).")";
                foreach($row as $value)
                {
                    $params[] = $value;
                }
            }
    
            $query = $query." VALUES ".implode(',', $values);
            $stmt = $PDO->prepare($query);
            $stmt->execute($params);
        }
    }
    

    $ row는 값 배열의 배열입니다. 당신의 경우에는

    insertMultiple("INSERT INTO tbl (`key1`,`key2`)",array(array('r1v1','r1v2'),array('r2v1','r2v2')));
    

    단일 쿼리로 여러 행을 삽입하는 동안 준비된 문을 사용하면 이점이 있습니다. 보안!

  14. ==============================

    14.

    이것은 나를 위해 일했다.

        $sql = 'INSERT INTO table(pk_pk1,pk_pk2,date,pk_3) VALUES '; 
        $qPart = array_fill(0, count($array), "(?, ?,UTC_TIMESTAMP(),?)");
     $sql .= implode(",", $qPart);
     $stmt =    DB::prepare('base', $sql);
         $i = 1;
         foreach ($array as $value) 
           { 
           $stmt->bindValue($i++, $value);
           $stmt->bindValue($i++, $pk_pk1);
           $stmt->bindValue($i++, $pk_pk2); 
          $stmt->bindValue($i++, $pk_pk3); 
          } 
        $stmt->execute();
    
  15. ==============================

    15.

    내 솔루션은 다음과 같습니다. https://github.com/sasha-ch/Aura.Sql auraphp / Aura.Sql 라이브러리를 기반으로합니다.

    사용 예 :

    $q = "insert into t2(id,name) values (?,?), ... on duplicate key update name=name"; 
    $bind_values = [ [[1,'str1'],[2,'str2']] ];
    $pdo->perform($q, $bind_values);
    

    버그 리포트를 환영합니다.

  16. ==============================

    16.

    빈 테이블에 모든 독일어 우편 코드를 삽입하는 실제 예 (나중에 도시 이름 추가) :

    // obtain column template
    $stmt = $db->prepare('SHOW COLUMNS FROM towns');
    $stmt->execute();
    $columns = array_fill_keys(array_values($stmt->fetchAll(PDO::FETCH_COLUMN)), null);
    // multiple INSERT
    $postcode = '01000';// smallest german postcode
    while ($postcode <= 99999) {// highest german postcode
        $values = array();
        while ($postcode <= 99999) {
            // reset row
            $row = $columns;
            // now fill our row with data
            $row['postcode'] = sprintf('%05d', $postcode);
            // build INSERT array
            foreach ($row as $value) {
                $values[] = $value;
            }
            $postcode++;
            // avoid memory kill
            if (!($postcode % 10000)) {
                break;
            }
        }
        // build query
        $count_columns = count($columns);
        $placeholder = ',(' . substr(str_repeat(',?', $count_columns), 1) . ')';//,(?,?,?)
        $placeholder_group = substr(str_repeat($placeholder, count($values) / $count_columns), 1);//(?,?,?),(?,?,?)...
        $into_columns = implode(',', array_keys($columns));//col1,col2,col3
        // this part is optional:
        $on_duplicate = array();
        foreach ($columns as $column => $row) {
            $on_duplicate[] = $column;
            $on_duplicate[] = $column;
        }
        $on_duplicate = ' ON DUPLICATE KEY UPDATE' . vsprintf(substr(str_repeat(', %s = VALUES(%s)', $count_columns), 1), $on_duplicate);
        // execute query
        $stmt = $db->prepare('INSERT INTO towns (' . $into_columns . ') VALUES' . $placeholder_group . $on_duplicate);//INSERT INTO towns (col1,col2,col3) VALUES(?,?,?),(?,?,?)... {ON DUPLICATE...}
        $stmt->execute($values);
    }
    

    당신이 볼 수 있듯이 완전히 유연합니다. 기둥의 수를 확인하거나 기둥이 어느 위치에 있는지 확인할 필요가 없습니다. 삽입 데이터 만 설정하면됩니다.

        $row['postcode'] = sprintf('%05d', $postcode);
    

    array_merge와 같은 무거운 배열 함수없이 작동하기 때문에 쿼리 문자열 생성자 중 일부를 자랑스럽게 생각합니다. 특히 vsprintf ()는 좋은 발견이었습니다.

    마지막으로 메모리 제한을 초과하지 않으려면 while ()을 2x 추가해야했습니다. 이것은 메모리 제한에 달려 있지만 문제를 피하기위한 좋은 해결책입니다 (10 개의 쿼리를 사용하면 여전히 10.000보다 훨씬 낫습니다).

  17. ==============================

    17.

    test.php

    <?php
    require_once('Database.php');
    
    $obj = new Database();
    $table = "test";
    
    $rows = array(
        array(
        'name' => 'balasubramani',
        'status' => 1
        ),
        array(
        'name' => 'balakumar',
        'status' => 1
        ),
        array(
        'name' => 'mani',
        'status' => 1
        )
    );
    
    var_dump($obj->insertMultiple($table,$rows));
    ?>
    

    Database.php

    <?php
    class Database 
    {
    
        /* Initializing Database Information */
    
        var $host = 'localhost';
        var $user = 'root';
        var $pass = '';
        var $database = "database";
        var $dbh;
    
        /* Connecting Datbase */
    
        public function __construct(){
            try {
                $this->dbh = new PDO('mysql:host='.$this->host.';dbname='.$this->database.'', $this->user, $this->pass);
                //print "Connected Successfully";
            } 
            catch (PDOException $e) {
                print "Error!: " . $e->getMessage() . "<br/>";
                die();
            }
        }
    /* Insert Multiple Rows in a table */
    
        public function insertMultiple($table,$rows){
    
            $this->dbh->beginTransaction(); // also helps speed up your inserts.
            $insert_values = array();
            foreach($rows as $d){
                $question_marks[] = '('  . $this->placeholders('?', sizeof($d)) . ')';
                $insert_values = array_merge($insert_values, array_values($d));
                $datafields = array_keys($d);
            }
    
            $sql = "INSERT INTO $table (" . implode(",", $datafields ) . ") VALUES " . implode(',', $question_marks);
    
            $stmt = $this->dbh->prepare ($sql);
            try {
                $stmt->execute($insert_values);
            } catch (PDOException $e){
                echo $e->getMessage();
            }
            return $this->dbh->commit();
        }
    
        /*  placeholders for prepared statements like (?,?,?)  */
    
        function placeholders($text, $count=0, $separator=","){
            $result = array();
            if($count > 0){
                for($x=0; $x<$count; $x++){
                    $result[] = $text;
                }
            }
    
            return implode($separator, $result);
        }
    
    }
    ?>
    
  18. ==============================

    18.

    준비된 쿼리를 작성하기 위해 여기에 제공된 대부분의 솔루션은 필요할 때보 다 더 복잡합니다. PHP의 내장 함수를 사용하면 상당한 오버 헤드없이 SQL 문을 쉽게 작성할 수 있습니다.

    $ 레코드가 주어지면 각 레코드 자체가 인덱스 배열 (field => value 형식) 인 레코드 배열이 주어지면 다음 함수는 주어진 테이블 $ table, PDO 연결 $ connection에 레코드를 삽입합니다 단 하나의 준비된 진술. array_push를 호출 할 때 인수 풀기를 사용하기 때문에 이것은 PHP 5.6+ 솔루션입니다.

    private function import(PDO $connection, $table, array $records)
    {
        $fields = array_keys($records[0]);
        $placeHolders = substr(str_repeat(',?', count($fields)), 1);
        $values = [];
        foreach ($records as $record) {
            array_push($values, ...array_values($record));
        }
    
        $query = 'INSERT INTO ' . $table . ' (';
        $query .= implode(',', $fields);
        $query .= ') VALUES (';
        $query .= implode('),(', array_fill(0, count($records), $placeHolders));
        $query .= ')';
    
        $statement = $connection->prepare($query);
        $statement->execute($values);
    }
    
  19. ==============================

    19.

    배열 합집합은 array_push보다 훨씬 빨라야합니다.

    $cumulativeArray += $rowArray; 
    
  20. from https://stackoverflow.com/questions/1176352/pdo-prepared-inserts-multiple-rows-in-single-query by cc-by-sa and MIT lisence