পিএইচপি অ্যারের মাধ্যমে একাধিক সারি মাইএসকিএলে প্রবেশ করান


129

আমি পিএসপিএফের মাধ্যমে সন্নিবেশ কমান্ডগুলি ব্যবহার করে একটি মাইএসকিউএল টেবিলের মধ্যে একটি বড় ডেটাসেটটি পাস করছি এবং আমি ভাবছি যে এক মাইল দীর্ঘ স্ট্রিংয়ের শেষে প্রতিটি মান সংযোজন ব্যতীত অন্য ক্যোয়ারির মাধ্যমে এক সাথে প্রায় 1000 সারি সন্নিবেশ করা সম্ভব কিনা? এটি কার্যকর। আমি কোডআইগনিটার ফ্রেমওয়ার্ক ব্যবহার করছি তাই এর ফাংশনগুলিও আমার কাছে উপলব্ধ।


আমি কোডইনিটারের একাধিক সারি সন্নিবেশ করানোর জন্য আপনার প্রশ্ন অনুসারে উত্তর দিয়েছি।
সোমনাথ মুলুক

@ সোমনাথ মুলুক আপনাকে ধন্যবাদ, তবে এই প্রশ্নের উত্তর দেওয়ার জন্য আমার যখন খুব বেশি সময় প্রয়োজন হয়েছে:) ... ...
toofarsideways

আমি CodeIgniter এর insert_batch ফাংশনটি ব্যবহার করার পরামর্শ দেব। আপনি যদি কোনও লাইব্রেরি ব্যবহার করেন তবে সর্বদা এটির শক্তি এবং কোডিং মানগুলিকে কাজে লাগানোর চেষ্টা করুন।
দেওয়াল্ড এলস

আমি বিশ্বাস করি যে সন্নিবেশ ব্যাচটি করার সবচেয়ে ভাল উপায়টি
সৈয়দ আমির বুখারী

উত্তর:


234

INSERTএকাধিক সারি সহ একটি বিবৃতি একত্রিত করা মাইএসকিউএলে INSERTসারি প্রতি এক বিবৃতি চেয়ে অনেক দ্রুত ।

এটি বলেছিল, মনে হচ্ছে আপনি পিএইচপি-তে স্ট্রিং-হ্যান্ডলিংয়ের সমস্যায় পড়ে যাচ্ছেন, যা সত্যিই একটি অ্যালগরিদম সমস্যা, কোনও ভাষা নয়। মূলত, বড় স্ট্রিংয়ের সাথে কাজ করার সময়, আপনি অপ্রয়োজনীয় অনুলিপিটি হ্রাস করতে চান। প্রাথমিকভাবে, এর অর্থ আপনি কনকনেটেশন এড়াতে চান। একটি বড় স্ট্রিং তৈরির দ্রুততম এবং সর্বাধিক মেমরির দক্ষ উপায়, যেমন একদিকে কয়েকশো সারি সন্নিবেশ করানোর জন্য, implode()ফাংশনটি এবং অ্যারে নিয়োগের সুবিধা গ্রহণ করা ।

$sql = array(); 
foreach( $data as $row ) {
    $sql[] = '("'.mysql_real_escape_string($row['text']).'", '.$row['category_id'].')';
}
mysql_query('INSERT INTO table (text, category) VALUES '.implode(',', $sql));

এই পদ্ধতির সুবিধাটি হ'ল আপনি যে এসকিউএল স্টেটমেন্টটি এ পর্যন্ত প্রতিটি কনক্যান্টেশন সহ একত্রিত করেছেন তা অনুলিপি এবং অনুলিপি করবেন না; পরিবর্তে, পিএইচপি বিবৃতিতে একবার এটি করে implode()। এটি একটি বড় জয়।

যদি আপনার একসাথে রাখার জন্য প্রচুর কলাম থাকে এবং এক বা একাধিক দীর্ঘ হয় তবে আপনি একই জিনিসটি করতে অভ্যন্তরীণ লুপটি তৈরি করতে পারেন implode()এবং বহির্মুখানের অ্যারেগুলিতে মান ধারাটি নির্ধারণ করতে ব্যবহার করতে পারেন ।


