One of the websites I host still runs on PHP 5.2 with MySQL 4.0. Its text is in Hebrew (displays just fine on the site), but in the DB the text appears as gibberish containing question marks—but not exclusively. It looks some like: ?????£ ?§???¥ ???£ ?×???
I am trying to move this DB to MySQL 5.x with the same website, with no luck so far. I have tried using the MYSQL 40 compatibility mode, as well as other compatibility modes. I have made sure that the destination DB has the hebrew_bin collation as the old one, and I've played around with SET NAMES. The problem is, this is a type of gibberish I am not yet familiar with and therefore have no idea how to convert it to readable text.
I didn't get another answer here, and therefore had no choice but to write a simple script that manually does the migration process through PHP and not through MySQL dumps.
Here is the script, with some obvious modifications. Please note that the script is "dirty code", it might not be secure and it's not the most efficient, but it should get the job done if you're using it internally. Do not use in an environment where the script is accessible to the public without further modifications.
<?php
$local = mysqli_connect([source server], [source username], [source password], [source DB name]) or die('No local connection');
mysqli_query($local, "SET NAMES 'hebrew'");
$remote = mysqli_connect([destination server], [destination username], [destination password], [destination DB name]) or die('No remote connection');
mysqli_query($remote, "SET NAMES 'utf8'");
$table_list = array('table1', 'table2', 'table3'); // you can get a list of tables automatically too if the list is very long
foreach ($table_list as $table)
{
$query_local = "SELECT * FROM `{$table}`";
$result_local = mysqli_query($local, $query_local) or die('Error in q1: '.mysqli_error($local));
$delete_remote = mysqli_query($remote, "DELETE FROM `{$table}` WHERE 1") or die('Error deleting table: '.$table); // necessary only if you plan to run it more than once
$i = 0;
while ($row_local = mysqli_fetch_assoc($result_local))
{
foreach ($row_local as $key => $value)
$row_local[$key] = mysqli_real_escape_string($remote, $value);
$query_remote = "INSERT INTO `{$table}` (`".implode('`, `', array_keys($row_local))."`) VALUES ('".implode("', '", $row_local)."')";
$result_remote = mysqli_query($remote, $query_remote)
or die('Error in remote q'.$i.' in table '.$table.':<br /> '.mysqli_error($remote).'<br /> Query: '.$query_remote);
echo 'Successfully transferred row '.$i.' in table '.$table;
echo '<br />'.PHP_EOL;
$i++;
}
}
?>
Related
I am trying to import a file into a mariadb (mysql), database. A proof of concept file is in .json format on the web at this location. https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson
I know how to do this on db2 for i.
select * from JSON_TABLE(
SYSTOOLS.HTTPGETCLOB('https://earthquake.usgs.gov' ||
'/earthquakes/feed/v1.0/summary/all_week.geojson',null),
'$.features[*]'
COLUMNS( MILLISEC BIGINT PATH '$.properties.time',
MAG DOUBLE PATH '$.properties.mag',
PLACE VARCHAR(100) PATH '$.properties.place'
)) AS X;
This reads a from the web and lists 3 fields. Surrounding it with an insert clause will put it into a database file for me.
I would like to do exactly the same thing on my home server using mariadb. Ultimately a script will run unattended on a hosted server.
A .json segment of the earthquake data looks like this:
… "features":[
{"type":"Feature",
"properties":{
"mag":1.1,
"place":"58 km WNW of Anchor Point, Alaska",
"time":1640472257402,
"updated":1640472615410,
"tz":null,
"url":"https://earthquake.usgs.gov/earthquakes/eventpage/ak021gi3al5x",
"detail":"https://earthquake.usgs.gov/earthquakes/feed/v1.0/detail/ak021gi3al5x.geojson",
"felt":null,
"cdi":null,
"mmi":null,
"alert":null,
"status":"automatic",
"tsunami":0,
"sig":19,
"net":"ak",
"code":"021gi3al5x",
"ids":",ak021gi3al5x,",
"sources":",ak,",
"types":",origin,",
"nst":null,
"dmin":null,
"rms":0.79,
"gap":null,
"magType":"ml",
"type":"earthquake",
"title":"M 1.1 - 58 km WNW of Anchor Point, Alaska"},
"geometry":{
"type":"Point",
"coordinates":[-152.8406,59.9119,89.7]
},
"id":"ak021gi3al5x"
}, ...
Just a thought, but you could maybe just write a BASH script, e.g.
#!/bin/sh
cd "$(dirname "$0")"
export PATH=/bin:/usr/bin:/usr/local/bin
TODAY=`date +"%d%b%Y-%H%M"`
MYSQL_HOST='127.0.0.1'
MYSQL_PORT='3306'
MYSQL_USER='root'
MYSQL_PASSWORD='root'
url=https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson
DATA=$(curl ${url} 2>/dev/null)
printf '%s' "$DATA" | awk '{print $0}'
exit
...
...
...
and then use a tool like https://webinstall.dev/jq/, Python and whatever other tools you have on your system to extract the data that you want and then update the DB.
I am more familiar with PHP, which would work also. You could tidy that up a bit, but seems to work actually.
earthquake.php
<?php
$database = false;
try {
$options = array(PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ, PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING, PDO::ATTR_EMULATE_PREPARES => true );
$conn = new PDO('mysql:host=127.0.0.1;dbname=test;port=3306;charset=utf8','root','root', $options);
} catch (PDOException $e) {
// Echo custom message. Echo error code gives you some info.
echo '[{"error":"Database connection can not be estabilished. Please try again later. Error code: ' . $e->getCode() . '"}]';
exit;
}
$url = "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson";
$ch = curl_init();
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
$result = curl_exec($ch);
$features = json_decode($result)->features;
foreach ($features as $feature) {
echo 'Mag: '.$feature->properties->mag.', Place: '.$feature->properties->place.', '.gmdate("Y-m-d H:i:s", $feature->properties->time/1000).PHP_EOL;
$query = 'INSERT INTO features (mag, place, time) VALUES (?, ?, ?)';
$params = [$feature->properties->mag, $feature->properties->place, gmdate("Y-m-d H:i:s", $feature->properties->time/1000)];
$stmt = $conn->prepare($query) or die ('["status":{"error":"Prepare Statement Failure","query":"' .$query . '"}]');
$stmt->execute($params) or die('[{"error":"' . $stmt->errorInfo()[2] . '","query":"' .$query . '","params":' .json_encode($params) . '}]');
}
?>
create a local DB called features with mag, place and time columns. If you have php on your system just run it from the CLI, php earthquake.php
e.g. Insert into mysql from Bash script
I use Laravel a bit, and would probably actually build my own model and use Eloquent and a little UI to handle that, but using a script seems like an option.
I have already connected MySQL to the database but the problem is that
I have some problems with inserting Data from Perl to Mysql.
The error that pops out is:
Use of uninitialized value in concatenation (.) or string at ./etl_server_info.pl line 204, (Which is the connection of the database )
DBD::mysql::st execute failed: called with 1 bind variables when 0 are needed at ($stmt->execute($sql);)
sub insert_record(){
my($data,$db_config)=#_;
my $result = -1; # -1 fail; 0 - succ
# connect to db
# connect to MySQL database
my $dsn = "DBI:mysql:database=".$db_config->{'Top_Data'}.";host=".$db_config->{'127.0.0.1'}.";port=".$db_config->{'3306'};
my $username = $db_config->{'username'};
my $password = $db_config->{'password'};
my %attr = (PrintError=>0,RaiseError=>1 );
my $dbh = DBI->connect($dsn,$username,$password,\%attr) or die $DBI::errstr;
print "We Have Successfully Connected To The Database \n";
# prepare sql statement
# execute insert
my $sql = 'insert into Top(Load_Average, CPU_us, CPU_id, CPU-wa, CPU_hi, CPU_si, CPU_st, Swap_Total, Swap_Free, Swap_Used, Memory_Total, Memeory_Free, Memory_Used, Memory_Buff, Date) values(float,float,float,float,float,float,float,float,varchar,varchar,varchar,varchar,varchar,varchar,date)';
my $stmt =$dbh->prepare($sql) or die "Its A Fail" . $dbh->errstr();
$stmt->execute($sql);
$stmt->finish();
$dbh->disconnect();
$result = 0;
return($result);
Your use of the $db_config variable looks suspicious to me. Either your config hash is strange, or you're using values instead of keys.
You haven't shown us where $db_config is set up, but I'd guess it looks something like this:
$db_config = {
name => 'Top_Data',
host => '127.0.0.1',
port => 3306,
username => 'someone',
password => 'a secret',
};
And then you would use it like this:
my $dsn = "DBI:mysql:database=".$db_config->{name}.";host=".$db_config->{host}.";port=".$db_config->{port};
Notice that I've used the key names (name, host and port) instead of the values (Top_Data, 127.0.0.1 and 3306).
I'll also point out that you can simplify this slightly by using Perl's ability to expand variables inside a double-quoted string.
my $dsn = "DBI:mysql:database=$db_config->{name};host=$db_config->{host};port=$db_config->{port}";
There's another problem later on, with your SQL statement.
my $sql = 'insert into Top(Load_Average, CPU_us, CPU_id, CPU-wa, CPU_hi,
CPU_si, CPU_st, Swap_Total, Swap_Free, Swap_Used, Memory_Total,
Memeory_Free, Memory_Used, Memory_Buff, Date)
values(float,float,float,float,float,float,float,float,
varchar,varchar,varchar,varchar,varchar,varchar,date)';
The values that you should be inserting are the actual data items. So where you have the strings "float", "varchar" or "date", you should actually have data items (a floating-point number, a string or a date).
Finally, having prepared your statement, you don't need to pass it to the execute() method. You should, however, look at using bind points in your SQL and passing your actual data items to the execute() call
This question already has answers here:
How to change mysql to mysqli?
(12 answers)
Closed 4 years ago.
How do I make this older version of php work in php7?
I have a mysql database that I use for posting high scores from my games that I create in Construct 2. But now it has stopped working because my host updated to php7 ( at the moment I can choose between php 7.1 - 7.3 )
I have tried for a long time, searching the web, to make it work again, but haven't been able to solve it.
I have 2 php-files: getscores.php and savescores.php
When I try to view getscores.php in a webbrowser ( Chrome ) I get an error:
Fatal error: Uncaught Error: Call to undefined function mysql_query()
...And it's referring to line 18.
I'm sorry but I have almost no knowledge of php and mysql-databases
Thank you so much, in advance, if there's anyone out there who could help. :)
///Soulmachine!
getscores.php
<?php
header('Access-Control-Allow-Origin: *');
$host="localhost"; // Host name
$username="username"; // Mysql username
$password="password"; // Mysql password
$db_name="database"; // Database name
$tbl_name="scores"; // Table name
// Connect to server and select database.
$link = mysqli_connect("$host", "$username", "$password", "$db_name");
// Retrieve data from database
$sql="SELECT * FROM scores ORDER BY score DESC LIMIT 10"; // The 'LIMIT 10' part will only read 10 scores. Feel free to change this value
$result=mysql_query($sql);
// Start looping rows in mysql database.
while($rows=mysqli_fetch_array($result)){
echo $rows['name'] . "|" . $rows['score'] . "|";
// close while loop
}
// close MySQL connection
mysql_close();
?>
savescores.php
<?php
$db = "database";//Your database name
$dbu = "username";//Your database username
$dbp = "password";//Your database users' password
$host = "localhost";//MySQL server - usually localhost
$dblink = mysqli_connect($host,$dbu,$dbp,$db);
if(isset($_GET['name']) && isset($_GET['score'])){
//Lightly sanitize the GET's to prevent SQL injections and possible XSS attacks
$name = strip_tags(mysql_real_escape_string($_GET['name']));
$score = strip_tags(mysql_real_escape_string($_GET['score']));
$sql = mysqli_query($dblink, "INSERT INTO `$db`.`scores` (`id`,`name`,`score`) VALUES ('','$name','$score');");
if($sql){
//The query returned true - now do whatever you like here.
echo 'Your score was saved. Congrats!';
}else{
//The query returned false - you might want to put some sort of error reporting here. Even logging the error to a text file is fine.
echo 'There was a problem saving your score. Please try again later.';
}
}else{
echo 'Your name or score wasnt passed in the request. Make sure you add ? name=NAME_HERE&score=1337 to the tags.';
}
mysqli_close($dblink);//Close off the MySQL connection to save resources.
?>
Replace mysql_query and mysql_close with mysqli_query and mysqli_close respectively.
<?php
header('Access-Control-Allow-Origin: *');
$host="localhost"; // Host name
$username="username"; // Mysql username
$password="password"; // Mysql password
$db_name="database"; // Database name
$tbl_name="scores"; // Table name
// Connect to server and select database.
$link = mysqli_connect("$host", "$username", "$password", "$db_name");
// Retrieve data from database
$sql="SELECT * FROM scores ORDER BY score DESC LIMIT 10"; // The 'LIMIT 10' part will only read 10 scores. Feel free to change this value
$result=mysqli_query($link, $sql);
// Start looping rows in mysql database.
while($rows=mysqli_fetch_array($result)){
echo $rows['name'] . "|" . $rows['score'] . "|";
// close while loop
}
// close MySQL connection
mysqli_close($link);
?>
This should work.
I am trying to connect to 2 databases on the same instance of MySQL from 1 Perl script.
I am using this in a migration script where I am grabbing data from the original database and inserting it into the new one.
Connecting to 1 database and then trying to initiate a second connection with the same user just changes the current database to the new one.
#!/usr/bin/perl
use DBI;
use strict;
my $driver = "mysql";
my $database1 = "db1";
my $dsn1 = "DBI:$driver:database=$database1";
my $userid = "userhead";
my $password = "pwdhead";
my $database2 = "db2";
my $dsn2 = "DBI:$driver:database=$database2";
my $dbh1 = DBI->connect($dsn1, $userid, $password ) or die $DBI::errstr;
my $dbh2 = DBI->connect($dsn2, $userid, $password ) or die $DBI::errstr;
my $sth = $dbh2->prepare("INSERT INTO Persons") $dbh1->prepare("SELECT *FROM Persons");
$sth->execute() or die $DBI::errstr;
print "Number of rows found :" + $sth->rows;
In the above example i am trying to copy from one database table to another datbase table. but i am getting error while running the script. Please help me out
At a guess, you're trying to use the same database handle to connect to both databases. If you need to operate two separate connections then you need two separate handles
This program uses the data_sources class method to discover all of the available MySQL databases and creates a connection to each of them, putting the handles in the array #dbh. You can use each element of that array as normal, for instance
my $stmt = $dbh[0]->prepare('SELECT * FROM table)
It may be that you prefer to set up the #databases array manually, or the username and password may be different for the two data sources, so some variation on this may be necessary
use strict;
use warnings 'all';
use DBI;
my $user = 'username';
my $pass = 'password';
my #databases = DBI->data_sources('mysql');
my #dbh = map { DBI->connect($_, $user, $pass) } #databases;
Update
You need to select data from the source table, fetch it one row at a time, and insert each row into the destination table
Here's an idea how that might work, but you need to adjust the number of question marks in the VALUES of the INSERT statement to match the number of columns
Note that, if you're just intending to copy the whole dataset, there aree better ways to go about this. In particular, if you have any foreign key constraints then you won't be able to add data until the table it it is dependent on is populated
#!/usr/bin/perl
use strict;
use warnings 'all';
use DBI;
my $userid = "userhead";
my $password = "pwdhead";
my ($dbase1, $dbase2) = qw/ db1 db2 /;
my $dsn1 = "DBI:mysql:database=$dbase1";
my $dsn2 = "DBI:mysql:database=$dbase2";
my $dbh1 = DBI->connect($dsn1, $userid, $password ) or die $DBI::errstr;
my $dbh2 = DBI->connect($dsn2, $userid, $password ) or die $DBI::errstr;
my $select = $dbh1->prepare("SELECT * FROM Persons");
my $insert = $dbh2->prepare("INSERT INTO Persons VALUES (?, ?, ?, ?, ?)");
$select->execute;
while ( my #row = $select->fetchrow_array ) {
$insert->execute(#row);
}
If you need to handle the columns from the source data separately then you can use named scalars instead of the array #row. Like this
while ( my ($id, $name) = $select->fetchrow_array ) {
my $lastname = '';
$insert->execute($id, $name, $lastname);
}
Plan A (especially if one-time task):
Run mysqldump on the source machine; feed the output to mysql on the target machine. This will be much faster and simpler. If you are on a Unix machine, do it with an exec() from Perl (if you like).
Plan B (especially if repeated task):
If the table is not "too big", do one SELECT to fetch all the rows into an array in Perl. Then INSERT the rows into the target machine. This can be sped up (with some effort) if you build a multi-row INSERT or create a CSV file and use LOAD DATA instead of INSERT.
In my development environment, all calls to mysqli_affected_rows($link) are unexpectedly returning -1, indicating an error of some sort.
The identical SQL executed from a SQL console works as expected.
To avoid people trying to understand the code, I have written rewritten this question with a very simple test script, as follows:
<?php
// $DB parameters deleted
$link = #mysqli_connect($DBHOSTNAME, $DBUSER, $DBPASSWORD, $DBNAME);
$query = 'UPDATE control SET message = 66476 WHERE controlid = "lastgood"';
$rs = mysqli_query($link, $query);
$nbr = mysqli_affected_rows($link);
echo $nbr;
?>
This script returns -1. Something in my environment is clobbering mysqli_affected_rows().
There is a bug documented at https://bugs.php.net/bug.php?id=67348 with mysqli_affected_rows when operating through a debugger.