MySQL statement that returns a SQL statement? - php

I need to do a dump of a table on a remote server, but I can't access the server directly. The only access I have is through PHP scripts.
Is there some way in which MySQL will return an
INSERT INTO `table_name` (`field1`, `field2`) VALUES ('a', 'b'), ('c', 'd')
statement, like what mysqldump will return?
I don't have access to phpMyAdmin, and I preferably don't want to use exec, system or passthru.
See this question for another export method

1) can you run mysqldump from exec or passthru
2) take a look at this: http://www.php-mysql-tutorial.com/perform-mysql-backup-php.php

If you can use php-scripts on the server i would recommend phpmyadmin. Then you can do this from the web-interface.

You should check out PHPMyAdmin, it is a php based MySQL administration tool. It supports backups and recovery for the database as well as a 'GUI' to the database server. It works very well.

I'm pretty sure phpMyAdmin will do this for you.

This
select 'insert into table table_name (field1, field2) values'
|| table_name.field1 || ', ' || table_field2 || ');'
from table_name
should get you started. Replace || with the string concatenation operator for your db flavour. If field1 or field2 are strings you will have to come up with some trick for quoting/escaping.

Here is one approach generating a lot of separate query statements. You can also use implode to more efficiently combine the strings, but this is easier to read for starters and derived from this you can come up with a million other approaches.
$results = mysql_query("SELECT * FROM `table_name`");
while($row = mysql_fetch_assoc($results)) {
$query = "INSERT INTO `table_name` ";
$fields = '(';
$values = '(';
foreach($row as $field=>$value) {
$fields .= "'".$field."',";
$values .= "'".mysql_escape_string($value)."',";
}
//drop the last comma off
$fields = substr($fields,0,-1);
$values = substr($values,0,-1);
$query .= $fields . " VALUES " . $values;
//your final result
echo $query;
}
See if that gets you started

Related

php insert data from fetch array to other table on version 5.4

I have moved to IIS 8 in PHP 5.4. I am trying to collect data from a table and insert them to a different one, i know my code is correct, but seems to be not working, probably because of the php version, can anyone help me?
here's my code
$query = odbc_exec($conn, "SELECT * FROM member");
while($rows = odbc_fetch_array($query)) {
$querystring = "INSERT INTO oldusers (username, password, regdate) VALUES ('$rows['userid']', '$rows['passwd']', '$rows['registdate']')";
$query2 = odbc_exec($conn, $querystring);
odbc_free_result($query2);
//echo $rows['userid']." ".$rows['passwd']." ".$rows['registdate']."<br>";
}
thanks in advance.
instead trying to insert one by one record, better to insert like below:
INSERT INTO oldusers (username, password, regdate) SELECT userid,passwd,registdate FROM member
for more information :http://dev.mysql.com/doc/refman/5.5/en/insert-select.html
You're placing $rows['passwd'] inside of a double-quoted string. Instead you should do:
$str = "some sql $rows[passwd] rest of sql"; // notice the absence of single quotes
or:
$str = "some sql {$rows['passwd']} rest of sql";
or (I think this way is most readable):
$str = 'some sql' . $rows[passwd] . ' rest of sql';
If your column contains text you'll need to add surrounding single quotes where necessary.
Having said all that, you should instead use parameterized queries (if your database supports it) as it's safer (from SQL injection). If that's unavailable you will at the very least need to escape the data before concatenating it to the string.

insert into. while loop, mysql

I'm new one in php, and I have a question.
$result = mssql_query('stored proc. with some parameters');
while ($row = mssql_fetch_row($result)){
mysqli_query('INSERT INTO dbname VALUES ($row[0], $row[1], ... , $row[15] );') or die ('Insertion mistake.');
}
The problem is, I've got die() exception after ~430 insertions. The size of $result query can be up to 100.000 results. I cannot access the MS base and touch stored procedures, and this data transfer in needable. Can somebody help me, with a solution, or show the place, I can read more about that kind of problem?
Creating a single query might be faster.
$result = mssql_query('stored proc. with some parameters');
$query = '';
while ($row = mssql_fetch_row($result)){
$query .= "INSERT INTO dbname VALUES ($row[0], $row[1], ... , $row[15]),";
}
mysqli_query($query) or die('Insertion mistake.');
Ore better this I think:
while ($row = mssql_fetch_row($result)){
$values = "({$row[0]}, {$row[1]}, ... , {$row[15]})";
}
$query = 'INSERT INTO dbname VALUES ' . implode(',', $values);
mysqli_query($query) or die('Insertion mistake.');
And I didn't show it, but you need to run the data $row[0], etc... through mysqli_real_escape_string() before inserting.
Also, in the query, you need to quote the data that is not destined for a numeric column type: '{$row[0]}' etc. if it is text.
I think you are running out of memory. You can add to the top of the script:
ini_set('memory_limit','512M');
This will set the maximum memory limit for your script to 512MB.
You can also try to change memory_limitat php.ini

