Reputation: 8326
I have two *.sql
files that I use when creating a new web site database. The first file creates all the tables. The second file populates some default records. I would like to execute these files from PHP. I also use the Zend_Framework, if that will help accomplish this.
Additional Info
SOLUTION
Using 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"');
...I never did get useful output, but followed some suggestions on another thread and finally got it all working. I switch to the --option=value
format for the commands and used --execute="SOURCE ..."
instead of <
to execute the file.
Also, I never got a good explanation of the difference between shell_exec()
and exec()
.
Upvotes: 56
Views: 117738
Reputation: 166
I found the easy solution, that's works for me
$new_conn=mysqli_connect("localhost","db_user","pass","db_name");
$quries=file_get_contents("db_backup.sql");
$res=mysqli_multi_query($new_conn,$quries);
Upvotes: 0
Reputation: 793
Just wanna to add to @Bill Karwin answer given above.
You can import | reinitialize | execute custom SQL; the database using sql script file, by simply clicking on button. That button would execute the sql script file using ajax.
eg.
Front end code
<input type="button" value="Execute SQL Script" id="btnExecuteScript" />
<input type="button" value="reset" onclick="clearDiv('divExecuteScript')" />
<div id="divExecuteScript" style='display: none'></div>
<br />
Jquery code calling the ajax
$('#btnExecuteScript').click(function (event) {
if ($('#divExecuteScript').html() == '') {
$('#divExecuteScript').html("<b style='font-family: sans-serif;font-size: larger'>Please Wait, It might take a few minutes</b>");
$('#divExecuteScript').show();
$.get("../controller/Controller.php?executeScript=TRUE", function (data) {
// alert("$" + data + "$");
$('body').css('cursor', 'default');
$('#divExecuteScript').html(data);
$('#divExecuteScript').show();
});
} else
$('#divExecuteScript').toggle();
});
connection file
class Conn {
protected $databaseURL; // const
protected $databaseName;
protected $databaseUName;
protected $databasePWord;
public $mysqli;
public function __construct($args = null) {
if (stripos($_SERVER['SERVER_NAME'], "localhost") !== FALSE) {
$this->databaseURL = "host";
$this->databaseName = "database";
$this->databaseUName = "user";
$this->databasePWord = "password";
}
$this->mysqli = new mysqli($this->databaseURL, $this->databaseUName, $this->databasePWord, $this->databaseName) or die('Could not connect to the database server' . mysqli_connect_error());
if (empty($this->mysqli))
die("Error while connecting to host");
}
function get_databaseURL() {
return $this->databaseURL;
}
function get_databaseUName() {
return $this->databaseUName;
}
function get_databasePWord() {
return $this->databasePWord;
}
function get_databaseName() {
return $this->databaseName;
}
}
controller code executing the command
$con = new Conn();
$mysqli = new mysqli($con->get_databaseURL(), $con->get_databaseUName(), $con->get_databasePWord(), $con->get_databaseName()) or die('Could not connect to the database server' . mysqli_connect_error());
if (isset($_GET['executeScript'])) {
$script_path = '/path-to-script-file/filename.sql';
$command = "mysql --user={$con->get_databaseUName()} --password='{$con->get_databasePWord()}' "
. "-h {$con->get_databaseURL()} -D {$con->get_databaseName()} < {$script_path}";
$output = shell_exec($command);
if (!empty($output))
echo "<b style='font-family: sans-serif;font-size: large'>Execute the SQL script<br />";
else
echo "<b style='font-family: sans-serif;font-size: large'>Unable to execute the SQL script</b><br />";
return;
}
Upvotes: -1
Reputation: 562230
This question comes up from time to time. There's no good solution for running a .sql script directly from PHP. There are edge cases where statements common in a .sql script can't be executed as SQL statements. For example, the mysql tool has builtin commands that are not recognized by the MySQL Server, e.g. CONNECT
, TEE
, STATUS
, and DELIMITER
.
So I give +1 to @Ignacio Vazquez-Abrams's answer. You should run your .sql script in PHP by invoking the mysql
tool, for instance with shell_exec()
.
I got this test working:
$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');
See also my answers to these related questions:
Upvotes: 53
Reputation: 677
Here is my solution and the below code explains what is does. The principle is to read the file line by line, build a query and execute each of them. I saw many solutions using the "file_get_contents" which is not a good solution because it could cause a buffer issue as it read the whole file contents to string variable. My solution takes also into account TRIGGERs' queries. There's no array allocation, comment and empty lines are stripped.
<?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;
}
Upvotes: 1
Reputation: 39
You can use this script to run MySQL script files. You'll need to set $hostName, $userName, $password, $dataBaseName, $port and $fileName of course.
<?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');
}
Upvotes: 2
Reputation: 69
To execute table generation from within the application, you may want to create a php file that will do just that when you run it.
$hostname = "localhost";
$database = "databasename";
$username = "rootuser";
$UserPassword = "password";
$myconnection = mysql_pconnect($hostname, $username , $UserPassword) or trigger_error(mysql_error(),E_USER_ERROR);
mysql_connect($hostname , $username , $UserPassword ) or die(mysql_error());
mysql_select_db($database) or die(mysql_error());
if ( !$myconnection ){ echo "Error connecting to database.\n";}
$userstableDrop = " DROP TABLE IF EXISTS `users`";
$userstableCreate = " CREATE TABLE IF NOT EXISTS `users` (
`UserID` int(11) NOT NULL,
`User_First_Name` varchar(50) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=15" ;
$userstableInsert = "INSERT INTO `users` (`UserID`, `User_First_Name`) VALUES
(1, 'Mathew'),
(2, 'Joseph'),
(3, 'James'),
(4, 'Mary')";
$userstableAlter1 = "ALTER TABLE `users` ADD PRIMARY KEY (`UserID`)";
$userstableAlter2 = " ALTER TABLE `users` MODIFY `UserID` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=15";
$createDb_sql = $userstableDrop;
$insertSite = mysql_query($createDb_sql);
$createDb_sql = $userstableCreate;
$insertSite = mysql_query($createDb_sql);
$createDb_sql = $userstableInsert;
$insertSite = mysql_query($createDb_sql);
$createDb_sql = $userstableAlter1;
$insertSite = mysql_query($createDb_sql);
$createDb_sql = $userstableAlter2;
$insertSite = mysql_query($createDb_sql);
echo "Succesful!";
mysql_close($myconnection );
Upvotes: 0
Reputation: 12725
$commands = file_get_contents($location);
$this->_connection->multi_query($commands);
Upvotes: 25
Reputation: 800
I created a migration script with multi_query
. It can process mysqldump output and phpmyadmin exports without mysql command line tool. I also made some logic to process multiple migration files based on timestamp stored in DB like Rails. I know it needs more error handling but currently does the work for me.
Check it out: https://github.com/kepes/php-migration
I think if you don't process user input with it only scripts made by developers or export tools you can use it safely.
Upvotes: 1
Reputation: 9443
I know I'm pretty late to the party but PHP Mini Admin has been a lifesaver on a couple of occasions. It's basically a "lite" PHPMyAdmin all contained in one file so no need for complicated installs, just upload it and log in. Simples!
Upvotes: 6
Reputation: 1228
Here is what I use:
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);
}
Upvotes: 13
Reputation: 89
I have never had to use it but the mysqli class has a multi_query method:
http://php.net/manual/en/mysqli.multi-query.php
Upvotes: 8
Reputation: 21085
Don't forget about phpMyAdmin. Pretty solid interface for interacting with MySQL.
I don't know if it solves your problem, since I don't know if you can interact with it directly from code, but just wanted to throw it out there.
Upvotes: 2
Reputation: 877
One suggestion:
// connect to db.
if (mysql_query("SOURCE myfile.sql")) {
echo "Hello Sonny";
}
Upvotes: -2
Reputation: 798456
You'll need to create a full SQL parser for this. I recommend you use the mysql
command line tool for this instead, invoking it externally from PHP.
Upvotes: 15