web-dev-qa-db-fra.com

Chargement de fichiers .sql de l'intérieur PHP

Je crée un script d'installation pour une application que je développe et j'ai besoin de créer des bases de données de manière dynamique à partir de PHP. Je l'ai pour créer la base de données mais maintenant je dois charger plusieurs fichiers .sql. J'avais prévu d'ouvrir le fichier et mysql_query une ligne à la fois - jusqu'à ce que je regarde les fichiers de schéma et que je réalise qu'ils ne sont pas une requête par ligne.

Alors, comment puis-je charger un fichier SQL depuis PHP (comme le fait phpMyAdmin avec sa commande d'importation)?

59
Josh Smeaton

J'ai l'impression que tout le monde ici qui a répondu à cette question ne sait pas ce que c'est que d'être un développeur d'applications Web qui permet aux gens d'installer l'application sur leurs propres serveurs. L'hébergement partagé, en particulier, ne vous permet pas d'utiliser SQL comme la requête "LOAD DATA" mentionnée précédemment. La plupart des hôtes partagés ne vous autorisent pas non plus à utiliser Shell_exec.

Maintenant, pour répondre au PO, votre meilleur choix consiste simplement à créer un fichier PHP contenant vos requêtes dans une variable et à les exécuter. Si vous êtes déterminé à analyser les fichiers .sql, vous devriez jeter un œil sur phpMyAdmin et trouver des idées pour extraire les données de ces fichiers .sql. Regardez autour de vous avec d'autres applications Web qui ont des installateurs et vous verrez que, plutôt que d'utiliser des fichiers .sql pour leurs requêtes, ils les emballent simplement dans des fichiers PHP et exécutent simplement chaque chaîne via mysql_query ils doivent faire.

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

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

$qr = $db->exec($sql);
65
Luis Granja

phpBB utilise quelques fonctions pour analyser leurs fichiers. Ils sont plutôt bien commentés (quelle exception!), Donc vous pouvez facilement savoir ce qu’ils font (j’ai cette solution de http://www.frihost.com/forums/vt-8194.html ). voici la solution et je l'ai beaucoup utilisée:

<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                : [email protected]
*
*     $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');
}

?>
58
Yasin

La solution la plus simple consiste à utiliser Shell_exec () pour exécuter le client mysql avec le script SQL en entrée. Cela peut être un peu plus lent, car il doit être modifié, mais vous pouvez écrire le code en quelques minutes, puis reprendre votre travail. Écrire un script PHP pour exécuter n’importe quel script SQL peut prendre des semaines. 

La prise en charge des scripts SQL est plus complexe que ce que les utilisateurs décrivent ici, sauf si vous êtes certain que votre script ne contient qu'un sous-ensemble des fonctionnalités des scripts. Vous trouverez ci-dessous quelques exemples d'éléments susceptibles d'apparaître dans un script SQL ordinaire, qui compliquent le codage d'un script afin de l'interpréter ligne par ligne.

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

Si vous ne prenez en charge qu'un sous-ensemble de scripts SQL, à l'exception de certains cas tels que ceux décrits ci-dessus, il est relativement facile d'écrire un script PHP qui lit un fichier et exécute les instructions SQL qu'il contient. Mais si vous souhaitez prendre en charge un script SQL valide, c'est beaucoup plus complexe.


Voir aussi mes réponses à ces questions connexes:

27
Bill Karwin

Dans mes projets, j'ai utilisé la solution suivante:

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

Sur le test des fichiers sql (41 Mo), utilisation maximale de la mémoire: 3,25 Mo

10
Gromo

mysqli peut exécuter plusieurs requêtes séparées par un ; 

vous pouvez lire le fichier entier et le lancer en même temps avec mysqli_multi_query()

Mais je serai le premier à dire que ce n'est pas la solution la plus élégante.

10
phatduckk

Puisque je ne peux pas commenter la réponse, méfiez-vous des solutions suivantes:

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

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

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

Il y a un bogue dans PHP PDO https://bugs.php.net/bug.php?id=61613

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

ne renverra pas d'erreur ni ne retournera la valeur false (testé sur PHP 5.5.14). 

5
zstate

Une solution mise à jour de la solution de Plahcinski. Sinon, vous pouvez utiliser fopen et fread pour les fichiers plus volumineux:

$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 = '';
        }
    }
}
4
sanneo

