開発中のアプリケーションのインストールスクリプトを作成しており、PHP内からデータベースを動的に作成する必要があります。データベースを作成するためにそれを手に入れましたが、今ではいくつかの.sqlファイルをロードする必要があります。ファイルを開き、mysql_queryを一度に1行ずつ開くことを計画していました-スキーマファイルを見て、それらが1行につき1つのクエリではないことに気付くまで。
では、PHP(phpMyAdminがインポートコマンドで行うように)内からsqlファイルをロードするにはどうすればよいですか?
この質問に答えた誰もが、自分のサーバーにアプリケーションをインストールすることを許可するWebアプリケーション開発者になるのがどんなものか知らないように感じています。特に、共有ホスティングでは、前述の「LOAD DATA」クエリのようなSQLを使用できません。ほとんどの共有ホストでは、Shell_execの使用も許可されていません。
さて、OPに答えるために、あなたの最善の策は、変数にクエリを含み、それらを実行することができるPHPファイルを構築することです。sqlファイルを解析することに決めた場合phpMyAdminを調べて、そのように.sqlファイルからデータを取得するためのアイデアを得る必要があります。インストーラーがある他のWebアプリケーションを見てみると、クエリに.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 : [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 < $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 < $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 < $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("/(?<!\\\\)(\\\\\\\\)*\\\\'/", $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 < $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("/(?<!\\\\)(\\\\\\\\)*\\\\'/", $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()を使用して、SQLスクリプトを入力としてmysqlクライアントを実行することです。フォークする必要があるため、これは少し遅くなる場合がありますが、数分でコードを記述してから、有用な作業に戻ることができます。 PHPスクリプトを記述してSQLスクリプトを実行するには、数週間かかる場合があります。
スクリプトにスクリプトの機能のサブセットのみが含まれていることが確実でない限り、SQLスクリプトのサポートは、ここで説明しているものよりも複雑です。以下に、通常のSQLスクリプトに現れる可能性のあるいくつかの例を示します。これにより、スクリプトを1行ずつ解釈するようにコーディングすることが複雑になります。
-- 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スクリプトのサブセットのみをサポートする場合、ファイルを読み取り、ファイル内のSQLステートメントを実行するPHPスクリプトを書くのは比較的簡単です。有効なSQLスクリプトをサポートする場合、それははるかに複雑です。
これらの関連する質問に対する私の回答も参照してください。
私のプロジェクトでは、次のソリューションを使用しました。
<?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ファイル(41Mb)のメモリピーク使用量:3.25Mb
mysqli
は、_;
_で区切られた複数のクエリを実行できます
mysqli_multi_query()
を使用して、ファイル全体を読み込んで一度に実行できます。
しかし、私はこれが最もエレガントなソリューションではないと最初に言います。
私は答えにコメントできないので、次の解決策を使用するように注意してください。
$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=6161 にバグがあります
db->exec('SELECT 1; invalidstatement; SELECT 2');
エラーまたはfalseを返しません(PHP 5.5.14でテスト済み)。
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 = '';
}
}
}
私の提案は、PHPMyBackupのソースコードを調べることです。これは自動化されたPHP SQLローダーです。mysql_queryは一度に1つのクエリのみをロードし、PHPMyAdminやPHPMyBackupのようなプロジェクトはSQLを正しい方法で解析するためのハードワークをすでに行っています。 。その車輪を再発明しないでください:P
1行に1つのクエリではありませんか?テキストエディタは行を折り返している場合がありますが、実際には各クエリは1行になっている場合があります。
とにかく、olleの方法が最適のようです。クエリを1つずつ実行する理由がある場合は、ファイルを1行ずつ読み取ってから、各クエリの最後にセミコロンを使用して区切ります。巨大な文字列を分割しようとするよりも、サーバーのメモリにはるかに優しいので、ファイルを1行ずつ読み込む方がはるかに優れています。例:
$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 = "";
}
}
}
mysql_query("LOAD DATA LOCAL INFILE '/path/to/file' INTO TABLE mytable");
これを試して:
// 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() > 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);
PostgreSQL PDOドライバーでは、セミコロンで区切られたスクリプトを実行できないことに気付きました。 PDOを使用して任意のデータベースで.sqlファイルを実行するには、ステートメントを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();
}
}
簡単に言うと、これを行った方法は次のとおりです。
ファイルを読み取ります(dbダンプ、たとえば$ mysqldump db > db.sql
)
$sql = file_get_contents(db.sql);
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/200249 =
huge .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()
ファイルが巨大(たとえば、数メガバイト以上)でない限り、一度に1行ずつ実行したり、複数のクエリに分割したり(;
は、私がcam8001の回答についてコメントしたように、クエリに文字列内にセミコロンが含まれていると壊れます)。
このphpによるsqlの復元に最適なコードは、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
皆のために問題を再度述べるために:
PHPのmysql_queryは、各SQLコマンドを自動的に区切ります。さらに、マニュアルではそうすることについて非常にあいまいです。 1つのコマンドを超えるものはすべてエラーになります。
もう一方の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);
私がここで見た解決策はどれも、LOAD DATA INFILEにアクセスできることを期待できないサーバーでストアドプロシージャを作成する際に、区切り文字を変更する必要があることに対処していません。誰かがこれを解決するためにphpMyAdminコードを調べなくても解決できることを望んでいました。他の人と同じように、私もGPLコードを自分で書いているので、私も他の誰かのGPL化されたやり方を探している最中でした。
いくつかのPHPライブラリは、複数のSQLステートメントで作成されたSQLファイルを解析し、適切に展開し(単純な ";"を使用せずに自然に展開)、実行できます。
たとえば、 Phing の PDOSQLExecTask を確認します
多くのホストでは、PHPを使用して独自のデータベースを作成することはできませんが、それを解決したようです。
DBが作成されたら、次のように操作してデータを追加できます。
mysql_connect( "localhost");
mysql_query( "SOURCE file.sql");
これは役に立つかもしれません->
多かれ少なかれ、最初に関数に与えられた文字列(file.sqlのfile_get_contents()値)を取得し、すべての改行を削除することです。次に、データを「;」で分割しますキャラクター。次に、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);
一部の人(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 = "";
}
}
}
より包括的だからです。 ;-)
これは私が取り組んでいるプロジェクトからのものです。基本的に任意のテキストファイルを取得し、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;
}
?>
Mysqlツールやphpmyadminが異なるホスト上のmysqlサーバーに接続するだけのphpアプリケーションではない環境がありますが、mysqldumpまたはmyadminによってエクスポートされたスクリプトを実行する必要があります。問題を解決するために、スクリプトを作成しましたmulti_query
私が言ったように ここ
Mysqlコマンドラインツールなしでmysqldump出力とphpmyadminエクスポートを処理できます。 RailsのようなDBに保存されているタイムスタンプに基づいて、複数の移行ファイルを処理するロジックも作成しました。私はそれがより多くのエラー処理を必要とすることを知っていますが、現在私のために仕事をしています。
チェックしてください: https://github.com/kepes/php-migration
純粋なphpであり、他のツールは必要ありません。開発者が作成したスクリプトまたはエクスポートツールのみでユーザー入力を処理しない場合は、安全に使用できます。
PhpMyAdminからコードを取得して使用してみませんか?結局のところ、それはオープンソースです...
これは実際に私のために働いた:
/* 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;
}
?>
次のコードが問題をかなり解決することを願っています。
//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 = '';
}
}
?>
私はこれを常に使用しています:
$sql = explode(";",file_get_contents('[your dump file].sql'));//
foreach($sql as $query)
mysql_query($query);