একাধিক প্রশ্নের জন্য PDO সমর্থন (PDO_MYSQL, PDO_MYSQLND)


102

আমি জানি যে PDO এক বিবৃতিতে কার্যকর হওয়া একাধিক প্রশ্নের সমর্থন করে না। আমি গুগল করছি এবং PDO_MYSQL এবং PDO_MYSQLND সম্পর্কে কথা বলার কয়েকটি পোস্ট পেয়েছি।

PDO_MySQL অন্যান্য প্রচলিত মাইএসকিউএল অ্যাপ্লিকেশনগুলির চেয়ে একটি বিপজ্জনক অ্যাপ্লিকেশন। Ditionতিহ্যবাহী মাইএসকিউএল কেবল একটি একক এসকিউএল কোয়েরিকে অনুমতি দেয়। PDO_MySQL এ এরকম কোনও সীমাবদ্ধতা নেই তবে আপনি একাধিক প্রশ্নের সাথে ইনজেকশনের ঝুঁকি নিয়েছেন।

থেকে: পিডিও এবং জেন্ডার ফ্রেমওয়ার্ক ব্যবহার করে এসকিউএল ইনজেকশনের বিরুদ্ধে সুরক্ষা (জুন ২০১০; জুলিয়ান দ্বারা)

দেখে মনে হচ্ছে PDO_MYSQL এবং PDO_MYSQLND একাধিক প্রশ্নের জন্য সহায়তা সরবরাহ করে তবে আমি সেগুলি সম্পর্কে আরও তথ্য খুঁজে পাচ্ছি না। এই প্রকল্পগুলি বন্ধ ছিল? PDO ব্যবহার করে একাধিক অনুসন্ধান চালানোর এখন কোনও উপায় আছে কি?


4
এসকিউএল লেনদেন ব্যবহার করুন।
তেরেখো

আপনি কেন একাধিক প্রশ্ন ব্যবহার করতে চান? তাদের লেনদেন হয় না, আপনি একে একে চালিয়ে যাবেন ঠিক তেমনই। আইএমএইচও কোনও উপকারিতা নয়, কেবল কনস। এসকিউআইএনজিকেশনের ক্ষেত্রে আপনি আক্রমণকারীকে যা খুশি করতে অনুমতি দিন।
ম্লেকো

এটি এখন ২০২০, এবং পিডিও এটি সমর্থন করে - নীচে আমার উত্তরটি দেখুন।
অ্যান্ডিস

উত্তর:


141

আমি জানি, পিএইচপি 5.3 এ PDO_MYSQLNDপ্রতিস্থাপিত PDO_MYSQL। বিভ্রান্তিকর অংশটি এখনও সেই নাম PDO_MYSQL। সুতরাং এখন এনডি মাইএসকিউএল + পিডিওর জন্য ডিফল্ট ড্রাইভার।

সামগ্রিকভাবে, একবারে আপনার একাধিক প্রশ্নগুলি কার্যকর করতে:

  • পিএইচপি 5.3+
  • mysqlnd
  • অনুকরণ করা বিবৃতি। নিশ্চিত করুন (ডিফল্ট) PDO::ATTR_EMULATE_PREPARESএ সেট করা আছে 1। বিকল্পভাবে আপনি প্রস্তুত বিবৃতি ব্যবহার এবং $pdo->execসরাসরি ব্যবহার এড়াতে পারেন ।

এক্সিকিউটিভ ব্যবহার করা হচ্ছে

$db = new PDO("mysql:host=localhost;dbname=test", 'root', '');

// works regardless of statements emulation
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0);

$sql = "
DELETE FROM car; 
INSERT INTO car(name, type) VALUES ('car1', 'coupe'); 
INSERT INTO car(name, type) VALUES ('car2', 'coupe');
";

$db->exec($sql);

বিবৃতি ব্যবহার করে

$db = new PDO("mysql:host=localhost;dbname=test", 'root', '');

// works not with the following set to 0. You can comment this line as 1 is default
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1);

$sql = "
DELETE FROM car; 
INSERT INTO car(name, type) VALUES ('car1', 'coupe'); 
INSERT INTO car(name, type) VALUES ('car2', 'coupe');
";

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

একটি নোট:

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


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

9
এই উত্তরের কোডটি খারাপ, এবং কিছু খুব ক্ষতিকারক অনুশীলনগুলিকে প্রচার করে (এসএমএল ইনজেকশন দুর্বলতার জন্য কোড প্রস্তুত করে এমন বিবৃতি প্রস্তুতের জন্য অনুকরণের ব্যবহার )। এটা ব্যবহার করোনা.
tereško

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

