PDO প্রস্তুত একক ক্যোয়ারিতে একাধিক সারি সন্নিবেশ করায়


145

আমি বর্তমানে একক কোয়েরিতে একাধিক সারি মান সন্নিবেশ করতে মাইএসকিউএলে এই ধরণের এসকিউএল ব্যবহার করছি:

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

পিডিও-তে পড়ার সময়, ব্যবহারের জন্য প্রস্তুত বিবৃতি আমাকে স্থির প্রশ্নের চেয়ে আরও ভাল সুরক্ষা দেয়।

অতএব আমি জানতে চাই যে প্রস্তুত বিবৃতি ব্যবহার করে "একটি ক্যোয়ারির সাহায্যে একাধিক সারি সন্নিবেশকরণ" তৈরি করা সম্ভব কিনা।

যদি হ্যাঁ, আমি কীভাবে এটি বাস্তবায়ন করতে পারি জানতে পারি?


$stmt->execute($data); Php.net/manual/en/… এর জন্য অনেক উত্তর দিয়ে সতর্কতা অবলম্বন করুন মূলত সমস্ত প্যারামগুলি স্ট্রিং হিসাবে বৈধ হয়ে গেছে। কোয়েরিটি তৈরি করার পরে এবং ম্যানুয়ালি bindValueবা bindParamতৃতীয়-আর্গুমেন্ট হিসাবে টাইপ করার পরে ডেটা লুপ করুন ।
মিঃমিসিজ

উত্তর:


150

PDO প্রস্তুত বিবৃতি সহ একাধিক মান সন্নিবেশ করান

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

$datafields = array('fielda', 'fieldb', ... );

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

আরও ডেটা মান বা আপনার সম্ভবত একটি লুপ রয়েছে যা ডেটা পপুলেট করে।

প্রস্তুত সন্নিবেশগুলির সাথে আপনার যে ক্ষেত্রগুলি সন্নিবেশ করা হচ্ছে সেগুলি এবং ক্ষেত্রগুলির সংখ্যাটি তৈরি করতে হবে তা জানতে হবে? আপনার পরামিতিগুলি আবদ্ধ করতে স্থানধারক।

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

এটি মূলত আমরা কীভাবে সন্নিবেশ বিবৃতিটি দেখতে চাই।

এখন, কোড:

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 সেকেন্ডের পার্থক্য ছিল।


4
একটি টাইপো, এটির উপরের ব্যাখ্যায় $ ডেটাফিল্ডগুলি উল্লেখ করেছে যদিও $ ডেটাফিল্ড q বর্গমূলে ব্যবহৃত হয়। সুতরাং কপি পেস্ট ত্রুটি হতে পারে। সংশোধন করুন। যদিও এই সমাধানের জন্য ধন্যবাদ।
pal4Live

1
এটি কিছুক্ষণ ব্যবহার করুন এবং লক্ষ্য করুন যে সেগুলিতে একক উদ্ধৃতি সহ মানগুলি যথাযথভাবে রক্ষা পায় না। ইমপ্লোশনে ডাবল কোট ব্যবহার করা আমার জন্য কবজির মতো কাজ করে: $ a [] = '("'। ইমপ্লোড (", ", $ প্রশ্ন_মার্ক)) '", এখন ())';
কিওয়ার্টজম্যান

1
অ্যারে_মার্জকে কেবল অ্যারে_পুষ ব্যবহারের চেয়ে ব্যয়বহুল মনে হয়।
K2xL

14
আপনি যখন বলেন "কেবলমাত্র 1 সেকেন্ডের পার্থক্য ছিল", আপনি কতগুলি সারি একটি ডাটা সন্নিবেশ করছিলেন? 1 সেকেন্ড প্রসঙ্গে নির্ভর করে বেশ তাৎপর্যপূর্ণ।
কেভিন ডাইস

3
অপ্টিমাইজেশন: বার বার কল placeholders()করার কোনও অর্থ নেই । লুপটির সাথে একবার এটি কল sizeof($datafields)করুন এবং ফলাফলের স্ট্রিংটিকে $question_marks[]লুপের অভ্যন্তরে যুক্ত করুন।
এভিআইডিপ্লোপার

71

মিঃ বালাগটাস হিসাবে একই উত্তর, কিছুটা পরিষ্কার ...

সাম্প্রতিক সংস্করণ মাইএসকিউএল এবং পিএইচপি PDO না সমর্থন মাল্টি সারি INSERTবিবৃতি।

এসকিউএল ওভারভিউ

এসকিউএল এমন একটি দেখতে পাবেন যা আপনি করতে চান এমন একটি 3-কলামের টেবিল ধরে নিচ্ছেন INSERT

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

ON DUPLICATE KEY UPDATEএমনকি বহু-সারি INSERT সহ প্রত্যাশিত হিসাবে কাজ করে; এটি যুক্ত করুন:

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

পিএইচপি ওভারভিউ

আপনার পিএইচপি কোডটি স্বাভাবিক $pdo->prepare($qry)এবং $stmt->execute($params)PDO কলগুলি অনুসরণ করবে ।

$paramsএর মধ্যে পাস করার জন্য সমস্ত মানের 1-মাত্রিক অ্যারে হবেINSERT