5
তার জন্য ধন্যবাদ! যদি কারও এটি অনুলিপি করার পরিকল্পনা করা হয় তবে ফাংশন শেষে আপনার বন্ধ হওয়া বন্ধনীটি হারিয়ে যাওয়া বিটিডব্লিউ। mysql_real_query ('টেবিল ভ্যালুতে অন্তর্ভুক্ত করুন (পাঠ্য, বিভাগ)' .আইপিপ্লোড (','। $ বর্গ));
toofarsideways

3
ধন্যবাদ! সংশোধন করা হয়েছে। (আমি প্রায়শই এটি করি ...)
স্ট্যাটিকসান

1
এবং ক্যোয়ারীটি সত্যই 'অন্তর্ভুক্ত টেবিলের (পাঠ্য, বিভাগ) ভ্যালুতে থাকা উচিত .আইপিপ্লোড (', '। $ বর্গ)' দীর্ঘ 4 টা কোডিং কোডিং ভয়ঙ্কর ডিবাগের দিকে নিয়ে যায় :(
টুফারসাইডওয়েজ

3
আমি বিশ্বাস করি যে এই কোডটি আমার সর্বশেষ প্রকল্পের জন্য একটি সমাধান তৈরি করবে। আমার প্রশ্ন এখানে, এসকিউএল ইঞ্জেকশন থেকে এটি নিরাপদ? আমার পরিকল্পনা আউট স্যুইচ করতে হয় mysql_real_escape_stringসঙ্গে mysqli_real_escape_stringএবং mysql_queryসঙ্গে mysqli_queryহিসাবে আমি MySQLi ব্যবহার করছি এবং এই PHP5 হিসাবে অবচিত হয়েছে। অনেক ধন্যবাদ!
ওয়ার্ডম্যান

2
mysql_*পিএইচপি থেকে সরানো হয়েছে, তাই mysqli_*ইন্টারফেসটি ব্যবহার করতে ভুলবেন না ।
রিক জেমস

60

একাধিক সন্নিবেশ / ব্যাচ সন্নিবেশ এখন কোডাইনাইটার দ্বারা সমর্থিত। আমারও একই সমস্যা ছিল প্রশ্নের উত্তরের জন্য খুব দেরি হলেও এটি কারওর পক্ষে সহায়তা করবে। এই কারণেই এই প্রশ্নের উত্তর দেওয়া।

$data = array(
   array(
      'title' => 'My title' ,
      'name' => 'My Name' ,
      'date' => 'My date'
   ),
   array(
      'title' => 'Another title' ,
      'name' => 'Another Name' ,
      'date' => 'Another date'
   )
);

$this->db->insert_batch('mytable', $data);

// Produces: INSERT INTO mytable (title, name, date) VALUES ('My title', 'My name', 'My date'), ('Another title', 'Another name', 'Another date')

2
আমি মনে করি এটি mysql_query ব্যবহার না করে মাল্টি সারি সন্নিবেশ করানোর সর্বাধিক প্রস্তাবিত উপায় recommended কারণ যখন আমরা কোনও কাঠামো ব্যবহার করি তখন কাঠামোর অভ্যন্তরীণ বৈশিষ্ট্যগুলি সর্বদা ব্যবহার করা ভাল অভ্যাস।
প্রণীত নিদর্শন

22

আপনি mysqli_stmt ক্লাসটি ব্যবহার করে একটি সারি সন্নিবেশ করানোর জন্য ক্যোয়ারী প্রস্তুত করতে পারেন এবং তারপরে ডেটা অ্যারেতে পুনরাবৃত্তি করতে পারেন। কিছুটা এইরকম:

$stmt =  $db->stmt_init();
$stmt->prepare("INSERT INTO mytbl (fld1, fld2, fld3, fld4) VALUES(?, ?, ?, ?)");
foreach($myarray as $row)
{
    $stmt->bind_param('idsb', $row['fld1'], $row['fld2'], $row['fld3'], $row['fld4']);
    $stmt->execute();
}
$stmt->close();

যেখানে 'আইডসবি' হ'ল সেই ধরণের ডেটা যেখানে আপনি বাঁধছেন (ইনট, ডবল, স্ট্রিং, ব্লব)।


6
আমি সম্প্রতি বাল্ক সন্নিবেশের সাথে তুলনা করে কিছু বেঞ্চমার্ক চালিয়েছি এবং এখানে উল্লিখিত হিসাবে সন্নিবেশ বিবৃতি প্রস্তুত করেছি। প্রায় 500 টি সন্নিবেশের জন্য, প্রস্তুত সন্নিবেশ পদ্ধতিটি 2.6-4.4 সেকেন্ডের মধ্যে এবং বাল্ক সন্নিবেশ পদ্ধতিটি 0.12-0.35 সেকেন্ডের মধ্যে সম্পন্ন হয়। আমি ভাবতাম যে মাইএসকিএল এই প্রস্তুত বিবৃতিগুলি একসাথে "বাল্ক" করেছে এবং বাল্ক সন্নিবেশগুলির পাশাপাশি সম্পাদন করবে, তবে একটি ডিফল্ট সেট আপে দৃশ্যত পারফরম্যান্সের পার্থক্য বিশাল। (বিটিডব্লিউর সমস্ত বেঞ্চমার্কযুক্ত প্রশ্নগুলি স্বয়ংক্রিয় প্রতিশ্রুতি রোধে প্রতিটি পরীক্ষার জন্য একটি একক লেনদেনের মধ্যে চলছিল)
মতিন

16

আমি জানি এটি একটি পুরানো প্রশ্ন, তবে আমি কেবল পড়ছিলাম এবং ভেবেছিলাম যে আমি অন্য কোথাও যা পেয়েছি তা যুক্ত করব:

পিএইচপি 5-তে মাইসকিলি হ'ল কিছু ভাল ফাংশন সহ একটি ওজবেক্ট যা আপনাকে উপরের উত্তরের জন্য সন্নিবেশের সময়টি দ্রুত করতে দেয়:

$mysqli->autocommit(FALSE);
$mysqli->multi_query($sqlCombined);
$mysqli->autocommit(TRUE);

অনেকগুলি সারি সন্নিবেশ করানোর সময় স্বতঃসংশোধন বন্ধ করা সন্নিবেশকে তীব্র করে তোলে, তাই এটি বন্ধ করুন, তারপরে উপরে উল্লিখিত হিসাবে সম্পাদন করুন, বা কেবল একটি স্ট্রিং (স্কেলকোম্বাইনেড) করুন যা আধা-কোলন দ্বারা বিভক্ত বহু সন্নিবেশ বিবৃতি এবং মাল্টি-কোয়েরি এগুলি সূক্ষ্মভাবে পরিচালনা করবে।

আশা করি এটি কাউকে সময় বাঁচাতে সহায়তা করবে (অনুসন্ধান এবং সন্নিবেশ!)

আর


আপনার ধারণাটি ব্যবহার করে আমি এই ত্রুটিটি পেয়েছি: "মারাত্মক ত্রুটি:
হোমেপেজ

8

আপনি সর্বদা মাইএসকিএল ব্যবহার করতে পারেন LOAD DATA:

LOAD DATA LOCAL INFILE '/full/path/to/file/foo.csv' INTO TABLE `footable` FIELDS TERMINATED BY ',' LINES TERMINATED BY '\r\n' 

গুচ্ছ INSERTবিবৃতি ব্যবহার না করে বাল্ক সন্নিবেশগুলি করতে ।


আমি এটি দেখেছিলাম কিন্তু তথ্য সন্নিবেশ করার আগে আমার হস্তক্ষেপ করা দরকার। এটি আমাকে কার্টেসিয়ান পণ্য হিসাবে 1400 বাই 1400 ইনট মানগুলির সেট করে দেয় যার মধ্যে অনেকগুলি শূন্য। স্থান বাঁচানোর জন্য মধ্যস্থতাকারী টেবিল ব্যবহার করে আমার এটি অনেকের সাথে অনেকগুলিতে রূপান্তর করা দরকার সুতরাং একটি বাল্ক সন্নিবেশের বিপরীতে সন্নিবেশগুলির প্রয়োজন
টুফারসাইডওয়েজ

আপনি সর্বদা একটি সিএসভি ফাইল তৈরি করতে পারেন এটি পরিচালনা করে এবং মাইএসকিএল বিবৃতিতে কল করার পরে যা ডেটা লোড করে
আলেকজান্ডার জারডিম

আমি মনে করি যে এটি আপনার এসকিউএল ক্লায়েন্টের কাছে এবং এটি এসকিউএল সার্ভারে নয় তবে এটি স্থানীয় is ফাইলটি সার্ভারে আপলোড করা হয় এবং তারপরে এটি পড়ে। আমি ভেবেছিলাম ফাইলটি ইতিমধ্যে সার্ভারে থাকা উচিত, এটি ক্ষেত্রে নেই। এটি ইতিমধ্যে সার্ভারে থাকলে, LOCALবিটটি সরিয়ে দিন ।
কাইল

5

ভাল, আপনি 1000 ক্যোয়ারী কলগুলি কার্যকর করতে চান না, তবে এটি করা ভাল:

$stmt= array( 'array of statements' );
$query= 'INSERT INTO yourtable (col1,col2,col3) VALUES ';
foreach( $stmt AS $k => $v ) {
  $query.= '(' .$v. ')'; // NOTE: you'll have to change to suit
  if ( $k !== sizeof($stmt)-1 ) $query.= ', ';
}
$r= mysql_query($query);

আপনার ডেটা উত্সের উপর নির্ভর করে অ্যারে পপুলেট করা কোনও ফাইল খোলার এবং সামগ্রীগুলি একটি অ্যারেতে ফেলে দেওয়ার মতো সহজ হতে পারে file()


1
আপনি যদি ক্যোয়ারির উপরে থাকেন এবং এটিকে ($ k> 0) এর মতো কিছুতে পরিবর্তন করেন তবে এটি পরিষ্কার।
চেরোভিম

@ চেরুভিম ... ঠিক আছে, তুমি ঠিক তাই করেছ। আপনার ইনপুট জন্য ধন্যবাদ। আমি যে উদাহরণটি দিয়েছি তা পুনরায় পড়ছি, আমি আপনার বক্তব্যটি দেখতে ব্যর্থ হয়েছি। বিস্তারিত জানাতে যত্ন করুন (পেস্টবিন ইত্যাদির মাধ্যমে?)। Thanks-
bdl

3
$query= array(); 
foreach( $your_data as $row ) {
    $query[] = '("'.mysql_real_escape_string($row['text']).'", '.$row['category_id'].')';
}
mysql_query('INSERT INTO table (text, category) VALUES '.implode(',', $query));

1

আপনি কোডাইনাইটার যেমন বেশ কয়েকটি উপায়ে এটি করতে পারেন

লুপ দ্বারা প্রথম

foreach($myarray as $row)
{
   $data = array("first"=>$row->first,"second"=>$row->sec);
   $this->db->insert('table_name',$data);
}

দ্বিতীয় - সন্নিবেশ ব্যাচ দ্বারা

$data = array(
       array(
          'first' => $myarray[0]['first'] ,
          'second' => $myarray[0]['sec'],
        ),
       array(
          'first' => $myarray[1]['first'] ,
          'second' => $myarray[1]['sec'],
        ),
    );

    $this->db->insert_batch('table_name', $data);

তৃতীয় উপায় - একাধিক মান পাসের মাধ্যমে

$sql = array(); 
foreach( $myarray as $row ) {
    $sql[] = '("'.mysql_real_escape_string($row['first']).'", '.$row['sec'].')';
}
mysql_query('INSERT INTO table (first, second) VALUES '.implode(',', $sql));

1

যদিও এই প্রশ্নের উত্তর দিতে দেরি হয়ে গেছে। এখানে আমার উত্তর একই।

আপনি যদি কোডআইগনিটার ব্যবহার করছেন তবে আপনি ক্যোয়ারী-বিল্ডার শ্রেণিতে সংজ্ঞায়িত ইনবিল্ট পদ্ধতিগুলি ব্যবহার করতে পারেন।

$ This-> db-> insert_batch ()

আপনার সরবরাহ করা ডেটার উপর ভিত্তি করে একটি সন্নিবেশ স্ট্রিং উত্পন্ন করে এবং ক্যোয়ারি চালায়। আপনি হয় ফাংশনটিতে একটি অ্যারে বা কোনও বস্তু পাস করতে পারেন। এখানে অ্যারে ব্যবহার করে একটি উদাহরণ দেওয়া হল:

$data = array(
    array(
            'title' => 'My title',
            'name' => 'My Name',
            'date' => 'My date'
    ),
    array(
            'title' => 'Another title',
            'name' => 'Another Name',
            'date' => 'Another date'
    )

);

$this->db->insert_batch('mytable', $data);
// Produces: INSERT INTO mytable (title, name, date) VALUES ('My title', 'My name', 'My date'),  ('Another title', 'Another name', 'Another date')

প্রথম প্যারামিটারে টেবিলের নাম থাকবে, দ্বিতীয়টি মানগুলির একটি মিশুক অ্যারে।

আপনি ক্যোয়ারী-বিল্ডার সম্পর্কে আরও বিশদ এখানে পাবেন


0

আমি এমন একটি শ্রেণি তৈরি করেছি যা মাল্টি-লাইন সম্পাদন করে যা নীচে ব্যবহৃত হয়:

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

    /**
     * Create a PDOMultiLine Insert object.
     *
     * @param PDO $pdo              The PDO connection
     * @param type $tableName       The table name
     * @param type $fieldsAsArray   An array of the fields being inserted
     * @param type $bigInsertCount  How many rows to collect before performing an insert.
     */
    function __construct(PDO $pdo, $tableName, $fieldsAsArray, $bigInsertCount = 100) {
        $this->_numberOfFields = count($fieldsAsArray);
        $insertIntoPortion = "REPLACE 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;
    }
}

