MySQL query fails to execute - php

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

Related

Prevent PHP from attempting to perform mathematical calculations on a string

So I'm using PHP to take the contents of a csv file, put it into a string array and then use SQL to add it to a database on an IBM iSeries.
However PHP keeps trying to treat the contents of the string (which contains special characters like "*" and "-") like a mathematical computation.
How do I prevent this?
here is the code in question
if (($handle = fopen($_FILES['uploadcsv']['tmp_name'], "r")) !== FALSE)
{
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE)
{
$length = count($data);
$s_data = implode(',', $data);
if($length > $maxcol)
{
// echo $length;
// die;
$uploadMsg = "Data Error: Not ($maxcol) Columns: ($s_data) <br>";
}
else
{
if($data[0] <> '')
{
$recda[0] = trim($data[0]); // qty = 1 roll
// Prepare the SQL statement (possibly faster, safer, better practice)
$insertsql = "INSERT INTO MIKELIB/PALLETS (PALLET)
VALUES($recda[0]) with nc";
$stmt = db2_prepare($db2conn, $insertsql);
//$result = db2_exec($db2conn, "Insert into file ...$data[0]"
$result = db2_execute($stmt, $data[0]);
if(!$result)
{
$uploadMsg .= "Result code: " . $result . "Data Error: " . db2_stmt_error() . " msg: " . db2_stmt_errormsg() . "data: ($s_data)<br>";
}
else
{
$s_data = implode(',', $recda);
$uploadMsg .= "Added row ($s_data)<br>";
}
}
}
}
fclose($handle);
}
Here is an example output of the error "Result code: Data Error: 42604 msg: Numeric constant 5D09C not valid. SQLCODE=-103data: (A2501-0044*970*5D09C*034)"
Actually, it's your database that is parsing your data as math.
Take a look at this line:
$insertsql = "INSERT INTO MIKELIB/PALLETS (PALLET)
VALUES($recda[0]) with nc";
$stmt = db2_prepare($db2conn, $insertsql);
You're putting the values directly into the query, so if the query has math, or invalid symbols, it'll break your query.
What you should do is:
$insertsql = "INSERT INTO `MIKELIB/PALLETS` (PALLET)
VALUES(?) with nc";
$stmt = db2_prepare($db2conn, $insertsql);
$recda0 = $recda[0];
db2_bind_param($stmt, 1, "recda0", DB2_PARAM_IN);
That way, there's nothing in $recda[0] that will break the query, or be parsed as part of the query.
Joesph, try modifing your SQL to treat that value as a string by wrapping it in single quotes.
$insertsql = "INSERT INTO MIKELIB/PALLETS (PALLET)
VALUES('$recda[0]') with nc";
You may also need to consider escaping single quotes in the string if there is a possibility it will contain any.
I get the impression that you may be trying to load values into multiple columns per row. That won't work in SQL. You have to specify each column.
I know DB2 for i, but not PHP, so I'll attempt to build on David's answer as a template.
$insertsql = "INSERT INTO MYLIB/MYTABLE (cola, colb, colc)
VALUES(?,?,?) with nc";
$stmt = db2_prepare($db2conn, $insertsql);
$vala = $recda[0];
$valb = $recda[1];
$valc = $recda[2];
db2_bind_param($stmt, 1, "vala", DB2_PARAM_IN);
db2_bind_param($stmt, 2, "valb", DB2_PARAM_IN);
db2_bind_param($stmt, 3, "valc", DB2_PARAM_IN);
You may need additional PHP code, perhaps to make sure each value is appropriate for its column, and might perhaps need to detect missing values and load a null or default value, depending on your table definition. But I'll leave that to those who know PHP.

How to insert data into MySql using an associative array [duplicate]