উপরের উদাহরণে এটিতে 9 টি উপাদান থাকা উচিত; PDO 3 টির প্রতিটি সেটকে মানগুলির একক সারি হিসাবে ব্যবহার করবে। (প্রতিটি 3 টি কলামের 3 সারি সন্নিবেশ করানো = 9 টি উপাদান অ্যারে।

বাস্তবায়ন

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

ধরে নেওয়া যাক:

  • $tblName - টেবিলের স্ট্রিংয়ের নামটি INSERT থেকে
  • $colNames- টেবিলের কলামের নামগুলির 1-মাত্রিক অ্যারে এই কলামের নামগুলি বৈধ মাইএসকিউএল কলাম শনাক্তকারী হতে হবে; যদি না হয় তবে তাদের ব্যাকটিক্স (escape `) দিয়ে পালাতে পারেন
  • $dataVals - মুটলি-ডাইমেনশনাল অ্যারে, যেখানে প্রতিটি উপাদান INSERT এ সারি সারিগুলির 1-d অ্যারে হয়

কোডের উদাহরণ

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

6
এটি সত্যিই খুব খারাপ যে পিডিও এটি এইভাবে পরিচালনা করে, অন্যান্য ডিবি ড্রাইভারদের মধ্যে এটি করার জন্য খুব মার্জিত উপায় রয়েছে।
জোনাথন

এটি স্থানধারকদের আরও নিখরচায় সেটআপ করে, $rowPlacesআর প্রয়োজনীয়তা তৈরি করে না:$allPlaces = implode(',', array_fill(0, count($dataVals), '('.str_pad('', (count($colNames)*2)-1, '?,').')'));
ফিল

নিখুঁত কাজ করে। আমি এই উত্তরে টেবিলের সূচকগুলির (সমন্বয়) স্বতন্ত্রতা নিশ্চিত করার প্রয়োজনীয়তাটি যুক্ত করব। ALTER টেবিল এর মতো votesএডিডি অনন্য unique_index( user, email, address);
জিউসেপে

1
অসাধারণ! বিটিডাব্লু, ব্যবহারের সময়টি array_push($dataToInsert, ...array_values($dataVals));আরও দ্রুত হবেforeach ($dataVals as $row => $data) {}
আনিস

39

এটির মূল্যের জন্য, আমি অনেকগুলি ব্যবহারকারী নির্বাচিত উত্তর যেমনটি পেয়েছে তেমন একক স্ট্রিং ক্যোয়ারী তৈরির পরিবর্তে 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 - সরাসরি এক মৃত্যুদন্ডে 10 টি সারি রাখার দুর্দান্ত ধারণা । আমি যখন জেএসএনের মতো কোনও বস্তুতে সঞ্চিত থাকি তখন কীভাবে আমি কয়েক হাজার সারি সন্নিবেশ করবো? আমার নীচের কোডগুলি স্পষ্টভাবে কাজ করে। তবে আমি কীভাবে এটি সম্পাদন করতে 10 টি সারি সন্নিবেশ করতে সামঞ্জস্য করতে পারি? `ফোরচ ($ ডেটারো হিসাবে tent জসন_কন্টেন্ট) $ $ আইডি = $ ডেটারো [আইডি]; $ তারিখ = $ দাতারো [তারিখ]; $ সার্বো3 = $ দাতারো [সারি 3]; $ সারি 4 = $ দাতারো [সারি 4]; $ সারি 5 = $ ডেটারো [সারি 5]; $ قطار6 = $ ডেটারো [সারি 6]; $ সারি 7 = $ দাতারো [সারি 7]; // এখন এক্সিকিউট করুন $ ডাটাবেইনসেট-> এক্সিকিউট (); fore // পূর্বাভাসের শেষ `
পিটার

@ জেএম 4 - ... এবং আমার দ্বিতীয় প্রশ্নটি: " bind_paramদ্বিতীয় আমদানির রুটিনে কেন কোনও বিবৃতি দেওয়া হয়নি "?
পিটার

আপনি দুবার লুপ করতে হবে না? আপনাকেও গতিশীলভাবে উত্পন্ন করতে হবে (?,?), তাই না?
NoobishPro

@ নুবিশপ্রো হ্যাঁ, আপনি উভয় তৈরি করতে / foreach জন্য একই ব্যবহার করতে পারেন।
চাজি ছাজ

34

হারবার্ট বালাগটাসের স্বীকৃত উত্তরটি যখন ডেটা অ্যারে ছোট হয় তখন ভাল কাজ করে। বৃহত্তর $ ডেটা অ্যারের সাথে অ্যারে_মেজ ফাংশনটি নিষিদ্ধভাবে ধীর হয়ে যায়। Test ডেটা অ্যারে তৈরির জন্য আমার পরীক্ষার ফাইলটিতে 28 টি কলস রয়েছে এবং এটি প্রায় 80,000 লাইন। চূড়ান্ত স্ক্রিপ্টটি সম্পূর্ণ হতে 41 সেকেন্ড সময় নিয়েছিল ।

ব্যবহার array_push () array_merge পরিবর্তে $ insert_values তৈরি করতে () একটি ফলে 100x গতি সঞ্চালনের সময় সঙ্গে 0.41s

সমস্যাযুক্ত অ্যারে_মার্জ ():

$insert_values = array();

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

অ্যারে_মার্জ () এর প্রয়োজনীয়তা অপসারণ করতে আপনি এর পরিবর্তে নিম্নলিখিত দুটি অ্যারে তৈরি করতে পারেন:

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

4
পিএইচপি 5.6 এ আপনি array_push($data, ...array_values($row))পরিবর্তে করতে পারেন $data = array_merge($data, array_values($row));। অনেক দ্রুত.
এমপেন

কেন 5.6? ডকুমেন্টেশন 5.6 সম্পর্কে কিছু বলে না, array_push()এমনকি পিএইচপি 4
তে

1
@ পিয়ারো এটি পিএইচপি 5.6+ কেবল কোড ব্যবহারের কারণে নয় array_push(), কারণ @ মার্কটি যুক্তি আনপ্যাকিং ব্যবহার করছে। ...array_values()সেখানে কল লক্ষ্য করবেন ?
mariano.iglesias

@ mariano.iglesias array_values()পিএইচপি 4- তেও উপলব্ধ argument unpacking
জুরাবওয়েব

2
@ পিয়ারো, আর্গুমেন্ট আনপ্যাকিং হ'ল এই বৈশিষ্ট্যটি পিএইচপি 5.6-এ প্রবর্তিত। এটি অ্যারে হিসাবে একাধিক যুক্তি সরবরাহ করার উপায় এখানে চেক করুন - php.net/manual/en/…
আনিস

14

দুটি সম্ভাব্য পন্থা:

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

যদি সমস্ত সারিগুলির ডেটা একক অ্যারেতে থাকে তবে আমি দ্বিতীয় সমাধানটি ব্যবহার করব।


10
পরে আপনি কি এক বিবৃতিতে সম্মিলনের পরিবর্তে পৃথক সম্পাদনকারী কলগুলি বেশ কয়েকটি (সম্ভবত হাজার হাজার) করছেন না?
জেএম 4

@ জেএম 4, আপনি কি ফোরচ $stmt->execute();লুপের বাইরে থাকার পরামর্শ দিচ্ছেন ?
বাফ্রোমকা

@ বাফ্রোমকা - হ্যাঁ আমি আছি। উপরে আমার উত্তর দেখুন। খাঁটি সন্নিবেশ বিবৃতিতে আমি যুক্তিযুক্তভাবে সামনে আসতে পারি এমন কোনও কারণ নেই যা এটি একটি একক বিবৃতি হতে পারে না। একটি কল, একটি চালানো। আসলে, ২০১২ সালের প্রথম দিকের আমার উত্তরটি আরও উন্নত হতে পারে - আমার আরও কিছু সময় পেলে আমি পরে কিছু করব। আপনি যদি সন্নিবেশ / আপডেট / সংযোজনগুলি মুছতে শুরু করেন তবে এটি অন্যরকম একটি গল্প।
জেএম 4

12

আপনি প্রস্তুত বিবৃতি ব্যবহার করার উপায়টি সহজ নয়।

প্রতি ক্যোয়ারীতে একটি সারি সন্নিবেশ করা পুরোপুরি ঠিক আছে কারণ আপনি বিভিন্ন পরামিতি সহ একাধিকবার একটি প্রস্তুত বিবৃতি কার্যকর করতে পারেন। প্রকৃতপক্ষে এটি সর্বাধিক সুবিধাগুলির মধ্যে একটি কারণ এটি আপনাকে দক্ষ, সুরক্ষিত এবং আরামদায়ক উপায়ে আপনাকে একটি বিশাল সংখ্যক সারি সন্নিবেশ করতে দেয়।

সুতরাং আপনার প্রস্তাবিত স্কিমটি কমপক্ষে একটি নির্দিষ্ট সংখ্যক সারির জন্য বাস্তবায়িত করা সম্ভবত সম্ভব, তবে এটি প্রায় নিশ্চিত যে আপনি এটি যা চান তা বাস্তবে নয়।


1
আপনি কি টেবিলের মধ্যে একাধিক সারি সন্নিবেশ করার আরও ভাল উপায়ের পরামর্শ দিতে পারেন?
ক্র্যাশট্যাচ

@ ক্র্যাশট্যাচ: এটিকে নিখুঁতভাবে করুন: প্রস্তুত বিবৃতিটি একবার সেটআপ করুন, তারপরে প্রতিটি সারিটির জন্য আবদ্ধ পরামিতিগুলির জন্য বিভিন্ন মান সহ এটি প্রয়োগ করুন। জাইকের উত্তরের এটিই দ্বিতীয় উপায়।
সেবাসগো

2
আপনি প্রস্তুত বিবৃতি জন্য যে উদ্দেশ্য উল্লেখ করেছেন তা সঠিক is তবে, মাল্টি-সন্নিবেশ ব্যবহার করা সন্নিবেশের গতি উন্নত করার জন্য অন্য কৌশল এবং এটি প্রস্তুত বিবৃতি দিয়েও ব্যবহার করা যেতে পারে। আমার অভিজ্ঞতায়, পিডিও প্রস্তুত বিবৃতি ব্যবহার করে 30 মিলিয়ন সারি ডেটা স্থানান্তরিত করার সময়, আমি দেখলাম মাল্টি-সারণি লেনদেনে 7-10 গুণ বেশি গতিযুক্ত একক সন্নিবেশকে গ্রুপবদ্ধ করা হয়েছিল।
আনিস

1
আনিসের সাথে একেবারে একমত। আমার 100k সারি রয়েছে এবং মুলি সারি সন্নিবেশ সহ একটি বিশাল গতি বৃদ্ধি পেয়েছি।
কেনেথ

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

8

একটি সংক্ষিপ্ত উত্তর: এরপরে কলামগুলি দ্বারা অর্ডার করা ডেটার অ্যারের সমতল করুন

//$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 বা ততোধিক রেকর্ড সন্নিবেশ করার সময় আপনার প্রয়োজন সমস্ত মানগুলির একটি গণনা যখন আপনাকে সন্নিবেশ করতে প্রতিটি রেকর্ডের মধ্য দিয়ে লুপ করতে হবে না।


5

এখানে আমার সহজ পদ্ধতি।

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

6
আপনি প্রস্তুত বিবৃতি ব্যবহার পয়েন্ট পরাজিত করছেন। বিকল্প প্রশ্নটির সুরক্ষার জন্য উদ্বিগ্নOn the readings on PDO, the use prepared statements should give me a better security than static queries.
YesItsMe

2
কেবল ইমেজিংয়ের যে আপনার বৈধতা নেই $workouts_id, যা $valueবেশ অনাবৃত ডেটা সহ থাকতে পারে । আপনি গ্যারান্টি দিতে পারবেন না এখনই নয় ভবিষ্যতে অন্য বিকাশকারী এই ডেটাটিকে নিরাপত্তাহীন করে তোলেন। সুতরাং আমি মনে করি পিডিও দ্বারা প্রস্তুত ক্যোয়ারীটি আরও সঠিকভাবে তৈরি করুন।
নিকিতা_খারকভ_ুয়া

3

এখানে আমি লিখেছি এমন একটি ক্লাস যা শুদ্ধ বিকল্প সহ একাধিক সন্নিবেশ লিখেছিল:

<?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;
    }
}

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

