Запуск MySQL * .sql файлов в PHP - PullRequest
       24

Запуск MySQL * .sql файлов в PHP

44 голосов
/ 27 октября 2010

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

Дополнительная информация

  1. У меня нет доступа к консоли
  2. Iпытаюсь автоматизировать создание сайта из нашего приложения.

РЕШЕНИЕ

Использование shell_exec() ...

$command = 'mysql'
        . ' --host=' . $vals['db_host']
        . ' --user=' . $vals['db_user']
        . ' --password=' . $vals['db_pass']
        . ' --database=' . $vals['db_name']
        . ' --execute="SOURCE ' . $script_path
;
$output1 = shell_exec($command . '/site_db.sql"');
$output2 = shell_exec($command . '/site_structure.sql"');

... Я никогда не получал полезного вывода, но следовал некоторым предложениям на другом потоке и, наконец, все заработало.Я переключаюсь в формат --option=value для команд и использую --execute="SOURCE ..." вместо < для выполнения файла.

Кроме того, я никогда не получал хорошего объяснения разницы между shell_exec() и exec().

Ответы [ 12 ]

41 голосов
/ 27 октября 2010

Этот вопрос время от времени возникает. Нет хорошего решения для запуска скрипта .sql напрямую из PHP. Существуют крайние случаи, когда операторы, общие в сценарии .sql, не могут быть выполнены как операторы SQL. Например, инструмент mysql имеет встроенные команды , которые не распознаются MySQL Server, например CONNECT, TEE, STATUS и DELIMITER.

Так что я даю +1 к ответу @Ignacio Vazquez-Abrams . Вам следует запустить скрипт .sql на PHP, вызвав инструмент mysql, например, с shell_exec().


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

$command = "mysql --user={$vals['db_user']} --password='{$vals['db_pass']}' "
 . "-h {$vals['db_host']} -D {$vals['db_name']} < {$script_path}";

$output = shell_exec($command . '/shellexec.sql');

Смотрите также мои ответы на следующие вопросы:

18 голосов
/ 19 апреля 2013
$commands = file_get_contents($location);   
$this->_connection->multi_query($commands);
14 голосов
/ 18 апреля 2012

Вот что я использую:


function run_sql_file($location){
    //load file
    $commands = file_get_contents($location);

    //delete comments
    $lines = explode("\n",$commands);
    $commands = '';
    foreach($lines as $line){
        $line = trim($line);
        if( $line && !startsWith($line,'--') ){
            $commands .= $line . "\n";
        }
    }

    //convert to array
    $commands = explode(";", $commands);

    //run commands
    $total = $success = 0;
    foreach($commands as $command){
        if(trim($command)){
            $success += (@mysql_query($command)==false ? 0 : 1);
            $total += 1;
        }
    }

    //return number of successful queries and total number of queries found
    return array(
        "success" => $success,
        "total" => $total
    );
}


// Here's a startsWith function
function startsWith($haystack, $needle){
    $length = strlen($needle);
    return (substr($haystack, 0, $length) === $needle);
}
12 голосов
/ 27 октября 2010

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

6 голосов
/ 20 июня 2013

Я знаю, что довольно поздно на вечеринку, но PHP Mini Admin несколько раз спасал меня.По сути, это «облегченный» PHPMyAdmin, содержащийся в одном файле, поэтому нет необходимости в сложной установке, просто загрузите его и войдите в систему.

6 голосов
/ 08 декабря 2012

Мне никогда не приходилось его использовать, но у класса mysqli есть метод multi_query:

http://php.net/manual/en/mysqli.multi-query.php

2 голосов
/ 27 октября 2010

Не забудьте про phpMyAdmin . Довольно солидный интерфейс для взаимодействия с MySQL.

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

1 голос
/ 16 декабря 2017

Вы можете использовать этот скрипт для запуска файлов скриптов MySQL. Вам нужно будет установить $ hostName, $ userName, $ password, $ dataBaseName, $ port и $ fileName

<?php

