mysql में php एरे के माध्यम से कई पंक्तियाँ डालें


129

मैं PHP कमांड्स का उपयोग करके PHP के माध्यम से एक MySQL टेबल में एक बड़ा डेटासेट पास कर रहा हूं और अगर एक मील लंबी स्ट्रिंग के अंत में प्रत्येक मान को जोड़ने के अलावा एक क्वेरी के माध्यम से एक बार में लगभग 1000 पंक्तियों को सम्मिलित करना संभव है, तो मैं सोच रहा हूं इसे क्रियान्वित करना। मैं CodeIgniter ढांचे का उपयोग कर रहा हूं, इसलिए इसके कार्य मेरे लिए भी उपलब्ध हैं।


मैंने Codeigniter की कई पंक्ति डालने के लिए आपके प्रश्न के अनुसार उत्तर दिया है।
सोमनाथ मुलुक

@SomnathMuluk धन्यवाद, हालांकि मुझे इस सवाल का जवाब देने की आवश्यकता होने के बाद से कुछ समय हो गया है
:)

मैं CodeIgniter के Insert_batch फ़ंक्शन का उपयोग करने की सलाह दूंगा। यदि आप एक पुस्तकालय का उपयोग करते हैं, तो हमेशा इसकी ताकत और कोडिंग मानकों का लाभ उठाने का प्रयास करें।
डेवल्ड एल्स

मेरा मानना ​​है कि सम्मिलित बैच ऐसा करने का सबसे अच्छा तरीका है कि लिंक stackoverflow.com/questions/27206178/codeigniter-insert-batch
सैयद अमीर बुखारी

जवाबों:


234

एक पंक्ति में INSERTएक INSERTकथन की तुलना में कई पंक्तियों के साथ एक पंक्ति में MySQL में बहुत तेज़ है ।

उस ने कहा, ऐसा लगता है कि आप PHP में स्ट्रिंग-हैंडलिंग समस्याओं में चल रहे हो सकते हैं, जो वास्तव में एक एल्गोरिथ्म समस्या है, भाषा नहीं। मूल रूप से, बड़े स्ट्रिंग्स के साथ काम करते समय, आप अनावश्यक नकल को कम करना चाहते हैं। मुख्य रूप से, इसका मतलब है कि आप सहमति से बचना चाहते हैं। एक बड़ी स्ट्रिंग बनाने के लिए सबसे तेज़ और सबसे मेमोरी कुशल तरीका, जैसे एक पर सैकड़ों पंक्तियाँ डालने के लिए, 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));

इस दृष्टिकोण का लाभ यह है कि आप उस एसक्यूएल स्टेटमेंट को कॉपी और री-कॉपी नहीं करते हैं, जिसे आपने अब तक प्रत्येक कॉन्सेप्टेशन के साथ इकट्ठा किया है; इसके बजाय, PHP बयान में एक बार ऐसा करता है implode()। यह एक बड़ी जीत है।

यदि आपके पास एक साथ रखने के लिए बहुत सारे स्तंभ हैं, और एक या एक से अधिक लंबे हैं, तो आप एक ही काम करने के लिए एक आंतरिक लूप का निर्माण कर सकते हैं और implode()बाहरी सरणी के मान मान को असाइन करने के लिए उपयोग कर सकते हैं।


5
उसके लिए धन्यवाद! यदि कोई भी इसे कॉपी करने की योजना बना रहा है, तो फ़ंक्शन के अंत में अपने गुम समापन ब्रैकेट को Btw। mysql_real_query ('INSERT INTO तालिका VALUES (पाठ, श्रेणी)' .implode (',' $ sql));
टॉपरसाइडवेज़

3
धन्यवाद! फिक्स्ड। (मैं अक्सर ऐसा करता हूं ...)
स्टेटिक्सन