1

এটি আমি এটি করেছিলাম:

প্রথমে আপনি যে কলামের নামগুলি ব্যবহার করবেন তা সংজ্ঞায়িত করুন, বা এটি ফাঁকা রেখে দিন এবং পিডিও ধরে নেবে আপনি টেবিলের সমস্ত কলামগুলি ব্যবহার করতে চান - সেক্ষেত্রে আপনাকে সারণির মানগুলি টেবিলে প্রদর্শিত হুবহু সঠিকভাবে অবহিত করতে হবে ।

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

এখন, ধরুন আপনার কাছে ইতিমধ্যে প্রস্তুত একটি দ্বিমাত্রিক অ্যারে রয়েছে। এটি সন্ধান করুন এবং আপনার সারি মানগুলির সাথে একটি স্ট্রিং তৈরি করুন:

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

এখন, আপনি সবে যা করেছেন তা পরীক্ষা করে দেখানো হয়েছিল যে $ সারিগুলি ইতিমধ্যে সংজ্ঞায়িত করা হয়েছে কিনা, এবং না থাকলে এটি তৈরি করুন এবং সারি মান এবং প্রয়োজনীয় এসকিউএল সিনট্যাক্স সংরক্ষণ করুন যাতে এটি একটি বৈধ বিবৃতি হবে। নোট করুন যে স্ট্রিংগুলি ডাবল কোট এবং একক উদ্ধৃতিগুলির মধ্যে থাকা উচিত, তাই এগুলি অবিলম্বে স্বীকৃত হবে।