3
প্রকৃতপক্ষে, কেবলমাত্র একজন যে আবেগকেই নয় তবে কিছু যুক্তি সরবরাহ করতে পেরেছিলেন, তিনি ছিলেন আর্কমেক্সেল। তবে তিনি যে লিঙ্কগুলি এনেছিলেন তা বেশ অপ্রাসঙ্গিক। প্রথমটি একেবারেই প্রয়োগযোগ্য নয় কারণ এটি স্পষ্টতই বলেছে "PDO সর্বদা এই বাগ থেকে প্রতিরোধক থাকে।" যদিও দ্বিতীয়টি যথাযথ এনকোডিং সেট করে কেবল সমাধানযোগ্য। সুতরাং, এটি একটি নোটের দাবিদার, সতর্কতা নয় এবং কম আবেদনকারী।
আপনার সাধারণ সংবেদন

6
যে কোনও মাইগ্রেশন সরঞ্জাম লিখছেন যা এসকিউএল ব্যবহার করে যা কেবলমাত্র আমাদের বিকাশকারীরা লিখেছেন (যেমন এসকিউএল ইনজেকশন কোনও সমস্যা নয়) এর সাথে কথা বলার ফলে এটি আমাকে ব্যাপকভাবে সহায়তা করেছে এবং এই কোডটি ক্ষতিকারক বলে চিহ্নিত হওয়া কোনও মন্তব্য পুরোপুরি বুঝতে পারে না এর ব্যবহারের জন্য প্রসঙ্গ
লুক

17

এটির সাথে আড্ডা দেওয়ার অর্ধেক দিন পরে, আবিষ্কার করলেন যে পিডিওতে একটি বাগ রয়েছে যেখানে ...

-

//This would run as expected:
$pdo->exec("valid-stmt1; valid-stmt2;");

-

//This would error out, as expected:
$pdo->exec("non-sense; valid-stmt1;");

-

//Here is the bug:
$pdo->exec("valid-stmt1; non-sense; valid-stmt3;");

এটি কার্যকর করে "valid-stmt1;", থামিয়ে দেয় "non-sense;"এবং কখনও ত্রুটি ছুঁড়ে না ফেলে। চালাবে না "valid-stmt3;", সত্য ফিরে আসবে এবং মিথ্যা বলবে যে সবকিছুই ভাল চলছে ।

আমি এটির ত্রুটি থেকে বেরিয়ে আসার আশা করব "non-sense;"তবে তা হয় না।

এই তথ্যটি আমি এখানে কোথায় পেয়েছি: অবৈধ PDO ক্যোয়ারী কোনও ত্রুটি ফেরায় না

এখানে বাগটি রয়েছে: https://bugs.php.net/bug.php?id=61613


সুতরাং, আমি মাইসকিলি দিয়ে এটি করার চেষ্টা করেছি এবং এটি কীভাবে কাজ করে সে সম্পর্কে সত্যই কোনও দৃ answer় উত্তর আমি পাইনি তাই আমি ভেবেছিলাম যে যারা এটি ব্যবহার করতে চান তাদের জন্য আমি কেবল এটি এখানে রেখে চলেছি ..

try{
    // db connection
    $mysqli = new mysqli("host", "user" , "password", "database");
    if($mysqli->connect_errno){
        throw new Exception("Connection Failed: [".$mysqli->connect_errno. "] : ".$mysqli->connect_error );
        exit();
    }

    // read file.
    // This file has multiple sql statements.
    $file_sql = file_get_contents("filename.sql");

    if($file_sql == "null" || empty($file_sql) || strlen($file_sql) <= 0){
        throw new Exception("File is empty. I wont run it..");
    }

    //run the sql file contents through the mysqli's multi_query function.
    // here is where it gets complicated...
    // if the first query has errors, here is where you get it.
    $sqlFileResult = $mysqli->multi_query($file_sql);
    // this returns false only if there are errros on first sql statement, it doesn't care about the rest of the sql statements.

    $sqlCount = 1;
    if( $sqlFileResult == false ){
        throw new Exception("File: '".$fullpath."' , Query#[".$sqlCount."], [".$mysqli->errno."]: '".$mysqli->error."' }");
    }

    // so handle the errors on the subsequent statements like this.
    // while I have more results. This will start from the second sql statement. The first statement errors are thrown above on the $mysqli->multi_query("SQL"); line
    while($mysqli->more_results()){
        $sqlCount++;
        // load the next result set into mysqli's active buffer. if this fails the $mysqli->error, $mysqli->errno will have appropriate error info.
        if($mysqli->next_result() == false){
            throw new Exception("File: '".$fullpath."' , Query#[".$sqlCount."], Error No: [".$mysqli->errno."]: '".$mysqli->error."' }");
        }
    }
}
catch(Exception $e){
    echo $e->getMessage(). " <pre>".$e->getTraceAsString()."</pre>";
}