Ma suggestion serait de regarder le code source de PHPMyBackup. C'est un chargeur automatique PHP SQL. Vous constaterez que mysql_query ne charge qu'une requête à la fois et que des projets tels que PHPMyAdmin et PHPMyBackup ont déjà effectué le travail difficile qui consiste à analyser correctement le code SQL. S'il vous plaît ne réinventez pas cette roue: P

4
SchizoDuckie

Fonctionne sur les décharges Navicat. Peut-être besoin de vider le premier/* */commentaire que navicat met dans.

$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 = "";
    }
  }
 }
3
Plahcinski
mysql_query("LOAD DATA LOCAL INFILE '/path/to/file' INTO TABLE mytable");
3
olle

Essaye ça:

// 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);
3
Neeraj Singh

Êtes-vous sûr que ce n'est pas une requête par ligne? Votre éditeur de texte est peut-être un saut de ligne, mais en réalité, chaque requête peut être sur une seule ligne.

Quoi qu'il en soit, la méthode de Olle semble la meilleure. Si vous avez des raisons d'exécuter des requêtes une par une, vous devriez pouvoir lire votre fichier ligne par ligne, puis utiliser le point-virgule à la fin de chaque requête pour délimiter. Vous feriez bien mieux de lire dans un fichier ligne par ligne plutôt que d’essayer de scinder une énorme chaîne, car elle serait beaucoup plus douce pour la mémoire de votre serveur. Exemple:

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

Évidemment, vous devrez tenir compte des transactions et du reste si vous exécutez un grand nombre de requêtes dans un lot, mais ce n'est probablement pas un gros problème pour un nouveau script d'installation.

3
cam8001

En bref, voici comment je l'ai fait:

  1. Lire le fichier (un db dump, par exemple $ mysqldump db > db.sql)

    $sql = file_get_contents(db.sql);
    
  2. Importez-le en utilisant mysqli :: multi_query

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

Attention, mysqli_query prend en charge les requêtes asynchrones. Plus ici: http://php.net/manual/en/mysqli.multi-query.php et ici https://stackoverflow.com/a/6652908/2002493

3
Portmanteau

Sauf si vous envisagez d'importer des fichiers huge .sql, il suffit de lire l'intégralité du fichier en mémoire et de l'exécuter en tant que requête.

Cela fait longtemps que je n’utilise pas PHP, donc pseudo-code:

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

Si les fichiers ne sont pas volumineux (par exemple, sur plusieurs mégaoctets), il n’ya aucune raison de l’exécuter ligne à la fois ou de tenter de le scinder en plusieurs requêtes (en scindant avec ;, ce qui, comme je le commentais sur la réponse de cam8001, break si la requête a des points-virgules dans des chaînes) ..

2
dbr

Le meilleur code pour la restauration SQL par PHP peut utiliser 100% Goooood! Merci beaucoup 

$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 = "";
  }
 }
}
2
Ricky

Le moyen le plus simple et le plus rapide de charger et d’analyser phpmyadmin dump du fichier mysql dump.

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

Juste pour reformuler le problème pour tout le monde:

Mysql_query, PHP, finit automatiquement par délimiter chaque commande SQL, et est en outre très vague dans son manuel. Tout ce qui dépasse une commande produira une erreur.

Par ailleurs, mysql_query convient parfaitement avec une chaîne contenant des commentaires de style SQL,\n,\r ..

La limitation de mysql_query se révèle en ce que l’analyseur SQL rapporte le problème directement à la commande suivante, par exemple.

 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...

