Загрузка файлов .sql из PHP

php sql mysql import scripting

121426 просмотра

30 ответа

Я создаю сценарий установки для приложения, которое я разрабатываю, и мне нужно динамически создавать базы данных из PHP. У меня есть это для создания базы данных, но теперь мне нужно загрузить в несколько файлов .sql. Я планировал открывать файл и mysql_query по одной строке за раз - пока я не посмотрел на файлы схемы и не понял, что это не просто один запрос на строку.

Итак, как мне загрузить файл sql из PHP (как phpMyAdmin с его командой import)?

Автор: Josh Smeaton Источник Размещён: 17.05.2019 02:37

Ответы (30)


46 плюса

Решение

У меня возникает ощущение, что все, кто здесь ответил на этот вопрос, не знают, каково это быть разработчиком веб-приложений, который позволяет людям устанавливать приложение на своих собственных серверах. В частности, виртуальный хостинг не позволяет использовать SQL, как, например, запрос «LOAD DATA», упомянутый ранее. Большинство общих хостов также не позволяют использовать shell_exec.

Теперь, чтобы ответить на OP, лучше всего создать файл PHP, содержащий ваши запросы в переменной и просто запустить их. Если вы полны решимости проанализировать файлы .sql, вам следует заглянуть в phpMyAdmin и получить некоторые идеи для получения данных из файлов .sql таким образом. Посмотрите на другие веб-приложения, в которых есть установщики, и вы увидите, что вместо того, чтобы использовать файлы .sql для своих запросов, они просто упаковывают их в файлы PHP и просто запускают каждую строку через mysql_query или все, что им нужно сделать ,

Автор: Jeremy Privett Размещён: 29.09.2008 06:48

65 плюса

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

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

$qr = $db->exec($sql);
Автор: Luis Granja Размещён: 24.08.2011 04:23

58 плюса

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

?>
Автор: Yasin Размещён: 07.07.2011 08:02

27 плюса

Самое простое решение - использовать 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, это намного сложнее.


Смотрите также мои ответы на эти связанные вопросы:

Автор: Bill Karwin Размещён: 29.09.2008 04:23

10 плюса

mysqli может выполнять несколько запросов, разделенных ;

Вы можете прочитать весь файл и запустить все сразу, используя mysqli_multi_query()

Но я буду первым, кто скажет, что это не самое элегантное решение.

Автор: phatduckk Размещён: 29.09.2008 05:40

10 плюса

В своих проектах я использовал следующее решение:

<?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 МБ

Автор: Gromo Размещён: 12.03.2013 06:04

5 плюса

Поскольку я не могу комментировать ответ, остерегайтесь использовать следующее решение:

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

не выдает ошибку или не возвращает false (проверено на PHP 5.5.14).

Автор: zstate Размещён: 02.04.2015 08:05

4 плюса

Мое предложение было бы посмотреть на исходный код PHPMyBackup. Это автоматический загрузчик PHP SQL. Вы обнаружите, что mysql_query загружает только один запрос за раз, а такие проекты, как PHPMyAdmin и PHPMyBackup, уже проделали тяжелую работу за правильный анализ SQL. Пожалуйста, не изобретайте это колесо: P

Автор: SchizoDuckie Размещён: 29.09.2008 09:49

4 плюса

Обновленное решение Плахчинского. В качестве альтернативы вы можете использовать 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 = '';
        }
    }
}
Автор: sanneo Размещён: 17.07.2012 02:54

3 плюса

Работает на свалках 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 = "";
    }
  }
 }
Автор: Plahcinski Размещён: 28.04.2011 08:29

3 плюса

Попробуй это:

// 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);
Автор: Neeraj Singh Размещён: 01.11.2011 09:15

3 плюса

Вы уверены, что это не один запрос на строку? Ваш текстовый редактор может переносить строки, но в действительности каждый запрос может быть в одной строке.

В любом случае, метод Олле кажется лучшим. Если у вас есть причины выполнять запросы по одному, вы должны иметь возможность читать в файле строку за строкой, а затем использовать точку с запятой в конце каждого запроса для разделения. Вы гораздо лучше читаете файл за строкой, чем пытаетесь разбить огромную строку, так как это будет намного лучше для памяти вашего сервера. Пример:

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

Очевидно, что вам нужно будет учитывать транзакции и все остальное, если вы выполняете большое количество запросов в пакете, но это, вероятно, не имеет большого значения для сценария новой установки.

Автор: cam8001 Размещён: 29.09.2008 08:21

3 плюса

mysql_query("LOAD DATA LOCAL INFILE '/path/to/file' INTO TABLE mytable");
Автор: olle Размещён: 29.09.2008 07:48

3 плюса

Вкратце, способ, которым я сделал это:

  1. Прочитать файл (например, дамп базы данных $ 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

Автор: Portmanteau Размещён: 21.05.2015 10:13

2 плюса

Если вы не планируете импортировать огромные файлы .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, сломает если запрос содержит точки с запятой в строках) ..