আপনি যদি কেবলমাত্র $pdo->exec("valid-stmt1; non-sense; valid-stmt3;");পূর্ববর্তী দুটি নির্বাহী ব্যতীত চালনা করেন তা কি কাজ করে ? আমি এটি মাঝখানে ত্রুটি ছুঁড়ে ফেলতে পারি, তবে সফল মৃত্যুদণ্ড কার্যকর করার পরে কার্যকর করা হয় না
জেফ পেকেট

না, না। এটি PDO সহ বাগ।
সাঁই ফানিন্দার রেড্ডি J

1
আমার খারাপ, এই 3 $pdo->exec("")জন একে অপরের থেকে স্বাধীন। সমস্যাটি উত্থাপনের জন্য তাদের ক্রমানুসারে থাকতে হবে না তা বোঝাতে আমি এখন এগুলিকে আলাদা করেছিলাম। এই 3 টি এক নির্বাহী বিবৃতিতে একাধিক ক্যোয়ারী চালনার 3 কনফিগারেশন।
সাঁই ফানিন্দার রেড্ডি জে

মজাদার. আপনি আমার পোস্ট করা প্রশ্ন দেখার সুযোগ পেয়েছেন? আমি আশ্চর্য হয়েছি যে এটি আংশিকভাবে প্যাচ করা হয়েছে কারণ আমি execপৃষ্ঠাতে কেবলমাত্র যদি ত্রুটিটি ফেলে দিতে পারি তবে আমি যদি execসেগুলির মধ্যে একাধিক এসকিউএল বিবৃতি দিয়ে একাধিক চালিত করি তবে আমি এখানে একই বাগটি পুনরুত্পাদন করব। তবে এটি যদি কেবল execপৃষ্ঠায় থাকে তবে আমি এটি পুনরুত্পাদন করতে পারি না।
জেফ পেকেট

যে এক কি execআপনার পৃষ্ঠায় একাধিক বিবৃতি আছে?
সাই ফানিন্দার রেড্ডি

3

একটি দ্রুত এবং নোংরা পদ্ধতির:

function exec_sql_from_file($path, PDO $pdo) {
    if (! preg_match_all("/('(\\\\.|.)*?'|[^;])+/s", file_get_contents($path), $m))
        return;

    foreach ($m[0] as $sql) {
        if (strlen(trim($sql)))
            $pdo->exec($sql);
    }
}

যুক্তিসঙ্গত এসকিউএল স্টেটমেন্টের শেষ পয়েন্টগুলিতে বিভক্ত হয়। চেক করার কোনও ত্রুটি নেই, কোনও ইঞ্জেকশন সুরক্ষা নেই। এটি ব্যবহারের আগে আপনার ব্যবহারটি বুঝতে হবে। ব্যক্তিগতভাবে, আমি এটি ইন্টিগ্রেশন পরীক্ষার জন্য কাঁচা মাইগ্রেশন ফাইলগুলি বীজ করার জন্য ব্যবহার করি।


1
এটি ব্যর্থ হয় যদি আপনার এসকিউএল ফাইলটিতে কোনও মাইএসকিএল বিল্টিন কমান্ড থাকে ... এটি যদি আপনার এসকিউএল ফাইলটি বড় হয় তবে এটি আপনার পিএইচপি মেমরির সীমাটিও ফুটিয়ে তুলবে ... ;আপনার এসকিউএল পদ্ধতিতে বা ট্রিগার সংজ্ঞা থাকলে বিরতিতে বিভক্ত হওয়া ... প্রচুর কারণ ভাল না কেন।
বিল কারভিন

1

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

function arrayOfQuerys($arrayQuery)
{
    $mx = true;
    $conn->beginTransaction();
    try {
        foreach ($arrayQuery AS $item) {
            $stmt = $conn->prepare($item["query"]);
            $stmt->execute($item["params"]);
            $result = $stmt->rowCount();
            if($result == 0)
                $mx = false;
         }
         if($mx == true)
             $conn->commit();
         else
             $conn->rollBack();
    } catch (Exception $e) {
        $conn->rollBack();
        echo "Failed: " . $e->getMessage();
    }
    return $mx;
}

ব্যবহারের জন্য (উদাহরণস্বরূপ):

 $arrayQuery = Array(
    Array(
        "query" => "UPDATE test SET title = ? WHERE test.id = ?",
        "params" => Array("aa1", 1)
    ),
    Array(
        "query" => "UPDATE test SET title = ? WHERE test.id = ?",
        "params" => Array("bb1", 2)
    )
);
arrayOfQuerys($arrayQuery);