এটি করার জন্য বাকি সমস্তটি হ'ল বিবৃতি প্রস্তুত এবং কার্যকর করা, যেমন:

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

এখন পর্যন্ত 2000 টি সারি দিয়ে পরীক্ষা করা হয়েছে এবং মৃত্যুদন্ড কার্যকর করার সময়টি বিরল। আরও কিছু পরীক্ষা চালাবে এবং আমার আরও কিছু অবদান রাখার ক্ষেত্রে এখানে ফিরে আসব।

শুভেচ্ছা।


1

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

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


1

যদিও একটি পুরানো প্রশ্ন সমস্ত অবদান আমাকে অনেক সহায়তা করেছিল তাই এখানে আমার সমাধানটি দেওয়া হয়েছে, যা আমার নিজের DbContextশ্রেণীর মধ্যে কাজ করে । $rowsপরামিতি কেবল সারি বা মডেল প্রতিনিধিত্বমূলক মিশুক অ্যারে একটি অ্যারে: field name => insert value

অ্যারে হিসাবে মডেল ডেটা পাস করার সময় আপনি যদি এমন প্যাটার্ন ব্যবহার করেন যা মডেলগুলি এটি সুন্দরভাবে ফিট করে ToRowArrayতবে মডেল ক্লাসের মধ্যে একটি পদ্ধতি থেকে বলুন ।

