سؤال

أقوم بإنشاء برنامج نصي لتثبيت تطبيق أقوم بتطويره وأحتاج إلى إنشاء قواعد بيانات ديناميكيًا من داخل PHP.لقد تمكنت من إنشاء قاعدة البيانات ولكنني الآن بحاجة إلى تحميل عدة ملفات .sql.لقد خططت لفتح الملف وmysql_query سطرًا تلو الآخر - حتى نظرت إلى ملفات المخطط وأدركت أنها ليست مجرد استعلام واحد في كل سطر.

لذا، كيف يمكنني تحميل ملف SQL من داخل PHP (كما يفعل phpMyAdmin مع أمر الاستيراد الخاص به)؟

هل كانت مفيدة؟

المحلول

أشعر أن كل من أجاب على هذا السؤال هنا لا يعرف كيف يكون الأمر عندما تكون مطور تطبيقات ويب يسمح للأشخاص بتثبيت التطبيق على خوادمهم الخاصة.لا تسمح لك الاستضافة المشتركة، على وجه الخصوص، باستخدام SQL مثل استعلام "LOAD DATA" المذكور سابقًا.لا يسمح لك معظم المضيفين المشتركين أيضًا باستخدام shell_exec.

الآن، للإجابة على OP، أفضل رهان لك هو إنشاء ملف PHP يحتوي على استعلاماتك في متغير ويمكنه تشغيلها فقط.إذا كنت مصممًا على تحليل ملفات .sql، فيجب عليك البحث في phpMyAdmin والحصول على بعض الأفكار للحصول على البيانات من ملفات .sql بهذه الطريقة.انظر حولك إلى تطبيقات الويب الأخرى التي تحتوي على أدوات تثبيت وسترى أنه بدلاً من استخدام ملفات .sql لاستعلاماتها، فإنها تقوم فقط بتجميعها في ملفات PHP وتشغيل كل سلسلة من خلال mysql_query أو أي شيء يحتاجون إلى القيام به .

نصائح أخرى

$db = new PDO($dsn, $user, $password);

$sql = file_get_contents('file.sql');

$qr = $db->exec($sql);