This question already has an answer here:
Mysqli prepared statements build INSERT query dynamically from array
(1 answer)
Closed 8 months ago.
I am now having a problem inserting data in associative array with its key as fields in the table and the values to be inserted into MySql database. Here is my code.
<?php
$table = 'articles';
$data = array(
'title' => 'Header',
'content' => 'This is content',
'author' => 'James');
$keys = implode(', ', array_keys($data));
$values = implode(', ', array_values($data));
$sql = 'insert into '.$table.'('.$keys.') values ('.$values.')';
$db = new mysqli('localhost', 'root', 'root', 'blog');
$db->query($sql);
?>
With this code, I wasn't able to insert the data into the database so I try to echo the query string out and I got something like this :
insert into articles(title, content, author) values (Header, This is content, James)
However, if I use the single quote in each value like this
insert into articles(title, content, author) values ('Header', 'This is content', 'James')
I can successfully insert the data into the database.
So I don't know what's wrong here. Is it a problem with the quote sign or not because when I use the single quote, this seems to work.
So please help me find the proper solution for this...
For the query you need to enclose each value in quotes. To do that you can change your implode statement to include the quotes to around the values -
$values = "'" .implode("','", array_values($data)) . "'";
EXAMPLE-demo
You should also be checking for errors.
Replace $db->query($sql);
with
if(!$result = $db->query($sql)){
die('There was an error running the query [' . $db->error . ']');
}
else{
echo "Data inserted.";
}
So I don't know what's wrong here. Is it a problem with the quote sign or not because when I use the single quote, this seems to work.
Yes, you need to use the single quote.
You can check it out:
$values = implode(', ', array_values($data));
Into something like it:
$values = implode (',', array_map (
function ($z)
{
return ((is_numeric ($z) || (is_string ($z) ? ($z == "NOW()" ? true : false) : false) || (is_array ($z)?(($z=implode(";",$z))?false:false):false)) ? $z : "'" . utf8_decode ($z) . "'");
}, array_values ($data)));
The idea is that you make every value field quoted, I meant value field by value field in the query. For instance, in my example, the function ignores NOW() as string, and keep it up to work as SQL's timestamp. Because if you treat it as string type, the command wouldn't work properly.
Anyway, the above is ugly and insecure.
I would advice you to look for some ORM like RedBeanORM or, maybe, use the proper PHP MySQL version like MySQLi. Mainly to avoid SQL injections.
Look one ORM example:
require 'rb.php';
R::setup();
$post = R::dispense('post');
$post->text = 'Hello World';
$id = R::store($post); //Create or Update
$post = R::load('post',$id); //Retrieve
R::trash($post); //Delete
Look one PHP MySQL improved version example:
$stmt = mysqli_prepare($link, "INSERT INTO CountryLanguage VALUES (?, ?, ?, ?)");
mysqli_stmt_bind_param($stmt, 'sssd', $code, $language, $official, $percent);
$code = 'DEU';
$language = 'Bavarian';
$official = "F";
$percent = 11.2;
mysqli_stmt_execute($stmt);
Good luck. Good learning.
Positional place-holders:
$values = implode(', ',
array_fill(0, count($data), '?')
);
// insert into articles(title, content, author) values (?, ?, ?)
Named place-holders:
$values = implode(', ', array_map(
function($value){
return ":$value";
},
array_keys($data)
));
// insert into articles(title, content, author) values (:title, :content, :author)
Not necessarily the nicest or best code.
As about the parameter array itself, I'm not familiar with mysqli but with many DB extensions you could use $data as-is.

php - bind_param inside foreach() not correctly passing

I'm sure this is a duplicate, but I've tried several different things on the site here and none of them are working for me. I'm calling my function in php, sending $mysqli connection, the $clientID, and the array of $tagFields to upload.
It's 'working', but the values are always null. I've put echo "$tagName" inside the foreach, and it's reading it, but not sending it up to the database. $clientID, however, IS passing information. So basically all it does is upload consistently blank rows into my database. What am I doing wrong here?
function tagRefresh($mysqli,$clientID,$tagFields) {
$stmt = $mysqli->stmt_init();
$query = "INSERT INTO client_tags (client_id,tag_category) VALUES (?,?) ";
$stmt->prepare($query);
foreach($tagFields as $tagName) {
$stmt->bind_param('is',$clientID,$tagName);
$stmt->execute();
}
}
some sample values for $tagFields:
$tagFields[0] = "Regional";$tagFields[1] = "Automotive";$tagFields[2] = "Maintenance";
Note mysqli_stmt::bind_param bind the reference of the variables.
Try the below:
function tagRefresh($mysqli,$clientID,$tagFields) {
$stmt = $mysqli->stmt_init();
$query = "INSERT INTO client_tags (client_id,tag_category) VALUES (?,?) ";
$stmt->prepare($query);
$stmt->bind_param('is', $clientID, $tagName);
foreach($tagFields as $tagName) {
$stmt->execute();
}
}
execute() shouldn't be situated inside the foreach.
Among with a myriad of problems associated with the database (including the client_id being the primary key), I've rebuilt the formula like this:
function tagRefresh($mysqli,$clientID,$tagFields) {
$query = "DELETE FROM client_tags WHERE client_id = '" . $clientID . "'"; //we have to delete the old ones every time
if(!$mysqli->query($query)) {
echo $mysqli->error;
}
if($tagFields != '') { //see if data was sent
$tags = array();
foreach($tagFields as $tag) {
$tags[] = "('" . (int) $clientID . "', '" . $tag ."')"; //build an array
}
$query = "INSERT INTO client_tags (client_id,tag) VALUES " . implode(',', $tags) . " ON DUPLICATE KEY UPDATE client_id = " . $clientID;
if(!$mysqli->query($query)) {
echo $mysqli->error; //drop errors, will attach this later
}
}
}
This formats to something like this:
INSERT INTO client_tags (client_id,tag) VALUES ('1234','mechanical'),('1234','regional'),('1234','service') ON DUPLICATE KEY UPDATE client_id = '1234';
The ON DUPLICATE part is important because for some reason the client_id is set to primary key. I'm gonna have to talk to the app guys and see if this matters to them.
Unfortunately, bind_param isn't being used, but this is a admin panel access only for company employees only, and now that this is working I'm giving them autocomplete boxes to reference existing values.

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.