দ্রষ্টব্য : এটি বলার অপেক্ষা রাখে না তবে এই পদ্ধতিতে পাস হওয়া আর্গুমেন্টগুলি কখনই ব্যবহারকারীর সামনে প্রকাশ করা বা সন্নিবেশিত মানগুলি বাদ দিয়ে মান সন্নিবেশিত মান বাদে কোনও ব্যবহারকারীর ইনপুট নির্ভর করতে দেয় না which $tableNameযুক্তি এবং কলাম নাম কলিং যুক্তি দ্বারা সংজ্ঞায়িত করা উচিত; উদাহরণস্বরূপ কোনও Userব্যবহারকারীর টেবিলের সাথে একটি মডেল ম্যাপ করা যেতে পারে, যার কলামের তালিকাটি মডেলের সদস্য ক্ষেত্রগুলিতে ম্যাপ করা হয়েছে।

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

কোনও লেনদেন থেকে মুক্তি পান, কেননা এটি কোনও একক প্রশ্নের জন্য কোনওটি ব্যবহার করার কোনও মানে হয় না। এবং যথারীতি, এই কোডটি এসকিউএল ইঞ্জেকশন বা কোয়েরি ত্রুটির পক্ষে ঝুঁকির মধ্যে রয়েছে।
আপনার কমন সেন্স

এই ক্ষেত্রে লেনদেনের অপ্রয়োজনীয় ব্যবহার সম্পর্কে আপনি ঠিক বলেছেন তবে এসকিউএল ইঞ্জেকশনের ক্ষেত্রে এটি কীভাবে ঝুঁকিপূর্ণ তা আমি দেখতে পাচ্ছি না। এটি প্যারামিটারাইজড তাই আমি ধরেই নিতে পারি যে আপনি ধরে $tableNameনিচ্ছেন যে এটি ব্যবহারকারীর সামনে প্রকাশিত হয়েছে, যা এটি নয়, এটি ডালে রয়েছে। আপনি কি আপনার দাবির প্রসারিত করতে পারবেন? শুধু জিনিস বলতে এটি সহায়ক নয়।
লি

ঠিক আছে, এটি কেবল একটি টেবিলের নাম নয় তবে যাইহোক: আপনি কীভাবে জানবেন যে এটি আপনি প্রকাশ করেছেন বা আপনার এখানে পোস্ট করা কোডটি ব্যবহার করবে এমন কেউ
আপনার সাধারণ জ্ঞান

সুতরাং কোডের প্রতিটি সম্ভাব্য ব্যবহারের বা আর্গুমেন্টের জন্য প্রতিটি উত্সের বাহ্যরেখা তৈরি করা কোনও পোস্টারের দায়িত্ব? আমার কাছে মানুষের উচ্চ প্রত্যাশা থাকতে পারে। আমি যদি কোনও নোট যুক্ত করে ব্যবহারকারীর অ্যাক্সেস না করার অনুমতি দেয় তবে কী আপনাকে আনন্দিত করবে $tableName?
লি

নির্ভরযোগ্য কোড পোস্ট করা কোনও পোস্টারের দায়িত্ব, যদি তাদের উদ্দেশ্য কাউকে সাহায্য করা হয়, কেবল প্রদর্শন করা নয়।
আপনার কমন সেন্স

1

এই সমস্যাটির জন্য এখানে আরও একটি (স্লিম) সমাধান রয়েছে:

প্রথমে আপনাকে উত্স অ্যারের ডেটা গণনা করতে হবে (এখানে: $ aData) গণনা সহ) ()। তারপরে আপনি অ্যারে_ফিল () ব্যবহার করুন এবং উত্স অ্যারেতে যতগুলি এনট্রি রয়েছে তার সাথে একটি নতুন অ্যারে তৈরি করুন, প্রতিটি "(?,?)" মান সহ (স্থানধারকের সংখ্যা আপনি যে ক্ষেত্রগুলি ব্যবহার করছেন তার উপর নির্ভর করে; এখানে: 2)। তারপরে উত্পন্ন অ্যারেটি বিস্তৃত হওয়া প্রয়োজন এবং আঠালো হিসাবে একটি কমা ব্যবহার করা হবে। পূর্বাঞ্চ লুপের মধ্যে, আপনার ব্যবহৃত স্থানধারীর সংখ্যার (স্থানধারকদের সংখ্যা * বর্তমান অ্যারে সূচক + 1) সম্পর্কিত আপনাকে অন্য একটি সূচক তৈরি করতে হবে। প্রতিটি প্রতিবন্ধিত মানের পরে আপনাকে উত্পন্ন সূচকটিতে 1 যুক্ত করতে হবে।

$do = $db->prepare("INSERT INTO table (id, name) VALUES ".implode(',', array_fill(0, count($aData), '(?,?)')));

foreach($aData as $iIndex => $aValues){
 $iRealIndex = 2 * $iIndex + 1;
 $do->bindValue($iRealIndex, $aValues['id'], PDO::PARAM_INT);
 $iRealIndex = $iRealIndex + 1;
 $do->bindValue($iRealIndex, $aValues['name'], PDO::PARAM_STR);
}

$do->execute();

0

আপনি এই ফাংশনটির সাথে একক ক্যোয়ারিতে একাধিক সারি সন্নিবেশ করতে পারেন:

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

$ সারি একটি হল অ্যারের মূল্যবোধের বিন্যাসের। আপনার ক্ষেত্রে আপনি সাথে ফাংশন কল করবে

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