Автор: dbr Размещён: 29.09.2008 08:41

2 плюса

Это лучший код для восстановления 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 = "";
  }
 }
}
Автор: Ricky Размещён: 24.10.2011 05:55

2 плюса

Самый простой и быстрый способ загрузить и проанализировать дамп phpmyadmin или файл дампа mysql.

$ mysql -u username -p -h localhost dbname < dumpfile.sql 
Автор: Nemanja Размещён: 22.05.2012 10:14

1 плюс

Ни одно из решений, которые я видел здесь, не связано с необходимостью изменения разделителя при создании хранимой процедуры на сервере, где я не могу рассчитывать на доступ к LOAD DATA INFILE. Я надеялся обнаружить, что кто-то уже решил это, не прибегая к помощи кода phpMyAdmin, чтобы понять это. Как и другие, я тоже находился в процессе поиска чужого GPL-способа сделать это, так как сам пишу GPL-код.

Автор: K B Размещён: 01.06.2010 03:14

1 плюс

Некоторые библиотеки PHP могут анализировать файл SQL, состоящий из нескольких операторов SQL, анализировать его правильно (без использования простого символа ";", естественно) и выполнять их.

Например, проверьте Phos 's PDOSQLExecTask

Автор: Francois Zaninotto Размещён: 01.09.2010 01:38

1 плюс

Просто чтобы сформулировать проблему для всех:

PHP-запрос mysql_query автоматически разделяет конечные разделители каждой команды SQL, и, кроме того, он очень расплывчат в этом руководстве. Все, кроме одной команды, приведет к ошибке.

С другой стороны, mysql_query подходит для строки, содержащей комментарии в стиле SQL, \ n, \ r ..

Ограничение 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);
Автор: Lorenz Lo Sauer Размещён: 10.09.2011 08:10

1 плюс

Многие хосты не позволят вам создать собственную базу данных через PHP, но вы, похоже, решили это.
После того, как БД была создана, вы можете просто манипулировать ею и заполнять ее:

mysql_connect ( "локальный");
mysql_query ("SOURCE file.sql");

Автор: SamGoody Размещён: 30.10.2011 09:01

1 плюс

Некоторые ребята (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 = "";
    }
  }
 }

but I would update it with the one which worked for me:

 //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 = "";
            }
          }
         }

because it is more comprehensive. ;-)

Автор: Darius Miliauskas Размещён: 19.09.2013 11:08

1 плюс

This may be helpful -->

More or less what it does is to first take the string given to the function (the file_get_contents() value of your file.sql) and remove all the line breaks. Then it splits the data by the ";" character. Next it goes into a while loop, looking at each line of the array that is created. If the line contains the " ` " character, it will know it is a query and execture the myquery() function for the given line data.

Code:

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);
Автор: White Rabbit Размещён: 23.10.2013 03:18

1 плюс

I noticed that the PostgreSQL PDO driver does not allow you to run scripts separated by semicolons. In order to run a .sql file on any database using PDO it is necessary to split the statements in PHP code yourself. Here is a solution that seems to work quite well:

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();
    }
}
Автор: Dion Truter Размещён: 29.01.2017 10:50

0 плюса

Почему бы не взять код из phpMyAdmin и использовать его? Это с открытым исходным кодом в конце концов ...

Автор: Mez Размещён: 29.09.2008 07:46

0 плюса

Я использую это все время:

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

foreach($sql as $query)
 mysql_query($query);
Автор: Chip Размещён: 12.01.2011 03:43

0 плюса

Я надеюсь, что следующий код решит вашу проблему довольно хорошо.

//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 = '';
}
}

?>
Автор: Vijin Paulraj Размещён: 09.01.2012 12:29

0 плюса

это на самом деле работает для меня:

/* 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;
}
?>
Автор: canoodle Размещён: 18.09.2013 04:47

0 плюса

У меня есть среда, в которой нет ни инструмента mysql, ни phpmyadmin, а просто мое приложение php, подключающееся к серверу mysql на другом хосте, но мне нужно запускать сценарии, экспортированные mysqldump или myadmin. Чтобы решить проблему, я создал скрипт, multi_queryкак я уже упоминал здесь

Он может обрабатывать вывод mysqldump и экспорт phpmyadmin без инструмента командной строки mysql. Я также сделал некоторую логику для обработки нескольких файлов миграции на основе метки времени, хранящейся в БД, таких как Rails. Я знаю, что требуется больше обработки ошибок, но в настоящее время делает работу для меня.

Проверьте это: https://github.com/kepes/php-migration

Это чистый php и не требует никаких других инструментов. Если вы не обрабатываете пользовательский ввод с помощью только сценариев, созданных разработчиками или инструментами экспорта, вы можете использовать его безопасно.

Автор: kepes Размещён: 21.01.2015 09:26

0 плюса

Это из проекта, над которым я работаю. В основном берет любой текстовый файл и извлекает операторы 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;
  }

?>
Автор: Dave H. Размещён: 30.03.2019 12:59
Вопросы из категории :
32x32