1
और क्वेरी वास्तव में 'INSERT INTO तालिका (पाठ, श्रेणी) VALUES' .implode (',' '$ sql) होनी चाहिए,' 4 sq 'आह कोडिंग भयानक डिबगिंग की ओर जाता है :(
toofarsideways

3
मुझे विश्वास है कि यह कोड मेरी नवीनतम परियोजना के लिए एक समाधान तैयार करेगा। मेरा सवाल यहाँ है, क्या यह SQL इंजेक्शन से सुरक्षित है? मेरी योजना MySQLi का उपयोग करने के mysql_real_escape_stringसाथ mysqli_real_escape_stringऔर उसके mysql_queryसाथ स्विच करने की है mysqli_queryऔर इन्हें PHP5 के रूप में हटा दिया गया है। बहुत धन्यवाद!
वर्डमैन

2
mysql_*PHP से हटा दिया गया है, इसलिए 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 का उपयोग करके बहु पंक्ति सम्मिलित करने का सबसे अनुशंसित तरीका है। क्योंकि जब हम एक फ्रेमवर्क का उपयोग करते हैं तो फ्रेमवर्क की अंतर्निहित विशेषताओं का उपयोग करना एक अच्छा अभ्यास है।
प्रणीत निदर्शन

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

जहाँ 'idsb' उस डेटा के प्रकार हैं जिसे आप बाँध रहे हैं (int, double, string, blob)।


6
मैंने हाल ही में कुछ बेंचमार्क की तुलना बल्क इंसर्ट से की है और यहां दिए गए इंसर्ट स्टेटमेंट तैयार किए हैं। लगभग 500 आवेषणों के लिए, तैयार आवेषण विधि 2.6-4.4 सेकेंड के बीच पूरी हुई, और 0.12-0.33 सेकंड में थोक सम्मिलित विधि। मुझे लगता है कि mysql ने इन तैयार बयानों को एक साथ "बल्क" कर दिया होगा और साथ ही साथ बल्क इंसर्ट भी करेंगे, लेकिन डिफॉल्ट सेट-अप में, प्रदर्शन का अंतर बहुत बड़ा है। (Btw सभी बेंचमार्क किए गए प्रश्न प्रत्येक परीक्षण के लिए एक एकल लेनदेन के अंदर चल रहे थे, जैसा कि ऑटो-
कमिटिंग

16

मुझे पता है कि यह एक पुरानी क्वेरी है, लेकिन मैं सिर्फ पढ़ रहा था और सोचा था कि मुझे वह मिल जाएगा जो मुझे कहीं और मिला:

PHP 5 में mysqli कुछ अच्छे कार्यों के साथ एक ओजबक्ट है जो आपको उत्तर के लिए प्रविष्टि समय को गति देने की अनुमति देगा:

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

कई पंक्तियों को सम्मिलित करते समय ऑटोकॉमिट को बंद करने से सम्मिलन में बहुत तेजी आती है, इसलिए इसे बंद करें, फिर ऊपर बताए अनुसार निष्पादित करें, या बस एक स्ट्रिंग (sqlCombined) करें, जो अर्ध-कॉलन और बहु-क्वेरी द्वारा अलग किए गए कई सम्मिलित बयान हैं जो उन्हें ठीक से संभाल लेंगे।

आशा है कि यह किसी को समय बचाने में मदद करता है (खोज और सम्मिलित करना!)

आर


यह वह त्रुटि है जो मुझे आपके विचार का उपयोग करने में मिली है: "घातक त्रुटि: एक सदस्य फ़ंक्शन को कॉल करें autocommit () null in /homepages/25/d402746174/htdocs/MoneyMachine/squQuotes.php पर लाइन 30"
user3217883

8

आप हमेशा mysql का उपयोग कर सकते हैं 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 के अंतर मूल्य हैं जिनमें से कई शून्य हैं। मुझे अंतरिक्ष को बचाने के लिए एक मध्यस्थ तालिका का उपयोग करके कई संबंधों में बदलने की आवश्यकता है, इसलिए आवेषण के लिए एक बल्क डालने के विपरीत की आवश्यकता है
toofarsideways

आप इसे हेरफेर करने और डेटा लोड करने वाले mysql स्टेटमेंट पर कॉल करने के बाद हमेशा एक csv फ़ाइल उत्पन्न कर सकते हैं
अलेक्जेंडर जार्डिम

मुझे लगता है कि यह जानना उपयोगी है कि पथ आपके SQL क्लाइंट के लिए स्थानीय है, और SQL सर्वर पर नहीं। फ़ाइल सर्वर पर अपलोड की जाती है और फिर इसके द्वारा पढ़ी जाती है। मुझे लगा कि फ़ाइल को सर्वर पर पहले से ही होना था, जो कि ऐसा नहीं है। यदि यह पहले से ही सर्वर पर है, तो 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)।
चेरोविम

@cherouvim ... खैर, आप इसके बारे में सही हैं। आपके सहयोग के लिए धन्यवाद। जैसा कि मैंने अपने द्वारा दिए गए उदाहरण को फिर से पढ़ा है, मैं आपकी बात को देखने में असफल रहा हूँ। देखभाल करने के लिए विस्तृत करें (pastebin के माध्यम से, आदि?)। धन्यवाद
बीडीएल

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

आप इसे codeigniter उदा जैसे कई तरीकों से कर सकते हैं

पहले लूप द्वारा

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

हालांकि इस सवाल का जवाब देने में बहुत देर हो चुकी है। यहाँ मेरा जवाब उसी पर हैं।

यदि आप CodeIgniter का उपयोग कर रहे हैं तो आप क्वेरी_बिल्डर क्लास में परिभाषित इनबिल्ट विधियों का उपयोग कर सकते हैं।

$ 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));
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.