Inserting multiple rows in a table using PHP

I am trying to insert multiple rows into MySQL DB using PHP and HTML from. I know basic PHP and searched many examples on different forums and created one script however it doesn't seem working. Can anybody help with this. Here is my script:
include_once 'include.php';
foreach($_POST['vsr'] as $row=>$vsr) {
$vsr=mysql_real_escape_string($vsr);
$ofice=mysql_real_escape_string($_POST['ofice'][$row]);
$date=mysql_real_escape_string($_POST['date'][$row]);
$type=mysql_real_escape_string($_POST['type'][$row]);
$qty=mysql_real_escape_string($_POST['qty'][$row]);
$uprice=mysql_real_escape_string($_POST['uprice'][$row]);
$tprice=mysql_real_escape_string($_POST['tprice'][$row]);
}
$sql .= "INSERT INTO maint_track (`vsr`, `ofice`, `date`, `type`, `qty`, `uprice`,
`tprice`) VALUES ('$vsr','$ofice','$date','$type','$qty','$uprice','$tprice')";
$result = mysql_query($sql, $con);
if (!$result) {
die('Error: ' . mysql_error());
} else {
echo "$row record added";
}
MySQL can insert multiple rows in a single query. I left your code as close as possible to the original. Keep in mind that if you have a lot of data, this could create a large query that could be larger than what MySQL will accept.
include_once 'include.php';
$parts = array();
foreach($_POST['vsr'] as $row=>$vsr) {
$vsr=mysql_real_escape_string($vsr);
$ofice=mysql_real_escape_string($_POST['ofice'][$row]);
$date=mysql_real_escape_string($_POST['date'][$row]);
$type=mysql_real_escape_string($_POST['type'][$row]);
$qty=mysql_real_escape_string($_POST['qty'][$row]);
$uprice=mysql_real_escape_string($_POST['uprice'][$row]);
$tprice=mysql_real_escape_string($_POST['tprice'][$row]);
$parts[] = "('$vsr','$ofice','$date','$type','$qty','$uprice','$tprice')";
}
$sql = "INSERT INTO maint_track (`vsr`, `ofice`, `date`, `type`, `qty`, `uprice`,
`tprice`) VALUES " . implode(', ', $parts);
$result = mysql_query($sql, $con);
Please try this code. Mysql query will not accept multiple insert using php. Since its is a for loop and the values are dynamically changing you can include the sql insert query inside the for each loop. It will insert each rows with the dynamic values. Please check the below code and let me know if you have any concerns
include_once 'include.php';
foreach($_POST['vsr'] as $row=>$vsr) {
$vsr=mysql_real_escape_string($vsr);
$ofice=mysql_real_escape_string($_POST['ofice'][$row]);
$date=mysql_real_escape_string($_POST['date'][$row]);
$type=mysql_real_escape_string($_POST['type'][$row]);
$qty=mysql_real_escape_string($_POST['qty'][$row]);
$uprice=mysql_real_escape_string($_POST['uprice'][$row]);
$tprice=mysql_real_escape_string($_POST['tprice'][$row]);
$sql = "INSERT INTO maint_track (`vsr`, `ofice`, `date`, `type`, `qty`, `uprice`,
`tprice`) VALUES ('$vsr','$ofice','$date','$type','$qty','$uprice','$tprice')";
$result = mysql_query($sql, $con);
if (!$result)
{
die('Error: ' . mysql_error());
}
else
{
echo "$row record added";
}
}
I would prefer a more modern approach that creates one prepared statement and binds parameters, then executes within a loop. This provides stable/secure insert queries and avoids making so many escaping calls.
Code:
// switch procedural connection to object-oriented syntax
$stmt = $con->prepare('INSERT INTO maint_track (`vsr`,`ofice`,`date`,`type`,`qty`,`uprice`,`tprice`)
VALUES (?,?,?,?,?,?,?)'); // use ?s as placeholders to declare where the values will be inserted into the query
$stmt->bind_param("sssssss", $vsr, $ofice, $date, $type, $qty, $uprice, $tprice); // assign the value types and variable names to be used when looping
foreach ($_POST['vsr'] as $rowIndex => $vsr) {
/*
If you want to conditionally abort/disqualify a row...
if (true) {
continue;
}
*/
$ofice = $_POST['ofice'][$rowIndex];
$date = $_POST['date'][$rowIndex];
$type = $_POST['type'][$rowIndex];
$qty = $_POST['qty'][$rowIndex];
$uprice = $_POST['uprice'][$rowIndex];
$tprice = $_POST['tprice'][$rowIndex];
echo "<div>Row# {$rowIndex} " . ($stmt->execute() ? 'added' : 'failed') . "</div>";
}
To deny the insertion of a row, use the conditional continue that is commented in my snippet -- of course, write your logic where true is (anywhere before the execute call inside the loop will work).
To adjust submitted values, overwrite the iterated variables (e.g. $vsr, $ofice, etc) before the execute call.
If you'd like to enjoy greater data type specificity, you can replace s (string) with i (integer) or d (double/float) as required.

Categories