function parseScript($script) {

  $result = array();
  $delimiter = ';';
  while(strlen($script) && preg_match('/((DELIMITER)[ ]+([^\n\r])|[' . $delimiter . ']|$)/is', $script, $matches, PREG_OFFSET_CAPTURE)) {
    if (count($matches) > 2) {
      $delimiter = $matches[3][0];
      $script = substr($script, $matches[3][1] + 1);
    } else {
      if (strlen($statement = trim(substr($script, 0, $matches[0][1])))) {
        $result[] = $statement;
      }
      $script = substr($script, $matches[0][1] + 1);
    }
  }

  return $result;

}

function executeScriptFile($fileName, $dbConnection) {
  $script = file_get_contents($scriptFleName);
  $statements = parseScript($script);
  foreach($statements as $statement) {
    mysqli_query($dbConnection, $statement);
  }
}

$hostName = '';
$userName = '';
$password = '';
$dataBaseName = '';
$port = '';
$fileName = '';

if ($connection = @mysqli_connect($hostName, $userName, $password, $dataBaseName, $port)) {
  executeScriptFile($fileName, $connection);
} else {
  die('Can not connect to MySQL');
}
1 голос
/ 20 января 2015

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

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

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

0 голосов
/ 28 мая 2018

Вот мое решение, и приведенный ниже код объясняет, что делает.Принцип заключается в том, чтобы прочитать файл построчно, построить запрос и выполнить каждый из них.Я видел много решений, использующих «file_get_contents», который не является хорошим решением, потому что он может вызвать проблему с буфером, поскольку он читает все содержимое файла в строковую переменную.Мое решение также учитывает запросы TRIGGER.Нет выделения массива, комментарии и пустые строки удаляются.

<?php
 /**
 * Get a connection from database
 * @param type $db_host database hostname
 * @param type $db_user database username
 * @param type $db_password database password
 * @param type $db_name database name
 * @return \PDO
 */
 function get_db_connection($db_host, $db_user, $db_password, $db_name)
{
    $dns = "mysql:host=$db_host;dbname=$db_name";
    try
    {
        return new PDO($dns, $db_user, $db_password);
    } catch (PDOException $ex)
    {
        return null;
    }
}

/**
 * Runs SQL queries from file
 */

 function exec_sql_queries_from_file($script_file, $db_host, $db_user, $db_password, $db_name)
{
    // to increase the default PHP execution time
    set_time_limit ( 60 ); // Max time = 60 seconds

    // Connect to database
    $connection = get_db_connection($db_host, $db_user, $db_password, $db_name);

    // If the connection is acquired
    if($connection != null){

        // Open sql file
        $f = fopen($script_file, 'r');

        // sql query
        $query = '';

        // Default delimiter for queries
        $delimiter = ';';

        // read line by line
        while (!feof($f))
        {           
            $line = str_replace(PHP_EOL, '', fgets($f)); // read a line and remove the end of line character

            /* if the current line contains the key word 'DELIMITER'. Ex: DELIMITER ;; or DELIMITER $$
             * mostly used for TRIGGERS' queries
             */
            if(strpos($line, 'DELIMITER') !== false)
            {
                // change the delimiter and read the next line
                $delimiter = str_replace('DELIMITER ', '', $line);
                continue;
            }   

            // Consider the line as part of a query if it's not empty and it's not a comment line
            if (!empty($line) && !starts_with($line, '/*') && !starts_with($line, '--'))
            {
                // the query hasn't reach its end: concatenate $line to $query if $line is not a delimiter
                $query .= $line !== $delimiter ? $line : '';

                // if the current line ends with $delimiter: end of current query
                if (ends_with($line, $delimiter))
                {                
                    // exec the query
                    $connection->exec($query) or die($connection->errorInfo());
                    // start new query
                    $query = '';
                }
            }                    
        }

        fclose($f);
    }
}

 /**
 * Starts with function
 */
function starts_with($haystack, $needle)
{
    return $haystack{0} === $needle{0} ? stripos($haystack, $needle) === 0 : false;
}

/**
 * Ends with function
 */
function ends_with($haystack, $needle)
{
    $pos = stripos($haystack, $needle);
    return $pos === FALSE ? FALSE : substr($haystack, $pos) === $needle;

}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...