MySQLi queries with php - query strings contain single quotes and curly braces - php

I am writing a php script to put a dictionary file into a Mysql database. It works fine, except in certain cases when the definition strings contain both single quotes and multiple sets of curly braces. This is one of the definition strings that fails.
(n) (1) {sports} carry-back/bringing the ball back to one's own
position (in rugby)/(2) {econ} carryback/carrying over a deduction or
credit from a prior year to the current year (to reduce income tax)
This is the **MySQLi ** error message:
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 's own position (in rugby)/(2) econ', {'(n) (1) {sports}
carry-back/bringing the ' at line 1
Heres the section of the script regarding the definition string:
$definition = substr($definition_string, 0, $pos);
$definition = substr($definition, 1);
// Escape single quote
$definition = str_replace(["'"], "''" , $definition);
$mysqli->set_charset("utf8");
$result = $mysqli->query("INSERT INTO dict (entry, reading, category, definition, entry_number) VALUES ('$entry', '$reading', '$category', '$definition', '$entry_number')");
I can't figure out why its failing and the error message isn't helping much. Any ideas?

I recommend you read about this here. They give several different methods on how to protect the data going into the database.
Here is one of the many ways:
$result = $mysqli->query("INSERT INTO dict (entry, reading, category, definition, entry_number) VALUES (
'" . $mysqli->escape_string($entry) . "',
'" . $mysqli->escape_string($reading) . "',
'" . $mysqli->escape_string($category) . "',
'" . $mysqli->escape_string($definition) . "',
'" . $mysqli->escape_string($entry_number) . "')");
Another more eloquent solution:
$stmt = $mysqli->prepare("INSERT INTO dict (entry, reading, category, definition, entry_number) VALUES (
?, ?, ?, ?, ?)");
$stmt->bind_param('sssss', $entry, $reading, $category, $definition, $entry_number);
$stmt->execute();
$result = $stmt->get_result();

Related

MySQL query fails to execute

I am trying to query large amounts of data to a server, here is my code for that:
$queryString = "";
$connect = mysqli_connect("localhost", "username", "password", "database");
$loopLength = 20;
$currentGroup = 1;
$currentLoopAmount = 0;
$queryAmount = 5;
for($v = 0; $v < ceil($loopLength / $queryAmount); $v++){
//echo "Looping Main: " . $v . "<br>";
//echo $loopLength - (($currentGroup - 1) * 10) . "<br>";
if($loopLength - (($currentGroup - 1) * $queryAmount) >= $queryAmount){
$currentLoopAmount = $queryAmount;
}
else{
$currentLoopAmount = $loopLength - (($currentGroup - 1) * $queryAmount);
}
//echo $currentLoopAmount;
$queryString = "";
for($q = (($currentGroup - 1) * $queryAmount); $q < $currentLoopAmount + (($currentGroup - 1) * $queryAmount); $q++){
//echo " Looping Sub: " . $q . "<br>";
$tempVariable = grabPageData($URLs[$q], $q);
$queryString .= $tempVariable;
if($q < $loopLength-1){
$queryString .= ",";
}
else{
$queryString .= ";";
}
}
echo $queryString;
$query = "INSERT INTO PublicNoticesTable (url, county, paperco, date, notice, id) VALUES " . $queryString;
$result = mysqli_query($connect, $query);
if($result){
echo "Success";
}
else{
echo "Failed : " . mysqli_error($connect) . "<br>";
}
$currentGroup += 1;
}
The $loopLength variable is dynamic and can be in the thousands or potentially hundred thousands. I designed this function to divide that massive number into a batch of smaller queries as I couldn't upload all the data at one time on my shared hosting service through GoDaddy. The $queryAmount variable represents how big the smaller queries are.
Here is an example of one of the value sets that gets inserted into the table:
It is the data from a public notice that my code retrieved in the grabPageData() function.
('http://www.publicnoticeads.com/az/search/view.asp?T=PN&id=37/7292017_24266919.htm','Pima','Green Valley News and Sun','2017/07/30',' ___________________________ARIZONA SUPERIOR COURT, PIMA COUNTYIn the Matter of the Estate of:JOSEPH T, DILLARD, SR.,Deceased.DOB: 10/09/1931No. PB20170865NOTICE TO CREDITORS(FOR PUBLICATION)NOTICE IS HEREBY GIVEN that DANA ANN DILLARD CALL has been appointed Personal Representative of this Estate. All persons having claims against the Estate are required to present their claimswithin four months after the date of the firat publication of this notice or the claims will be forever barred. Claims must be presented by delivering or mailing a written statement of the claim to the Personal Representative at the Law Offices of Michael W. Murray, 257 North Stone Avenue, Tucson, Arizona 85701.DATED this 17th day of July, 2017./S/ Micahel W. MurrayAttorney for the Personal RepresentativePub: Green Valley News & SunDate: July 23, 30, August 6, 2017 Public Notice ID: 24266919',' 24266919'),
To attain this data, I run it through a function that crawls the page and grabs it. Then I put the webpage html code through this function:
function cleanData($data){
$data = strip_tags($data);
//$data = preg_replace("/[^a-zA-Z0-9]/", "", $data);
//$data = mysql_real_escape_string($data);
return $data;
}
Which gives me the content without tags as you see above. Here's the problem.
The function executes and everything seems just dandy. Then the function (depending on the $queryAmount variable which I don't keep over 10 for problem's sake) outputs, as you can see it would in the function something like...
Failed : 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 '' at line 1
The weird part is that when I have large amounts of data like say the $loopLength variable is like 116. The result will output, "Failed : (error)Failed : (Error)Fai...(Error)Success. So it's only actually querying the last set of data??? Not sure.
I am not sure how to fix this and I want a fresh eye. Can somebody help me please. I have been working on this problem for... several hours trying to find solution.
Sorry for making this question a pain in the butt :(
EDIT:
I changed the code from previously to use mysql prepared statements and what not... See below:
$grabDataResults = [
"url" => "",
"county" => "",
"paperco" => "",
"date" => "",
"notice" => "",
"id" => "",
];
$connect = mysqli_connect("localhost", "bwt_admin", "Thebeast1398", "NewCoDatabase");
if($stmt = mysqli_prepare($connect, "INSERT INTO PublicNoticesTable (url, county, paperco, date, notice, id) VALUES (?, ?, ?, ?, ?, ?)")){
mysqli_stmt_bind_param($stmt, 'ssssss', $grabDataResults["url"], $grabDataResults["county"], $grabDataResults["paperco"], $grabDataResults["date"], $grabDataResults["notice"], $grabDataResults["id"]);
$loopLength = 1;
for($v = 0; $v < $loopLength; $v++){
$grabDataResults = grabPageData($URLs[$v], $v);
mysqli_stmt_execute($stmt);
printf("%d Row inserted.\n", mysqli_stmt_affected_rows($stmt));
printf("Error:\n", mysqli_stmt_error($stmt));
echo "(" . $grabDataResults["url"] . "," . $grabDataResults["county"] . "," . $grabDataResults["paperco"] . "," . $grabDataResults["date"] . "," . $grabDataResults["notice"] . "," . $grabDataResults["id"] . ")";
}
mysqli_stmt_close($stmt);
mysqli_close($connect);
}
Unfortunately this is what I get from the output:
1 Row inserted. 0 Error:
No error actually prints out and the row is inserted. However when I navigate to my database, and look at the values that have been stored.. They are all empty. The echo statement outputs this:
(http://www.publicnoticeads.com/az/search/view.asp?T=PN&id=31/7292017_24266963.htm,Yuma,Sun (Yuma), The,2017/07/30,, 24266963)
So I know that all of the variables contain something except for the $notice variable which gets destroyed by my cleanData() function for some reason.
You need to bind the data after fetching it and before executing it...
$loopLength = 1;
for($v = 0; $v < $loopLength; $v++){
$grabDataResults = grabPageData($URLs[$v], $v);
mysqli_stmt_bind_param($stmt, 'ssssss', $grabDataResults["url"],
$grabDataResults["county"], $grabDataResults["paperco"],
$grabDataResults["date"], $grabDataResults["notice"],
$grabDataResults["id"]);
mysqli_stmt_execute($stmt);
printf("%d Row inserted.\n", mysqli_stmt_affected_rows($stmt));
printf("Error:\n", mysqli_stmt_error($stmt));
echo "(" . $grabDataResults["url"] . "," . $grabDataResults["county"] . "," . $grabDataResults["paperco"] . "," . $grabDataResults["date"] . "," . $grabDataResults["notice"] . "," . $grabDataResults["id"] . ")";
}
You code is correct. Just you need to add () arround querystring
Akso you need to remove ; from query string end. SO remove following else condition
else{
$queryString .= ";";
}
change you query like :
$query = "INSERT INTO PublicNoticesTable (url, county, paperco, date, notice, id) VALUES (" . $queryString . ")";
Also it advisable to use prepared statements to prevent from sql injections
The main error I can see on your query, are the query itself. You're using a INSERT INTO with separated fields and values. But you forget to use the pharentesis on values.
Remember, the use of INSERT INTO are as follows:
First option:
INSERT INTO table field1 = value1, field2 = value2;
Second option:
INSERT INTO table (field1, field2) VALUES (value1, value2);
Also, remember to escape every field and value for avoid more errors: Example:
First option:
INSERT INTO `table` `field1` = 'value1', `field2` = 'value2';
Second option:
INSERT INTO `table` (`field1`, `field2`) VALUES ('value1', 'value2');
If you're using mysqli driver, for more security, you can use prepared statements, to get your values automatically escaped. In that case, the syntax of the query are as follows:
First option:
INSERT INTO `table` `field1` = ?, `field2` = ?;
Second option:
INSERT INTO `table` (`field1`, `field2`) VALUES (?, ?);
Also, instead of using mysqli_query(), you need to use mysqli_prepare(), mysqli_bind_param() and mysqli_execute(). You can check more data about they syntax here: http://php.net/manual/en/mysqli.prepare.php
At least, you can use mysqli_real_escape_string() function for getting your input properly escaped and checked. You can check documentation of this function here: http://php.net/manual/en/mysqli.real-escape-string.php

What's wrong with the PHP syntax here?

I'm having hard time to figure out whats wrong in this code. I tried many variations but still getting error in this line:
$query= "INSERT INTO publish (name, email, title, content)" .
"VALUES ('$row['Name']','$row['Email']',$row['title'],$row['content'])";
What could be wrong?
here's the rest of the code:
<?php
// connect to the database
include('config2.php');
// check if the 'id' variable is set in URL, and check that it is valid
if (isset($_GET['id']) && is_numeric($_GET['id']))
{
// get id value
$id = $_GET['id'];
$dbc = mysqli_connect('localhost', 'x', 'x', 'x')
or die('Error');
$name = $row['Name'];
$email = $row['Email'];
$title = $row['title'];
$content = $row['content'];
$result = mysql_query("select *stories WHERE id=$id")
or die(mysql_error());
$row = mysql_fetch_array( $result );
$query= "INSERT INTO publish (name, email, title, content)" .
"VALUES ('$row['Name']','$row['Email']',$row['title'],$row['content'])";
or die('Error querying database.');
mysqli_close($dbc);
}
?>
Error message: "parse error expecting identifier (t_string) ' or variable (t_variable) ' or number (t_num_string) '"
You probably want to use complex string syntax to properly interpolate those variables. For example:
$query= "INSERT INTO publish (name, email, title, content)" .
"VALUES ('{$row['Name']}','{$row['Email']}',{$row['title']},{$row['content']})";
Though that will only fix one of the issues with the code.
Do note there are plenty of other ways to resolve this one too, such as concatenation instead of interpolation, or string replacements, etc etc.
It might also be worth reading the documentation on strings at some point.
You forgot the "." between your variables and your strings. Like so:
$query= "INSERT INTO publish (name, email, title, content)" .
"VALUES (".$row['Name'].','.$row['Email'].','.$row['title'].','.$row['content'].")";
However, it looks like you may have some additional issues going on there with the actual SQL query.
The best practice in PHP is to use single quote ' for strings. Cos PHP looks for variables inside double quoted strings and keeps on sniffing whether there is a variable (or multiple variables) inside the string.
So for example: "A very very long string... $var1 .. long string .. $var2 string" this will run slower compared to 'A very very long string... ' . $var1 . ' .. long string .. ' . $var2 . ' string'; cos when PHP sees single quote it won't sniff for variables inside it thus it's faster.
From my experience, in my early age I worked on a very large php script and used double quotes everywhere. After the above explanation from an expert I converted the whole script to single quote and the performance was much better.
So for your situation I'd suggest and request to use single quotes and it'll avoid confusions as well. Also using mysql_real_escape_string() is a good practice to avoid SQL Injection.
$query= 'INSERT INTO publish (name, email, title, content)
VALUES (
\'' . mysql_real_escape_string ($row['Name']) . '\',
\'' . mysql_real_escape_string ($row['Email']) . '\',
\'' . mysql_real_escape_string ($row['title']) . '\',
\'' . mysql_real_escape_string ($row['content']) . '\')';

MySQLi query to MySQL query

I am trying do multi-driver support for my Framework, which basically means I can use MySQL, MySQLi or PDO(MySQL) with ease.
So, let's say I have an array of values I want to insert.
array('Manuel', 'StackOverflow');
and I have this query..
mysql_query("INSERT INTO users(name, fav_site) VALUES(?, ?)");
So, I'd like to replace the question marks with those values in order, so Manuel goes first and then goes StackOverflow. Remembering that I need to add -> ' <- at the sides of these values so MySQL doesn't throw an error.
I have tried searching if someone has asked this and had no luck.
Any help is appreciated!
NOTE: I know I shouldn't even bother with MySQL, but hey! A feature is a feature.
<?php
$query = "INSERT INTO users(name, fav_site) VALUES(?, ?)";
$args = array('joe', 'google goggles');
while(strpos($query, '?') !== FALSE)
{
$query = preg_replace('/\?/', your_quoting_func(array_shift($args)), $query, 1);
}
echo $query;
Basically, this says...while there is still a ? remaining in the string, delete the first question mark and replace it with a quoted (use your own function or mysql_real_escape_string and surround with single quotes) string, and shift that item off the array. You should probably substr_count the ? marks versus the number of arguments for error checking.
I used preg_replace because it accepts an argument specifying how many values to replace, whereas str_replace does not.
I would do it this way (with one exeption: I wouldn't use mysql_):
<?php
$values = array('foo', 'bar');
$query_start = "INSERT INTO `users` (`name`, `fav_site`) VALUES ('";
$query_end = "')";
$query = $query_start . implode("', '", $values) . $query_end;
$result = mysql_query($query);
?>
$query_start contains the start of the MySQL query (notice the ' at the end), and $query_end goes at the end.
Then $values is imploded, with ', ' as the 'glue', and $result is set as:
$query_start (impoded $result) $query_end.
See implode - PHP Manual.

insert special characters into a Postgresql database

I have a php script which returns some values with special characters, especially single quotes(') and the 'at sign'(#). The values that contain these characters are not inserted into the database. I saw a post in doing this on mysql database at (http://stackoverflow.com/questions/2584066/php-how-to-insert-special-characters-into-a-database).
My question then is how can it be done in Postgresql database.
See below the php code:
<?php
require 'table.php';
// Opens a connection to a PostgresSQL server
$connection = pg_connect("dbname=postgis user=postgres password=local");
// Execute query
foreach ($xml->item as $entry){
$georss = $entry->children($namespaces['georss']);
list($lat, $lng) = explode(' ', (string)$georss->point);
$query = "INSERT INTO geognews(title, link, author, latitude, longitude) VALUES ('" . $entry->title . "', '" . $entry->link . "', '" . $entry->children($namespaces['dc'])->creator . "', '" . $lat . "', '" . $lng . "')";
$result = pg_query($query);
printf ("These values are inserted into the database - %s %s %s", $entry->title, $entry->link, $entry->children($namespaces['dc'])->creator, $lat, $lng);
}
pg_close();
?>
Use pg_query_params(), by far the easiest way to avoid SQL injection. And thus quotes ' and other risky stuff.
You have a few of options:
You could wrap dynamic data pg_escape_string() (and related functions for other types) to properly encode special characters. This will require the least amount of change to the code you've posted.
You could use prepared statements and bind your dynamic data as parameters. See the docs for pg_prepare() for examples on how to do this. Prepared statements are the recommended way to protect against SQL Injection.
You could use PDO with parameterized queries. This gives you the safety and performance benefits of parameterized queries plus a universal database abstraction layer.
The last option is preferred.

PHP/MySQL Query and String Concatenation of row from mysql_fetch_array()

This works:
$row = mysql_fetch_array($result);
$accountID = $row['accountID'];
queryMysql('INSERT INTO accounts (accountID, password) VALUES (' .
"'$accountID'" . ', \'a\')');
But this doesn't:
$row = mysql_fetch_array($result);
queryMysql('INSERT INTO accounts (accountID, password) VALUES (' .
$row['accountID'] . ', \'a\')');
Why?
Because you're missing another ' right before and after $row['accountId']
$row = mysql_fetch_array($result);
queryMysql('INSERT INTO accounts (accountID, password) VALUES (\'' .
$row['accountID'] . '\', \'a\')');
If you are beginning PHP and have the required version of PHP (5.1.0) I strongly suggest you start using PDO
http://php.net/pdo
instead of the standard mysql_*
First, you should always tell us why it doesn't work. Only saying "it doesn't work" is really begging for getting your post ignored.
Second, the cause of the error is most likely the lack of quote, but that would only be necessary if there's another underlying problem. The type of the column accountID seems to be varchar or text. An ID should be an integer.
You have to wrap your value with quotes if it's a string, you don't if it's an integer.

Categories