Voici une solution rapide: (En supposant que le SQL soit bien formaté;

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

Aucune des solutions que j'ai vues ici ne concerne la nécessité de modifier le délimiteur lors de la création d'une procédure stockée sur un serveur où je ne peux pas compter sur l'accès à LOAD DATA INFILE. J'espérais trouver que quelqu'un avait déjà résolu ce problème sans avoir à parcourir le code phpMyAdmin pour le résoudre. Comme d’autres, j’étais moi aussi en train de rechercher le moyen de le faire sous licence GPL, puisque j’écris moi-même le code GPL.

1
K B

Certaines bibliothèques PHP peuvent analyser un fichier SQL composé de plusieurs instructions SQL, l'exploser correctement (sans utiliser un simple ";" exploser naturellement), puis les exécuter. 

Par exemple, vérifiez Phing 's PDOSQLExecTask

1
Francois Zaninotto

De nombreux hôtes ne vous permettront pas de créer votre propre base de données via PHP, mais vous semblez avoir résolu le problème.
Une fois la base de données créée, vous pouvez la manipuler et la remplir simplement:

mysql_connect ("localhost");
mysql_query ("SOURCE fichier.sql");

1
SamGoody

Cela peut être utile ->

Plus ou moins, il faut d'abord prendre la chaîne donnée à la fonction (la valeur file_get_contents () de votre file.sql) et supprimer tous les sauts de ligne. Ensuite, il divise les données en ";" personnage. Ensuite, il passe dans une boucle while en examinant chaque ligne du tableau créé. Si la ligne contient le caractère "` ", il saura qu'il s'agit d'une requête et déterminera la fonction myquery () pour les données de la ligne donnée.

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);
1
White Rabbit

Certains gars (Plahcinski) ont suggéré ce code:

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

mais je voudrais le mettre à jour avec celui qui a fonctionné pour moi:

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

parce que c'est plus complet. ;-)

1
Darius Miliauskas

Cela provient d'un projet sur lequel je travaille. Fondamentalement, prend tout fichier texte et extrait les instructions SQL en ignorant les commentaires et les sauts de ligne gratuits.

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

?>
0
Dave H.

J'ai un environnement où aucun outil mysql ou phpmyadmin ne concerne que mon application php se connectant à un serveur mysql sur un hôte différent, mais je dois exécuter des scripts exportés par mysqldump ou myadmin. Pour résoudre le problème, j’ai créé un script multi_query comme je l’ai mentionné ici

Il peut traiter les sorties mysqldump et les exportations phpmyadmin sans l'outil de ligne de commande mysql. J'ai également créé une logique pour traiter plusieurs fichiers de migration en fonction de l'horodatage stocké dans la base de données, comme Rails. Je sais que cela nécessite plus de traitement des erreurs, mais fait actuellement le travail pour moi.

Découvrez-le: https://github.com/kepes/php-migration

C'est du php pur et ne nécessite aucun autre outil. Si vous ne traitez pas les entrées utilisateur avec uniquement des scripts créés par des développeurs ou des outils d'exportation, vous pouvez les utiliser en toute sécurité.

0
kepes

Pourquoi ne pas prendre le code de phpMyAdmin et l'utiliser? C'est Open Source après tout ...

0
Mez

cela a réellement fonctionné pour moi:

/* 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;
}
?>
0
canoodle

J'ai remarqué que le pilote PDO PostgreSQL ne vous permettait pas d'exécuter des scripts séparés par des points-virgules. Pour pouvoir exécuter un fichier .sql sur n’importe quelle base de données utilisant PDO, il est nécessaire de scinder vous-même les instructions en code PHP. Voici une solution qui semble fonctionner assez bien:

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

La classe référencée a fait le tour pour moi d'une manière indépendante de la base de données, veuillez m'envoyer un message en cas de problème. Voici comment vous pouvez utiliser le script après l'avoir ajouté à votre projet:

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

J'espère que le code suivant résoudra assez bien votre problème.

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

?>
0
Vijin Paulraj

Je l'utilise tout le temps:

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

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