একক ক্যোয়ারী সহ একাধিক সারি সন্নিবেশ করানোর সময় আপনি প্রস্তুত বিবৃতিগুলি ব্যবহার করে এর সুবিধা রয়েছে । সিকিউরিটি!


0

এখানে আমার সমাধান: https://github.com/sasha-ch/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);

বুগেরপোর্টগুলি স্বাগত।


২.৪ পর্যন্ত আপনি github.com/auraphp/Aura.SqlQuery/tree/… এর সাথে একাধিক সন্নিবেশ তৈরি করতে এবং এক্সটেন্ডেডপডো ব্যবহার করতে পারেন :) কার্যকর করতে :)
হরি কেটি

0

খালি টেবিলের মধ্যে সমস্ত জার্মান পোস্টকোড toোকানোর জন্য আমার আসল বিশ্বের উদাহরণ (পরে শহরের নাম যুক্ত করতে):

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

ক্যারি স্ট্রিং কনস্ট্রাক্টরগুলির জন্য আমি গর্বিত কারণ তারা অ্যারে_মিটারের মতো ভারী অ্যারে-ফাংশন ছাড়াই কাজ করে। বিশেষত vsp پرنf () একটি ভাল সন্ধান ছিল।

শেষ পর্যন্ত আমাকে 2x যোগ করার দরকার ছিল () স্মৃতির সীমাটি ছাড়িয়ে যাওয়ার জন্য। এটি আপনার মেমোরি সীমাটির উপর নির্ভর করে তবে সমস্যাগুলি এড়ানোর জন্য এটির একটি সাধারণ সাধারণ সমাধান (এবং 10 অনুসন্ধান থাকা এখনও 10.000 এর চেয়ে অনেক ভাল)।


0

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

}
?>

স্ট্যাকওভারফ্লোতে স্বাগতম। শুধু কোড নয়, আপনার সমস্যাটি পোস্ট করুন এবং ব্যাখ্যা করুন।
প্রকাশ পলনতি

মূলত। এটি কেবল স্বীকৃত উত্তরে প্রদত্ত
আপনার সাধারণ সেন্স

0

আমারও একই সমস্যা ছিল এবং আমি নিজের পক্ষে এটিই সম্পাদন করি এবং আমি এটির জন্য নিজের জন্য একটি ফাংশন তৈরি করেছি (এবং যদি এটি আপনাকে সহায়তা করে তবে আপনি এটি ব্যবহার করতে পারেন)।

উদাহরণ:

অন্তর্ভুক্ত দেশগুলিতে (দেশ, শহর) ভ্যালু (জার্মানি, বার্লিন), (ফ্রান্স, প্যারিস);

$arr1 = Array("Germany", "Berlin");
$arr2 = Array("France", "France");

insertMultipleData("countries", Array($arr1, $arr2));


// Inserting multiple data to the Database.
public function insertMultipleData($table, $multi_params){
    try{
        $db = $this->connect();

        $beforeParams = "";
        $paramsStr = "";
        $valuesStr = "";

        for ($i=0; $i < count($multi_params); $i++) { 

            foreach ($multi_params[$i] as $j => $value) {                   

                if ($i == 0) {
                    $beforeParams .=  " " . $j . ",";
                }

                $paramsStr .= " :"  . $j . "_" . $i .",";                                       
            }

            $paramsStr = substr_replace($paramsStr, "", -1);
            $valuesStr .=  "(" . $paramsStr . "),"; 
            $paramsStr = "";
        }


        $beforeParams = substr_replace($beforeParams, "", -1);
        $valuesStr = substr_replace($valuesStr, "", -1);


        $sql = "INSERT INTO " . $table . " (" . $beforeParams . ") VALUES " . $valuesStr . ";";

        $stmt = $db->prepare($sql);


        for ($i=0; $i < count($multi_params); $i++) { 
            foreach ($multi_params[$i] as $j => &$value) {
                $stmt->bindParam(":" . $j . "_" . $i, $value);                                      
            }
        }

        $this->close($db);
        $stmt->execute();                       

        return true;

    }catch(PDOException $e){            
        return false;
    }

    return false;
}

// Making connection to the Database 
    public function connect(){
        $host = Constants::DB_HOST;
        $dbname = Constants::DB_NAME;
        $user = Constants::DB_USER;
        $pass = Constants::DB_PASS;

        $mysql_connect_str = 'mysql:host='. $host . ';dbname=' .$dbname;

        $dbConnection = new PDO($mysql_connect_str, $user, $pass);
        $dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

        return $dbConnection;
    }

    // Closing the connection
    public function close($db){
        $db = null;
    }

যদি ultiোকান মাল্টিপলডেটা ($ টেবিল, $ মাল্টি_প্যারামস) সত্য দেয় , আপনার ডেটা আপনার ডাটাবেসে inোকানো হয়েছে।


0

আমার পরীক্ষার উপর ভিত্তি করে আমি জানতে পেরেছি যে একক লেনদেনে একাধিক মান সারি সহ মাইএসকিএল সন্নিবেশ বিবৃতিটি দ্রুততম।