Backing up MySQL DB... Proper way to escape strings?

So I am backing up my DB with the following code:
$rows = $this->_getDb()->fetchAll("SELECT * FROM $table");
foreach ($rows AS $row)
{
foreach ($row AS &$value)
{
if (!is_numeric($value))
{
$value = "'".addcslashes($value, "'\\")."'";
$value = str_replace("\n", '\n', $value);
}
}
if (!$count)
{
$output .= "INSERT INTO `$table` (" .implode(', ', $columns). ") VALUES";
}
$count++;
$output .= "\n(" .implode(', ', $row). "),";
if ($count >= $limit)
{
$count = 0;
$output = preg_replace('#,$#', ";\n\n", $output);
}
}
$output = preg_replace('#,$#', ";\n\n", $output);
This seems to be working great... But I'm comparing my output to what I get from a PHPMyAdmin and I'm noticing some slight differences. With my code, because of how I am using addcslashes, if a string contains a ' it will escape it with \'. However, in the output from PHPMyAdmin, it will instead replace a single ' with two single quotes '' in a row.
Is there really a difference? Please look at the way I am escaping non-numeric fields and tell me if there is a better way.
The method of two single-quotes in a row '' is more standard SQL, so it is more portable.
Even MySQL supports a SQL_MODE called NO_BACKSLASH_ESCAPES that would make your backslash-treated strings invalid if you try to import the backup to a server with that mode enabled.
But I have to add comments to make it clear that your method of backing up your database is full of other problems.
You don't handle NULLs:
if (!is_numeric($value))
This does not handle column names that need to be delimited because they may conflict with SQL reserved words:
$output .= "INSERT INTO `$table` (" .implode(', ', $columns). ") VALUES";
If you have millions of rows in any of your tabes, trying to store the entire content of that table in the form of a series of INSERT statements in a single string will exceed PHP's max memory limit:
$output .= "\n(" .implode(', ', $row). "),";
You only show part of your script, but it may also not properly handle binary strings, character sets, triggers, stored routines, views, table options, etc.
You are really reinventing the wheel.
I've seen past questions where people attempt to do what you're doing, but it's difficult to get right:
PHP Database Dump Script - are there any issues?
Why is my database backup script not working in php?
It will be a much better use of your time to just use shell_exec() from PHP to call mysqldump or mydumper.

SQL statement inside loop with PHP, good idea?