يستخدم phpBB بعض الوظائف لتحليل ملفاتهم.لقد تم التعليق عليهم جيدًا (يا له من استثناء!) حتى تتمكن بسهولة من معرفة ما يفعلونه (حصلت على هذا الحل من http://www.frihost.com/forums/vt-8194.html).إليك الحل وقد استخدمته كثيرًا:

<php
ini_set('memory_limit', '5120M');
set_time_limit ( 0 );
/***************************************************************************
*                             sql_parse.php
*                              -------------------
*     begin                : Thu May 31, 2001
*     copyright            : (C) 2001 The phpBB Group
*     email                : support@phpbb.com
*
*     $Id: sql_parse.php,v 1.8 2002/03/18 23:53:12 psotfx Exp $
*
****************************************************************************/

/***************************************************************************
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 ***************************************************************************/

/***************************************************************************
*
*   These functions are mainly for use in the db_utilities under the admin
*   however in order to make these functions available elsewhere, specifically
*   in the installation phase of phpBB I have seperated out a couple of
*   functions into this file.  JLH
*
\***************************************************************************/

//
// remove_comments will strip the sql comment lines out of an uploaded sql file
// specifically for mssql and postgres type files in the install....
//
function remove_comments(&$output)
{
   $lines = explode("\n", $output);
   $output = "";

   // try to keep mem. use down
   $linecount = count($lines);

   $in_comment = false;
   for($i = 0; $i &lt; $linecount; $i++)
   {
      if( preg_match("/^\/\*/", preg_quote($lines[$i])) )
      {
         $in_comment = true;
      }

      if( !$in_comment )
      {
         $output .= $lines[$i] . "\n";
      }

      if( preg_match("/\*\/$/", preg_quote($lines[$i])) )
      {
         $in_comment = false;
      }
   }

   unset($lines);
   return $output;
}

//
// remove_remarks will strip the sql comment lines out of an uploaded sql file
//
function remove_remarks($sql)
{
   $lines = explode("\n", $sql);

   // try to keep mem. use down
   $sql = "";

   $linecount = count($lines);
   $output = "";

   for ($i = 0; $i &lt; $linecount; $i++)
   {
      if (($i != ($linecount - 1)) || (strlen($lines[$i]) > 0))
      {
         if (isset($lines[$i][0]) && $lines[$i][0] != "#")
         {
            $output .= $lines[$i] . "\n";
         }
         else
         {
            $output .= "\n";
         }
         // Trading a bit of speed for lower mem. use here.
         $lines[$i] = "";
      }
   }

   return $output;

}

//
// split_sql_file will split an uploaded sql file into single sql statements.
// Note: expects trim() to have already been run on $sql.
//
function split_sql_file($sql, $delimiter)
{
   // Split up our string into "possible" SQL statements.
   $tokens = explode($delimiter, $sql);

   // try to save mem.
   $sql = "";
   $output = array();

   // we don't actually care about the matches preg gives us.
   $matches = array();

   // this is faster than calling count($oktens) every time thru the loop.
   $token_count = count($tokens);
   for ($i = 0; $i &lt; $token_count; $i++)
   {
      // Don't wanna add an empty string as the last thing in the array.
      if (($i != ($token_count - 1)) || (strlen($tokens[$i] > 0)))
      {
         // This is the total number of single quotes in the token.
         $total_quotes = preg_match_all("/'/", $tokens[$i], $matches);
         // Counts single quotes that are preceded by an odd number of backslashes,
         // which means they're escaped quotes.
         $escaped_quotes = preg_match_all("/(?&lt;!\\\\)(\\\\\\\\)*\\\\'/", $tokens[$i], $matches);

         $unescaped_quotes = $total_quotes - $escaped_quotes;

         // If the number of unescaped quotes is even, then the delimiter did NOT occur inside a string literal.
         if (($unescaped_quotes % 2) == 0)
         {
            // It's a complete sql statement.
            $output[] = $tokens[$i];
            // save memory.
            $tokens[$i] = "";
         }
         else
         {
            // incomplete sql statement. keep adding tokens until we have a complete one.
            // $temp will hold what we have so far.
            $temp = $tokens[$i] . $delimiter;
            // save memory..
            $tokens[$i] = "";

            // Do we have a complete statement yet?
            $complete_stmt = false;

            for ($j = $i + 1; (!$complete_stmt && ($j &lt; $token_count)); $j++)
            {
               // This is the total number of single quotes in the token.
               $total_quotes = preg_match_all("/'/", $tokens[$j], $matches);
               // Counts single quotes that are preceded by an odd number of backslashes,
               // which means they're escaped quotes.
               $escaped_quotes = preg_match_all("/(?&lt;!\\\\)(\\\\\\\\)*\\\\'/", $tokens[$j], $matches);

               $unescaped_quotes = $total_quotes - $escaped_quotes;

               if (($unescaped_quotes % 2) == 1)
               {
                  // odd number of unescaped quotes. In combination with the previous incomplete
                  // statement(s), we now have a complete statement. (2 odds always make an even)
                  $output[] = $temp . $tokens[$j];

                  // save memory.
                  $tokens[$j] = "";
                  $temp = "";

                  // exit the loop.
                  $complete_stmt = true;
                  // make sure the outer loop continues at the right point.
                  $i = $j;
               }
               else
               {
                  // even number of unescaped quotes. We still don't have a complete statement.
                  // (1 odd and 1 even always make an odd)
                  $temp .= $tokens[$j] . $delimiter;
                  // save memory.
                  $tokens[$j] = "";
               }

            } // for..
         } // else
      }
   }

   return $output;
}

$dbms_schema = 'yourfile.sql';

$sql_query = @fread(@fopen($dbms_schema, 'r'), @filesize($dbms_schema)) or die('problem ');
$sql_query = remove_remarks($sql_query);
$sql_query = split_sql_file($sql_query, ';');

$host = 'localhost';
$user = 'user';
$pass = 'pass';
$db = 'database_name';

//In case mysql is deprecated use mysqli functions. 
mysqli_connect($host,$user,$pass) or die('error connection');
mysqli_select_db($db) or die('error database selection');

$i=1;
foreach($sql_query as $sql){
echo $i++;
echo "<br />";
mysql_query($sql) or die('error in query');
}

?>

الحل الأبسط هو استخدام shell_exec() لتشغيل عميل mysql باستخدام برنامج SQL النصي كمدخل.قد يعمل هذا بشكل أبطأ قليلاً لأنه يجب أن يتفرع، ولكن يمكنك كتابة الكود في بضع دقائق ثم العودة إلى العمل على شيء مفيد.قد تستغرق كتابة برنامج PHP النصي لتشغيل أي برنامج نصي SQL أسابيع.

يعد دعم البرامج النصية لـ SQL أكثر تعقيدًا مما يصفه الأشخاص هنا، إلا إذا كنت متأكدًا من أن البرنامج النصي الخاص بك يحتوي فقط على مجموعة فرعية من وظائف البرامج النصية.فيما يلي بعض الأمثلة على الأشياء التي قد تظهر في برنامج نصي SQL عادي مما يجعل من الصعب ترميز برنامج نصي لتفسيره سطرًا تلو الآخر.

-- Comment lines cannot be prepared as statements
-- This is a MySQL client tool builtin command.  
-- It cannot be prepared or executed by server.
USE testdb;

-- This is a multi-line statement.
CREATE TABLE foo (
  string VARCHAR(100)
);

-- This statement is not supported as a prepared statement.
LOAD DATA INFILE 'datafile.txt' INTO TABLE foo;

-- This statement is not terminated with a semicolon.
DELIMITER //

-- This multi-line statement contains a semicolon 
-- but not as the statement terminator.
CREATE PROCEDURE simpleproc (OUT param1 INT)
BEGIN
  SELECT COUNT(*) INTO param1 FROM foo;
END
// 

إذا كنت تدعم فقط مجموعة فرعية من برامج SQL النصية، باستثناء بعض الحالات الزاوية مثل تلك المذكورة أعلاه، فمن السهل نسبيًا كتابة برنامج PHP النصي الذي يقرأ ملفًا وينفذ عبارات SQL داخل الملف.ولكن إذا كنت تريد دعم أي برنامج نصي SQL صالح، فهذا أكثر تعقيدًا.


انظر أيضًا إجاباتي على هذه الأسئلة ذات الصلة:

mysqli يمكن تشغيل استعلامات متعددة مفصولة بـ a ;

يمكنك قراءة الملف بأكمله وتشغيله مرة واحدة باستخدام mysqli_multi_query()

ولكن، سأكون أول من يقول أن هذا ليس الحل الأكثر أناقة.

لقد استخدمت الحل التالي في مشاريعي:

<?php

/**
 * Import SQL from file
 *
 * @param string path to sql file
 */
function sqlImport($file)
{

    $delimiter = ';';
    $file = fopen($file, 'r');
    $isFirstRow = true;
    $isMultiLineComment = false;
    $sql = '';

    while (!feof($file)) {

        $row = fgets($file);

        // remove BOM for utf-8 encoded file
        if ($isFirstRow) {
            $row = preg_replace('/^\x{EF}\x{BB}\x{BF}/', '', $row);
            $isFirstRow = false;
        }

        // 1. ignore empty string and comment row
        if (trim($row) == '' || preg_match('/^\s*(#|--\s)/sUi', $row)) {
            continue;
        }

        // 2. clear comments
        $row = trim(clearSQL($row, $isMultiLineComment));

        // 3. parse delimiter row
        if (preg_match('/^DELIMITER\s+[^ ]+/sUi', $row)) {
            $delimiter = preg_replace('/^DELIMITER\s+([^ ]+)$/sUi', '$1', $row);
            continue;
        }

        // 4. separate sql queries by delimiter
        $offset = 0;
        while (strpos($row, $delimiter, $offset) !== false) {
            $delimiterOffset = strpos($row, $delimiter, $offset);
            if (isQuoted($delimiterOffset, $row)) {
                $offset = $delimiterOffset + strlen($delimiter);
            } else {
                $sql = trim($sql . ' ' . trim(substr($row, 0, $delimiterOffset)));
                query($sql);

                $row = substr($row, $delimiterOffset + strlen($delimiter));
                $offset = 0;
                $sql = '';
            }
        }
        $sql = trim($sql . ' ' . $row);
    }
    if (strlen($sql) > 0) {
        query($row);
    }

    fclose($file);
}

/**
 * Remove comments from sql
 *
 * @param string sql
 * @param boolean is multicomment line
 * @return string
 */
function clearSQL($sql, &$isMultiComment)
{
    if ($isMultiComment) {
        if (preg_match('#\*/#sUi', $sql)) {
            $sql = preg_replace('#^.*\*/\s*#sUi', '', $sql);
            $isMultiComment = false;
        } else {
            $sql = '';
        }
        if(trim($sql) == ''){
            return $sql;
        }
    }

    $offset = 0;
    while (preg_match('{--\s|#|/\*[^!]}sUi', $sql, $matched, PREG_OFFSET_CAPTURE, $offset)) {
        list($comment, $foundOn) = $matched[0];
        if (isQuoted($foundOn, $sql)) {
            $offset = $foundOn + strlen($comment);
        } else {
            if (substr($comment, 0, 2) == '/*') {
                $closedOn = strpos($sql, '*/', $foundOn);
                if ($closedOn !== false) {
                    $sql = substr($sql, 0, $foundOn) . substr($sql, $closedOn + 2);
                } else {
                    $sql = substr($sql, 0, $foundOn);
                    $isMultiComment = true;
                }
            } else {
                $sql = substr($sql, 0, $foundOn);
                break;
            }
        }
    }
    return $sql;
}

/**
 * Check if "offset" position is quoted
 *
 * @param int $offset
 * @param string $text
 * @return boolean
 */
function isQuoted($offset, $text)
{
    if ($offset > strlen($text))
        $offset = strlen($text);

    $isQuoted = false;
    for ($i = 0; $i < $offset; $i++) {
        if ($text[$i] == "'")
            $isQuoted = !$isQuoted;
        if ($text[$i] == "\\" && $isQuoted)
            $i++;
    }
    return $isQuoted;
}

function query($sql)
{
    global $mysqli;
    //echo '#<strong>SQL CODE TO RUN:</strong><br>' . htmlspecialchars($sql) . ';<br><br>';
    if (!$query = $mysqli->query($sql)) {
        throw new Exception("Cannot execute request to the database {$sql}: " . $mysqli->error);
    }
}

set_time_limit(0);

$mysqli = new mysqli('localhost', 'root', '', 'test');
$mysqli->set_charset("utf8");

header('Content-Type: text/html;charset=utf-8');
sqlImport('import.sql');

echo "Peak MB: ", memory_get_peak_usage(true)/1024/1024;

عند اختبار ذروة استخدام ذاكرة ملف SQL (41 ميجابايت):3.25 ميجا بايت

بما أنني لا أستطيع التعليق على الإجابة، احذر من استخدام الحل التالي:

$db = new PDO($dsn, $user, $password);

$sql = file_get_contents('file.sql');

$qr = $db->exec($sql);

هناك خطأ في PHP PDO https://bugs.php.net/bug.php?id=61613

db->exec('SELECT 1; invalidstatement; SELECT 2');

لن يظهر خطأ أو يُرجع خطأ (تم اختباره على PHP 5.5.14).

سيكون اقتراحي هو إلقاء نظرة على الكود المصدري لـ PHPMyBackup.إنه مُحمل PHP SQL الآلي.ستجد أن mysql_query يقوم بتحميل استعلام واحد فقط في كل مرة، وأن مشاريع مثل PHPMyAdmin و PHPMyBackup قد قامت بالفعل بالعمل الشاق من أجل تحليل SQL بالطريقة الصحيحة.من فضلك لا تعيد اختراع تلك العجلة :P

حل محدث لحل Plahcinski.بدلًا من ذلك، يمكنك استخدام fopen وfread للملفات الأكبر حجمًا:

$fp = file('database.sql', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$query = '';
foreach ($fp as $line) {
    if ($line != '' && strpos($line, '--') === false) {
        $query .= $line;
        if (substr($query, -1) == ';') {
            mysql_query($query);
            $query = '';
        }
    }
}

هل أنت متأكد من أنه ليس استعلامًا واحدًا في كل سطر؟قد يكون محرر النصوص الخاص بك عبارة عن أسطر ملتفة، ولكن في الواقع قد يكون كل استعلام على سطر واحد.

على أية حال، تبدو طريقة أولي هي الأفضل.إذا كانت لديك أسباب لتشغيل الاستعلامات واحدًا تلو الآخر، فيجب أن تكون قادرًا على قراءة ملفك سطرًا تلو الآخر، ثم استخدم الفاصلة المنقوطة في نهاية كل استعلام لتحديد الحدود.من الأفضل لك قراءة ملف سطرًا تلو الآخر بدلاً من محاولة تقسيم سلسلة ضخمة، حيث سيكون ذلك أكثر لطفًا على ذاكرة الخادم الخاص بك.مثال:

$query  = '';
$handle = @fopen("/sqlfile.sql", "r");

if ($handle) {
    while (!feof($handle)) {
        $query.= fgets($handle, 4096);

        if (substr(rtrim($query), -1) === ';') {
            // ...run your query, then unset the string
            $query = '';
        }
    }

    fclose($handle);
}

من الواضح أنك ستحتاج إلى مراعاة المعاملات والباقي إذا كنت تقوم بتشغيل مجموعة كبيرة من الاستعلامات دفعة واحدة، ولكن من المحتمل ألا يكون ذلك مشكلة كبيرة بالنسبة لبرنامج نصي للتثبيت الجديد.

يعمل على مقالب Navicat.قد تحتاج إلى تفريغ التعليق الأول /* */ الذي يضعه navicat.

$file_content = file('myfile.sql');
$query = "";
foreach($file_content as $sql_line){
  if(trim($sql_line) != "" && strpos($sql_line, "--") === false){
    $query .= $sql_line;
    if (substr(rtrim($query), -1) == ';'){
      echo $query;
      $result = mysql_query($query)or die(mysql_error());
      $query = "";
    }
  }
 }

جرب هذا:

// SQL File
$SQLFile = 'YourSQLFile.sql';

// Server Name
$hostname = 'localhost';

// User Name
$db_user = 'root';

// User Password
$db_password = '';

// DBName
$database_name = 'YourDBName';

// Connect MySQL
$link = mysql_connect($hostname, $db_user, $db_password);

if (!$link) {
die("MySQL Connection error");
}

// Select MySQL DB
mysql_select_db($database_name, $link) or die("Wrong MySQL Database");

// Function For Run Multiple Query From .SQL File
function MultiQuery($sqlfile, $sqldelimiter = ';') {
set_time_limit(0);

if (is_file($sqlfile) === true) {
$sqlfile = fopen($sqlfile, 'r');

if (is_resource($sqlfile) === true) {
$query = array();
echo "<table cellspacing='3' cellpadding='3' border='0'>";

while (feof($sqlfile) === false) {
$query[] = fgets($sqlfile);

if (preg_match('~' . preg_quote($sqldelimiter, '~') . '\s*$~iS', end($query)) === 1) {
$query = trim(implode('', $query));

if (mysql_query($query) === false) {
echo '<tr><td>ERROR:</td><td> ' . $query . '</td></tr>';
} else {
echo '<tr><td>SUCCESS:</td><td>' . $query . '</td></tr>';
}

while (ob_get_level() &gt; 0) {
ob_end_flush();
}

flush();
}

if (is_string($query) === true) {
$query = array();
}
}
echo "</table>";

return fclose($sqlfile);
}
}

return false;
}

/* * * Use Function Like This: ** */

MultiQuery($SQLFile);
mysql_query("LOAD DATA LOCAL INFILE '/path/to/file' INTO TABLE mytable");

باختصار الطريقة التي قمت بها هي:

  1. اقرأ الملف (تفريغ db على سبيل المثال $ mysqldump db > db.sql)

    $sql = file_get_contents(db.sql);
    
  2. قم باستيراده باستخدام mysqli::multi_query

    if ($mysqli->multi_query($sql)) {
        $mysqli->close();
    } else {
        throw new Exception ($mysqli->error);
    }
    

انتبه إلى أن mysqli_query يدعم الاستعلامات غير المتزامنة.المزيد هنا: http://php.net/manual/en/mysqli.multi-query.php و هنا https://stackoverflow.com/a/6652908/2002493

إلا إذا كنت تخطط للاستيراد ضخم ملفات .sql، ما عليك سوى قراءة الملف بأكمله في الذاكرة وتشغيله كاستعلام.

لقد مر وقت طويل منذ أن استخدمت PHP، لذا، الكود الزائف:

all_query = read_file("/my/file.sql")
con = mysql_connect("localhost")
con.mysql_select_db("mydb")
con.mysql_query(all_query)
con.close()

ما لم تكن الملفات ضخمة (على سبيل المثال، أكثر من عدة ميغابايت)، فلا يوجد سبب لتنفيذها سطرًا تلو الآخر، أو محاولة تقسيمها إلى استعلامات متعددة (عن طريق التقسيم باستخدام ;, ، والتي كما علقت على إجابة cam8001، سوف تنقطع إذا كان الاستعلام يحتوي على فاصلة منقوطة داخل السلاسل)..

هذا أفضل كود لاستعادة sql بواسطة php يمكنه استخدام 100% Goooood!شكرا جزيلا

$file_content = file('myfile.sql');
$query = "";
foreach($file_content as $sql_line){
if(trim($sql_line) != "" && strpos($sql_line, "--") === false){
 $query .= $sql_line;
 if (substr(rtrim($query), -1) == ';'){
   echo $query;
   $result = mysql_query($query)or die(mysql_error());
   $query = "";
  }
 }
}

الطريقة الأسهل والأسرع لتحميل وتحليل ملف تفريغ phpmyadmin أو ملف تفريغ MySQL..

$ mysql -u username -p -h localhost dbname < dumpfile.sql 

لقد لاحظت أن برنامج تشغيل PostgreSQL PDO لا يسمح لك بتشغيل البرامج النصية مفصولة بفواصل منقوطة.من أجل تشغيل ملف .sql على أي قاعدة بيانات باستخدام PDO، من الضروري تقسيم البيانات في كود PHP بنفسك.إليك الحل الذي يبدو أنه يعمل بشكل جيد:

https://github.com/diontruter/migrate/blob/master/src/Diontruter/Migrate/SqlScriptParser.php

لقد قام الفصل المشار إليه بالمهمة بالنسبة لي بطريقة مستقلة عن قاعدة البيانات، يرجى مراسلتي إذا كانت هناك أية مشكلات.إليك كيفية استخدام البرنامج النصي بعد إضافته إلى مشروعك:

$pdo = new PDO($connectionString, $userName, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$parser = new SqlScriptParser();
$sqlStatements = $parser->parse($fileName);
foreach ($sqlStatements as $statement) {
    $distilled = $parser->removeComments($statement);
    if (!empty($distilled)) {
        $statement = $pdo->prepare($sql);
        $affectedRows = $statement->execute();
    }
}

لا يتعامل أي من الحلول التي رأيتها هنا مع الحاجة إلى تغيير المحدد أثناء إنشاء إجراء مخزن على خادم حيث لا يمكنني الاعتماد على الوصول إلى LOAD DATA INFILE.كنت أتمنى أن أجد أن شخصًا ما قد قام بحل هذه المشكلة بالفعل دون الحاجة إلى البحث في كود phpMyAdmin لمعرفة ذلك.مثل الآخرين، كنت أيضًا في طور البحث عن طريقة مملوكة لـ GPL لشخص آخر للقيام بذلك بما أنني أكتب كود GPL بنفسي.

يمكن لبعض مكتبات PHP تحليل ملف SQL مكون من عدة عبارات SQL، وتفجيرها بشكل صحيح (بدون استخدام "؛" بسيطة، وتفجيرها بشكل طبيعي)، وتنفيذها.

على سبيل المثال، تحقق بينغPDOSQLExecTask

فقط لإعادة صياغة المشكلة للجميع:

يقوم mysql_query الخاص بـ PHP تلقائيًا بتحديد نهاية كل أوامر SQL، بالإضافة إلى أنه غامض جدًا بشأن القيام بذلك في دليله.كل شيء يتجاوز أمراً واحداً سيؤدي إلى خطأ.

ومن ناحية أخرى، يكون mysql_query مناسبًا مع سلسلة تحتوي على تعليقات بنمط SQL، ، ..

يكشف قيود mysql_query عن نفسه حيث يقوم محلل SQL بالإبلاغ عن المشكلة مباشرة في الأمر التالي على سبيل المثال.

 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 'INSERT INTO `outputdb:`
 (`intid`, `entry_id`, `definition`) VALUES...

هنا حل سريع:(بافتراض SQL منسقة بشكل جيد؛

$sqlCmds = preg_split("/[\n|\t]*;[\n|\t]*[\n|\r]$/", $sqlDump);

لن يسمح لك العديد من المضيفين بإنشاء قاعدة البيانات الخاصة بك من خلال PHP، ولكن يبدو أنك قد قمت بحل هذه المشكلة.
بمجرد إنشاء قاعدة البيانات، يمكنك التعامل معها وتعبئتها ببساطة:

mysql_connect("المضيف المحلي");
mysql_query("SOURCE file.sql");

اقترح بعض الرجال (Plahcinski) هذا الرمز:

$file_content = file('myfile.sql');
$query = "";
foreach($file_content as $sql_line){
  if(trim($sql_line) != "" && strpos($sql_line, "--") === false){
    $query .= $sql_line;
    if (substr(rtrim($query), -1) == ';'){
      echo $query;
      $result = mysql_query($query)or die(mysql_error());
      $query = "";
    }
  }
 }

لكنني سأقوم بتحديثه بالذي يناسبني:

 //selecting my database
    $database = 'databaseTitleInFile';
    $selectDatabase = mysql_select_db($database, $con);
    if(! $selectDatabase )
    {
      die('Could not select the database: ' . mysql_error());
    }
    echo "The database " . $database . " selected successfully\n";
//reading the file
    $file_path='..\yourPath\to\File';
    if(!file_exists($file_path)){
        echo "File Not Exists";
    }
    $file_content = file_get_contents($file_path);
    $array = explode("\n", $file_content)
//making queries
    $query = "";
        foreach($array as $sql_line){
$sql_line=trim($sql_line);
          if($sql_line != "" && substr($sql_line, 0, 2) === "--" && strpos($sql_line, "/*") === false){
            $query .= $sql_line;
            if (substr(rtrim($query), -1) == ';'){
              $result = mysql_query($query)or die(mysql_error());
              $query = "";
            }
          }
         }

لأنه أشمل.؛-)

قد يكون هذا مفيدًا -->

أكثر أو أقل ما يفعله هو أولاً أخذ السلسلة المعطاة للوظيفة (قيمة file_get_contents() الخاصة بملفك file.sql) وإزالة جميع فواصل الأسطر.ثم يقسم البيانات بواسطة "؛" شخصية.بعد ذلك، ينتقل إلى حلقة while، وينظر إلى كل سطر من المصفوفة التي تم إنشاؤها.إذا كان السطر يحتوي على الحرف " ` "، فسوف يعرف أنه استعلام وينفذ وظيفة myquery() لبيانات السطر المحددة.

شفرة:

function myquery($query) {

mysql_connect(dbhost, dbuser, dbpass);

mysql_select_db(dbname);

$result = mysql_query($query);

if (!mysql_errno() && @mysql_num_rows($result) > 0) {
}

else {

$result="not";
}
mysql_close();

return $result;

}



function mybatchquery ($str) {

$sql = str_replace("\n","",$str)

$sql = explode(";",$str);

$x=0;

while (isset($str[$x])) {

if (preg_match("/(\w|\W)+`(\w|\W)+) {

myquery($str[$x]);

}

$x++

}

return TRUE;

}




function myrows($result) {

$rows = @mysql_num_rows($result);

return $rows;
}




function myarray($result) {

$array = mysql_fetch_array($result);

return $array;
}




function myescape($query) {

$escape = mysql_escape_string($query);

return $escape;
}



$str = file_get_contents("foo.sql");
mybatchquery($str);

لماذا لا تأخذ الكود من phpMyAdmin وتستخدمه؟إنه مفتوح المصدر بعد كل شيء ...

أنا استخدم هذا في كل وقت:

$sql = explode(";",file_get_contents('[your dump file].sql'));// 

foreach($sql as $query)
 mysql_query($query);

آمل أن يحل الكود التالي مشكلتك بشكل جيد.

//Empty all tables' contents

$result_t = mysql_query("SHOW TABLES");
while($row = mysql_fetch_assoc($result_t))
{
mysql_query("TRUNCATE " . $row['Tables_in_' . $mysql_database]);
}
// Temporary variable, used to store current query
$templine = '';
// Read in entire file
$lines = file($filename);
// Loop through each line
foreach ($lines as $line)
{
// Skip it if it's a comment
if (substr($line, 0, 2) == '--' || $line == '')
    continue;

// Add this line to the current segment
$templine .= $line;
// If it has a semicolon at the end, it's the end of the query
if (substr(trim($line), -1, 1) == ';')
{
    // Perform the query
    mysql_query($templine) or print('Error performing query \'<strong>' . $templine . '\': ' . mysql_error() . '<br /><br />');
    // Reset temp variable to empty
    $templine = '';
}
}

?>

لقد نجح هذا بالفعل بالنسبة لي:

/* load sql-commands from a sql file */
function loadSQLFromFile($url)
{
    // ini_set ( 'memory_limit', '512M' );
    // set_time_limit ( 0 );

    global $settings_database_name;
    global $mysqli_object; global $worked; $worked = false;

    $sql_query = "";

    // read line by line
    $lines = file($url);
    $count = count($lines);

    for($i = 0;$i<$count;$i++)
    {
        $line = $lines[$i];
        $cmd3 = substr($line, 0, 3);
        $cmd4 = substr($line, 0, 4);
        $cmd6 = substr($line, 0, 6);
        if($cmd3 == "USE")
        {
            // cut away USE ``;
            $settings_database_name = substr($line, 5, -3);
        }
        else if($cmd4 == "DROP")
        {
            $mysqli_object->query($line); // execute this line
        }
        else if(($cmd6 == "INSERT") || ($cmd6 == "CREATE"))
        {
            // sum all lines up until ; is detected
            $multiline = $line;
            while(!strstr($line, ';'))
            {
                $i++;
                $line = $lines[$i];
                $multiline .= $line;
            }
            $multiline = str_replace("\n", "", $multiline); // remove newlines/linebreaks
            $mysqli_object->query($multiline); // execute this line
        }       
    }

    return $worked;
}
?>

لدي بيئة حيث لا توجد أداة mysql أو phpmyadmin فقط تطبيق php الخاص بي يتصل بخادم mysql على مضيف مختلف ولكني بحاجة إلى تشغيل البرامج النصية التي تم تصديرها بواسطة mysqldump أو myadmin.لحل المشكلة قمت بإنشاء برنامج نصي multi_query كما ذكرت هنا

يمكنه معالجة إخراج mysqldump وتصدير phpmyadmin بدون أداة سطر أوامر mysql.لقد قمت أيضًا بإنشاء بعض المنطق لمعالجة ملفات ترحيل متعددة بناءً على الطابع الزمني المخزن في قاعدة البيانات مثل Rails.أعلم أنه يحتاج إلى مزيد من معالجة الأخطاء ولكنه يقوم بالعمل حاليًا نيابةً عني.

تحقق من ذلك: https://github.com/kepes/php-migration

إنه PHP خالص ولا يحتاج إلى أي أدوات أخرى.إذا لم تقم بمعالجة إدخال المستخدم باستخدام البرامج النصية التي أنشأها المطورون أو أدوات التصدير فقط، فيمكنك استخدامها بأمان.

وهذا من المشروع الذي أعمل عليه.يأخذ بشكل أساسي أي ملف نصي ويستخرج عبارات SQL مع تجاهل التعليقات وفواصل الأسطر غير المبررة.

<?php

  /*
     ingestSql(string) : string

     Read the contents of a SQL batch file, stripping away comments and
     joining statements that are broken over multiple lines with the goal
     of producing lines of sql statements that can be successfully executed
     by PDO exec() or execute() functions.

     For example:
       -- My SQL Batch
       CREATE TABLE foo(
         bar VARCHAR(80),
         baz INT NOT NULL);

     Becomes:
       CREATE TABLE foo(bar VARCHAR(80), baz INT NOT NULL);
  */

  function ingestSql($sqlFilePath=__DIR__ . "/create-db.sql") {
    $sqlFile = file($sqlFilePath);
    $ingestedSql = "";
     $statement = "";
    foreach($sqlFile as $line) {

      // Ignore anything between a double-dash and the end of the line.
      $commentStart = strpos($line, "--");
      if ($commentStart !== false) {
        $line = substr($line, 0, $commentStart);
      }

      // Only process non-blank lines.
      if (strlen($line)) {

        // Remove any leading and trailing whitespace and append what's
        // left of the line to the current statement.
        $line = trim($line);
        $statement .= $line;

        // A semi-colon ends the current statement.  Otherwise what was a
        // newline becomes a single space;
        if (substr($statement, -1) == ";") {
          $ingestedSql .= $statement;
          $statement = "\n";
        }
        else {
          $statement .= " ";
        }
      }
    }

    return $ingestedSql;
  }

?>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top