0

একাধিক সারি ডেটা সন্নিবেশ করতে কোডইনিটারে সন্নিবেশ ব্যাচটি ব্যবহার করুন।

$this->db->insert_batch('tabname',$data_array); // $data_array holds the value to be inserted

0

আমি এই সহজ ফাংশনটি তৈরি করেছি যা আপনি ছেলেরা সহজেই ব্যবহার করতে পারেন। আপনাকে সন্নিবেশ করানো ডেটা, ডেটা অ্যারের বিরুদ্ধে সারণী-নাম ($tbl), সারণী-ক্ষেত্রটি পাস করতে হবে ।($insertFieldsArr)($arr)

insert_batch('table',array('field1','field2'),$dataArray);

    function insert_batch($tbl,$insertFieldsArr,$arr){ $sql = array(); 
    foreach( $arr as $row ) {
        $strVals='';
        $cnt=0;
        foreach($insertFieldsArr as $key=>$val){
            if(is_array($row)){
                $strVals.="'".mysql_real_escape_string($row[$cnt]).'\',';
            }
            else{
                $strVals.="'".mysql_real_escape_string($row).'\',';
            }
            $cnt++;
        }
        $strVals=rtrim($strVals,',');
        $sql[] = '('.$strVals.')';
    }

    $fields=implode(',',$insertFieldsArr);
    mysql_query('INSERT INTO `'.$tbl.'` ('.$fields.') VALUES '.implode(',', $sql));
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.