তবে, ডেটা যদি খুব বেশি হয় তবে মাইএসকিএল এর max_allowed_packetসেটিং একাধিক মান সারি সহ একক লেনদেন সন্নিবেশকে সীমাবদ্ধ করতে পারে। অতএব, যখন mysql এর max_allowed_packetআকারের চেয়ে বেশি ডেটা থাকে তখন নিম্নলিখিত ফাংশনগুলি ব্যর্থ হয় :

  1. singleTransactionInsertWithRollback
  2. singleTransactionInsertWithPlaceholders
  3. singleTransactionInsert

সর্বাধিক সফল তথ্য সন্নিবেশ করানোর ক্ষেত্রে সবচেয়ে transactionSpeedসফলটি হ'ল পদ্ধতি, তবে এটি উল্লিখিত পদ্ধতিগুলির চেয়ে বেশি সময় ব্যয় করে। সুতরাং, এই সমস্যাটি পরিচালনা করতে আপনি নিজের তথ্যগুলিকে ছোট অংশগুলিতে বিভক্ত করতে পারেন এবং একক লেনদেনকে একাধিকবার কল করতে পারেন বা transactionSpeedপদ্ধতিটি ব্যবহার করে কার্যকর করার গতি ছেড়ে দিতে পারেন ।

এখানে আমার গবেষণা

<?php

class SpeedTestClass
{
    private $data;

    private $pdo;

    public function __construct()
    {
        $this->data = [];
        $this->pdo = new \PDO('mysql:dbname=test_data', 'admin', 'admin');
        if (!$this->pdo) {
            die('Failed to connect to database');
        }
    }

    public function createData()
    {
        $prefix = 'test';
        $postfix = 'unicourt.com';
        $salutations = ['Mr.', 'Ms.', 'Dr.', 'Mrs.'];

        $csv[] = ['Salutation', 'First Name', 'Last Name', 'Email Address'];
        for ($i = 0; $i < 100000; ++$i) {
            $csv[] = [
                $salutations[$i % \count($salutations)],
                $prefix.$i,
                $prefix.$i,
                $prefix.$i.'@'.$postfix,
            ];
        }

        $this->data = $csv;
    }

    public function truncateTable()
    {
        $this->pdo->query('TRUNCATE TABLE `name`');
    }

    public function transactionSpeed()
    {
        $timer1 = microtime(true);
        $this->pdo->beginTransaction();
        $sql = 'INSERT INTO `name` (`first_name`, `last_name`) VALUES (:first_name, :last_name)';
        $sth = $this->pdo->prepare($sql);

        foreach (\array_slice($this->data, 1) as $values) {
            $sth->execute([
                ':first_name' => $values[1],
                ':last_name' => $values[2],
            ]);
        }

        // $timer2 = microtime(true);
        // echo 'Prepare Time: '.($timer2 - $timer1).PHP_EOL;
        // $timer3 = microtime(true);

        if (!$this->pdo->commit()) {
            echo "Commit failed\n";
        }
        $timer4 = microtime(true);
        // echo 'Commit Time: '.($timer4 - $timer3).PHP_EOL;

        return $timer4 - $timer1;
    }

    public function autoCommitSpeed()
    {
        $timer1 = microtime(true);
        $sql = 'INSERT INTO `name` (`first_name`, `last_name`) VALUES (:first_name, :last_name)';
        $sth = $this->pdo->prepare($sql);
        foreach (\array_slice($this->data, 1) as $values) {
            $sth->execute([
                ':first_name' => $values[1],
                ':last_name' => $values[2],
            ]);
        }
        $timer2 = microtime(true);

        return $timer2 - $timer1;
    }

    public function noBindAutoCommitSpeed()
    {
        $timer1 = microtime(true);

        foreach (\array_slice($this->data, 1) as $values) {
            $sth = $this->pdo->prepare("INSERT INTO `name` (`first_name`, `last_name`) VALUES ('{$values[1]}', '{$values[2]}')");
            $sth->execute();
        }
        $timer2 = microtime(true);

        return $timer2 - $timer1;
    }

    public function singleTransactionInsert()
    {
        $timer1 = microtime(true);
        foreach (\array_slice($this->data, 1) as $values) {
            $arr[] = "('{$values[1]}', '{$values[2]}')";
        }
        $sth = $this->pdo->prepare('INSERT INTO `name` (`first_name`, `last_name`) VALUES '.implode(', ', $arr));
        $sth->execute();
        $timer2 = microtime(true);

        return $timer2 - $timer1;
    }

    public function singleTransactionInsertWithPlaceholders()
    {
        $placeholders = [];
        $timer1 = microtime(true);
        $sql = 'INSERT INTO `name` (`first_name`, `last_name`) VALUES ';
        foreach (\array_slice($this->data, 1) as $values) {
            $placeholders[] = '(?, ?)';
            $arr[] = $values[1];
            $arr[] = $values[2];
        }
        $sql .= implode(', ', $placeholders);
        $sth = $this->pdo->prepare($sql);
        $sth->execute($arr);
        $timer2 = microtime(true);

        return $timer2 - $timer1;
    }