এবং আমার সংযোগ:

    try {
        $options = array(
            //For updates where newvalue = oldvalue PDOStatement::rowCount()   returns zero. You can use this:
            PDO::MYSQL_ATTR_FOUND_ROWS => true
        );
        $conn = new PDO("mysql:host=$servername;dbname=$database", $username, $password, $options);
        $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    } catch (PDOException $e) {
        echo "Error connecting to SQL Server: " . $e->getMessage();
    }

দ্রষ্টব্য:
এই সমাধানটি আপনাকে একসাথে একাধিক বিবৃতি চালাতে সহায়তা করে,
যদি কোনও ভুল বিবৃতি ঘটে থাকে তবে এটি অন্য কোনও বিবৃতি কার্যকর করে না


0

নিম্নলিখিত কোড চেষ্টা করা হয়েছে

 $db = new PDO("mysql:host={$dbhost};dbname={$dbname};charset=utf8", $dbuser, $dbpass, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));

তারপর

 try {
 $db->query('SET NAMES gbk');
 $stmt = $db->prepare('SELECT * FROM 2_1_paidused WHERE NumberRenamed = ? LIMIT 1');
 $stmt->execute(array("\xbf\x27 OR 1=1 /*"));
 }
 catch (PDOException $e){
 echo "DataBase Errorz: " .$e->getMessage() .'<br>';
 }
 catch (Exception $e) {
 echo "General Errorz: ".$e->getMessage() .'<br>';
 }

এবং পেয়েছিলাম

DataBase Errorz: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '/*' LIMIT 1' at line 1

$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);পরে যুক্ত হলে$db = ...

তারপরে ফাঁকা পাতা পেল

পরিবর্তে যদি SELECTচেষ্টা করা হয় DELETE, তবে উভয় ক্ষেত্রেই ত্রুটি পেয়েছে

 DataBase Errorz: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '* FROM 2_1_paidused WHERE NumberRenamed = '¿\' OR 1=1 /*' LIMIT 1' at line 1

সুতরাং আমার উপসংহার যে কোনও ইঞ্জেকশন সম্ভব নয় ...


3
আপনার এটি একটি নতুন প্রশ্ন করা উচিত যেখানে এটির জন্য একটি রেফারেন্স দেওয়া হয়েছে
আপনার সাধারণ সংবেদন

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

এটি প্রশ্নের যে কোনও কিছুর সাথে কীভাবে প্রাসঙ্গিক তা নিশ্চিত নয়।
সিএইচও

প্রশ্নে শব্দগুলি but you risk to be injected with multiple queries.আমার উত্তরটি ইনজেকশন সম্পর্কে
এন্ডিস

0

এই ফাংশনটি ব্যবহার করে দেখুন: mltiple ক্যোয়ারী এবং একাধিক মান সন্নিবেশ।

function employmentStatus($Status) {
$pdo = PDO2::getInstance();

$sql_parts = array(); 
for($i=0; $i<count($Status); $i++){
    $sql_parts[] = "(:userID, :val$i)";
}

$requete = $pdo->dbh->prepare("DELETE FROM employment_status WHERE userid = :userID; INSERT INTO employment_status (userid, status) VALUES ".implode(",", $sql_parts));
$requete->bindParam(":userID", $_SESSION['userID'],PDO::PARAM_INT);
for($i=0; $i<count($Status); $i++){
    $requete->bindParam(":val$i", $Status[$i],PDO::PARAM_STR);
}
if ($requete->execute()) {
    return true;
}
return $requete->errorInfo();
}

0

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

$statement = $connection->query($query);
do {
  $data[] = $statement->fetchAll(PDO::FETCH_ASSOC);
} while ($statement->nextRowset());

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

প্রিয় @ ইওরকমমনসেন্স একযোগে একাধিক ক্যোয়ারী চালানো পারফরম্যান্সে সহায়তা করে, কম নেটওয়ার্ক ট্র্যাফিক + সার্ভার সম্পর্কিত অনুসন্ধানগুলি অনুকূল করতে পারে। আমার (সরলীকৃত) উদাহরণটি কেবল এটি ব্যবহারের জন্য প্রয়োজনীয় পদ্ধতিটি প্রবর্তন করে। আপনি উল্লেখ করছেন এমন ভাল অনুশীলনগুলি ব্যবহার না করা হলে এটি কেবল একটি সুরক্ষার গর্ত। বিটিডাব্লু, আমি এমন লোকদের সম্পর্কে সন্দেহ করি যারা "আমি কখনই বুঝতে পারি না ..." বলে যখন তারা সহজেই পারত ... :-)
অ্যান্ডিস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.