I ran into the following question while writing a PHP script. I need to store the first two integers from an array of variable lenght into a database table, remove them and repeat this until the array is empty. I could do it with a while loop, but I read that you should avoid writing SQL statements inside a loop because of the performance hit.
A simpliefied example:
while(count($array) > 0){
if ($sql = $db_connect->prepare("INSERT INTO table (number1, number2) VALUES (?,?)")){
$sql->bind_param('ii',$array[0],$array[1]);
$sql->execute();
$sql->close();
}
array_shift($array);
array_shift($array);
}
Is this the best way, and if not, what's a better approach?
You can do something like this, which is way faster aswell:
Psuedo code:
$stack = array();
while(count($array) > 0){
array_push($stack, "(" . $array[0] . ", " . $array[1] . ")");
array_shift($array);
array_shift($array);
}
if ($sql = $db_connect->prepare("INSERT INTO table (number1, number2)
VALUES " . implode(',', $stack))){
$sql->execute();
$sql->close();
}
The only issue here is that it's not a "MySQL Safe" insert, you will need to fix that!
This will generate and Array that holds the values. Within 1 query it will insert all values at once, where you need less MySQL time.
Whether you run them one by one or in an array, an INSERT statement is not going to make a noticeable performance hit, from my experience.
The database connection is only opened once, so it is not a huge issue. I guess if you are doing some insane amount of queries, it could be.
I think as long as your loop condition is safe ( will break in time ) and you got something from it .. it's ok
You would be better off writing a bulk insert statement, less hits on mysql
$sql = "INSERT INTO table(number1, number2) VALUES";
$params = array();
foreach( $array as $item ) {
$sql .= "(?,?),\n";
$params[] = $item;
}
$sql = rtrim( $sql, ",\n" ) . ';';
$sql = $db_connect->prepare( $sql );
foreach( $params as $param ) {
$sql->bind_param( 'ii', $param[ 0 ], $param[ 1 ] );
}
$sql->execute();
$sql->close();
In ColdFusion you can put your loop inside the query instead of the other way around. I'm not a php programmer but my general belief is that most things that can be done in language a can also be done in language b. This code shows the concept. You should be able to figure out a php version.
<cfquery>
insert into mytable
(field1, field2)
select null, null
from SomeSmallTable
where 1=2
<cfloop from="1' to="#arrayLen(myArray)#" index="i">
select <cfqueryparam value="myArray[i][1]
, <cfqueryparam value="myArray[i][]
from SomeSmallTable
</cfloop>
</cfquery>
When I've looked at this approach myself, I've found it to be faster than query inside loop with oracle and sql server. I found it to be slower with redbrick.
There is a limitation with this approach. Sql server has a maximum number of parameters it will accept and a maximum query length. Other db engines might as well, I've just not discovered them yet.

How to write a good PHP database insert using an associative array

In PHP, I want to insert into a database using data contained in a associative array of field/value pairs.
Example:
$_fields = array('field1'=>'value1','field2'=>'value2','field3'=>'value3');
The resulting SQL insert should look as follows:
INSERT INTO table (field1,field2,field3) VALUES ('value1','value2','value3');
I have come up with the following PHP one-liner:
mysql_query("INSERT INTO table (".implode(',',array_keys($_fields)).") VALUES (".implode(',',array_values($_fields)).")");
It separates the keys and values of the the associative array and implodes to generate a comma-separated string . The problem is that it does not escape or quote the values that were inserted into the database. To illustrate the danger, Imagine if $_fields contained the following:
$_fields = array('field1'=>"naustyvalue); drop table members; --");
The following SQL would be generated:
INSERT INTO table (field1) VALUES (naustyvalue); drop table members; --;
Luckily, multiple queries are not supported, nevertheless quoting and escaping are essential to prevent SQL injection vulnerabilities.
How do you write your PHP Mysql Inserts?
Note: PDO or mysqli prepared queries aren't currently an option for me because the codebase already uses mysql extensively - a change is planned but it'd take alot of resources to convert?
The only thing i would change would be to use sprintf for readability purposes
$sql = sprintf(
'INSERT INTO table (%s) VALUES ("%s")',
implode(',',array_keys($_fields)),
implode('","',array_values($_fields))
);
mysql_query($sql);
and make sure the values are escaped.
Nothing wrong with that. I do the same.
But make sure you mysql_escape() and quote the values you stick in the query, otherwise you're looking at SQL injection vulnerability.
Alternately, you could use parametrized queries, in which case you can practically pass the array in itself, instead of building a query string.
The best practice is either to use an ORM (Doctrine 2.0), an ActiveRecord implementation (Doctrine 1.0, RedBean), or a TableGateway pattern implementation (Zend_Db_Table, Propel). These tools will make your life a lot easier, and handle a lot of the heavy lifting for you, and can help protect you from SQL injections.
Other than that, there's nothing inherently wrong with what you're doing, you just might want to abstract it away into a class or a function, so that you can repeat the functionality in different places.
Using the sprintf trick mentioned by Galen in a previous answer, I have come up with the following code:
$escapedfieldValues = array_map(create_function('$e', 'return mysql_real_escape_string(((get_magic_quotes_gpc()) ? stripslashes($e) : $e));'), array_values($_fields));
$sql = sprintf('INSERT INTO table (%s) VALUES ("%s")', implode(',',array_keys($_fields)), implode('"," ',$escapedfieldValues));
mysql_query($sql);
It generates a escaped and quoted insert. It also copes independent of whether magic_quotes_gpc is on or off. The code could be nicer if I used new PHP v5.3.0 anonymous functions but I need it to run on older PHP installations.
This code is a bit longer that the original (and slower) but it is more secure.
I use this to retrieve the VALUES part of the INSERT.
But it might be an absurd way to do things. Comments/suggestions are welcome.
function arrayToSqlValues($array)
{
$sql = "";
foreach($array as $val)
{
//adding value
if($val === NULL)
$sql .= "NULL";
else
/*
useless piece of code see comments
if($val === FALSE)
$sql .= "FALSE";
else
*/
$sql .= "'" . addslashes($val) . "'";
$sql .= ", ";
};
return "VALUES(" . rtrim($sql, " ,") . ")";
}
There is a problem with NULL (in the accepted answer) values being converted to empty string "". So this is fix, NULL becomes NULL without quotes:
function implode_sql_values($vals)
{
$s = '';
foreach ($vals as $v)
$s .= ','.(($v===NULL)?'NULL':'"'.mysql_real_escape_string($v).'"');
return substr($s, 1);
}
Usage:
implode_sql_values(array_values( array('id'=>1, 'nick'=>'bla', 'fbid'=>NULL) ));
// =='"1","bla",NULL'
If you want to enhance your approach and add the possibility for input validation and sanitation, you might want to do this:
function insertarray($table, $arr){
foreach($arr as $k => $v){
$col[] = sanitize($k);
$val[] = "'".sanitize($v)."'";
}
query('INSERT INTO '.sanitize($table).' ('.implode(', ', $col).') VALUES ('.implode(', ', $val).')' );
}

Categories