    public function singleTransactionInsertWithRollback()
    {
        $placeholders = [];
        $timer1 = microtime(true);
        $sql = 'INSERT INTO `name` (`first_name`, `last_name`) VALUES ';
        foreach (\array_slice($this->data, 1) as $values) {
            $placeholders[] = '(?, ?)';
            $arr[] = $values[1];
            $arr[] = $values[2];
        }
        $sql .= implode(', ', $placeholders);
        $this->pdo->beginTransaction();
        $sth = $this->pdo->prepare($sql);
        $sth->execute($arr);
        $this->pdo->commit();
        $timer2 = microtime(true);

        return $timer2 - $timer1;
    }
}

$s = new SpeedTestClass();
$s->createData();
$s->truncateTable();
echo "Time Spent for singleTransactionInsertWithRollback: {$s->singleTransactionInsertWithRollback()}".PHP_EOL;
$s->truncateTable();
echo "Time Spent for single Transaction Insert: {$s->singleTransactionInsert()}".PHP_EOL;
$s->truncateTable();
echo "Time Spent for single Transaction Insert With Placeholders: {$s->singleTransactionInsertWithPlaceholders()}".PHP_EOL;
$s->truncateTable();
echo "Time Spent for transaction: {$s->transactionSpeed()}".PHP_EOL;
$s->truncateTable();
echo "Time Spent for AutoCommit: {$s->noBindAutoCommitSpeed()}".PHP_EOL;
$s->truncateTable();
echo "Time Spent for autocommit with bind: {$s->autoCommitSpeed()}".PHP_EOL;
$s->truncateTable();

মাত্র দুটি কলামযুক্ত একটি টেবিলের জন্য 100,000 এন্ট্রিগুলির ফলাফল নীচে রয়েছে

$ php data.php
Time Spent for singleTransactionInsertWithRollback: 0.75147604942322
Time Spent for single Transaction Insert: 0.67445182800293
Time Spent for single Transaction Insert With Placeholders: 0.71131205558777
Time Spent for transaction: 8.0056409835815
Time Spent for AutoCommit: 35.4979159832
Time Spent for autocommit with bind: 33.303519010544

0

এটি আমার পক্ষে কাজ করেছে

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

0

এরকম কিছু সম্পর্কে:

        if(count($types_of_values)>0){
         $uid = 1;
         $x = 0;
         $sql = "";
         $values = array();
          foreach($types_of_values as $k=>$v){
            $sql .= "(:id_$k,:kind_of_val_$k), ";
            $values[":id_$k"] = $uid;
            $values[":kind_of_val_$k"] = $v;
          }
         $sql = substr($sql,0,-2);
         $query = "INSERT INTO table (id,value_type) VALUES $sql";
         $res = $this->db->prepare($query);
         $res->execute($values);            
        }

এর পিছনে ধারণাটি হ'ল আপনার অ্যারে মানগুলি সাইকেল চালানো, আপনার প্রস্তুত বিবৃতি স্থানধারীদের জন্য প্রতিটি লুপে "আইডি নম্বর" যুক্ত করার সাথে সাথে একই সময়ে, আপনি বাধ্যতামূলক পরামিতিগুলির জন্য আপনার অ্যারেতে মানগুলি যুক্ত করেন। আপনি যদি অ্যারে থেকে "কী" সূচকটি ব্যবহার করতে পছন্দ না করেন তবে আপনি লুপের মধ্যে $ i = 0 এবং $ i ++ যুক্ত করতে পারেন। হয় এই উদাহরণে কাজ করে, আপনার কাছে নামযুক্ত কীগুলি সহ মিশ্রিত অ্যারে থাকলেও কীগুলি অনন্য ছিল সরবরাহ করার জন্য এটি কাজ করবে। অল্প কাজ করে নেস্টেড অ্যারেগুলির জন্য এটিও ঠিক থাকবে ..

** দ্রষ্টব্য যে সাবস্ট্রটারটি space বর্গক্ষেত্রের ভেরিয়েবলগুলি সর্বশেষ স্থান এবং কমাতে বিভক্ত করে, যদি আপনার কাছে স্থান না থাকে তবে আপনাকে এটি -2 এর পরিবর্তে -1 এ পরিবর্তন করতে হবে।


-1

প্রস্তুত ক্যোয়ারী তৈরির জন্য এখানে প্রদত্ত বেশিরভাগ সমাধানগুলি আরও জটিল যা তাদের হওয়া দরকার। পিএইচপি'র বিল্ট ফাংশনগুলি ব্যবহার করে আপনি সহজেই উল্লেখযোগ্য ওভারহেড ছাড়াই এসকিউএল স্টেটমেন্টটি তৈরি করতে পারেন।

প্রদত্ত $records, রেকর্ডগুলির একটি অ্যারে যেখানে প্রতিটি রেকর্ড নিজেই একটি সূচকযুক্ত অ্যারে (আকারে field => value) হয়, নিম্নলিখিত ফাংশনটি একটি একক প্রস্তুত বিবৃতি ব্যবহার $tableকরে একটি পিডিও সংযোগে প্রদত্ত টেবিলের মধ্যে রেকর্ডগুলি সন্নিবেশ করবে $connection। দ্রষ্টব্য যে কলটিতে কলটি আনপ্যাকিংয়ের কারণে এটি একটি PHP 5.6+ সমাধান array_push:

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

1
এই কোডটি এসকিউএল ইনজেকশনের পক্ষে ঝুঁকির কারণে কখনও ব্যবহার করা উচিত নয়
আপনার প্রচলিত সংবেদন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.