I'm trying to remove apostrophes within certain fields of a SQL Server query within PHP, and despite the fact that I'm throwing in the extra set of ''s in the string pattern section, it still errors out when an apostrophe is found within the result.. I'm not sure what I'm doing wrong here, any help would be hugely appreciated!
This section of the code loops through each row result from a web scrape and throws it into a new table row for each result. The functionality works, but it errors out and breaks the loop whenever an apostrophe is returned by the query.
for($i = 1, $max = count($table); $i < $max; ++$i) {
$dbrow = $table[$i];
$insquery = "INSERT INTO db.schema.table (EVENT_ID, EVENT_CODE, DESCRIPTION,
STATUS, SITE_STATUS, CITY, COUNTY, ZIP, STATE, STARTDATE, ENDDATE, YEARS_PRIOR, TOTAL_PRICE,
CUSTODIAN_FEE, ESTIMATED_FEES, FEE_TYPE, SD, PROGRAM, RC_LN, BUF_AMOUNT, LOC_PREM,
ST_PREM, SNAPSHOT_DATE) VALUES('".$dbrow[0]."','".$dbrow[1]."', replace('".$dbrow[2]."','''', ''),'".$dbrow[3]."','".$dbrow[4]."', replace('".$dbrow[5]."','''', ''), replace('".$dbrow[6]."','''', ''),'".$dbrow[7]."','".$dbrow[8]."','".$dbrow[9]."','".$dbrow[10]."','".$dbrow[11]."','".$dbrow[12]."','".$dbrow[13]."','".$dbrow[14]."','".$dbrow[15]."', replace('".$dbrow[16]."','''', ''), replace('".$dbrow[17]."','''', ''), replace('".$dbrow[18]."','''', ''), replace('".$dbrow[19]."','''', ''),'".$dbrow[20]."','".$dbrow[21]."','".$dbrow[22]."');";
sqlsrv_query($conn, $insquery) or die ("Error in query: $insquery. ".sqlsrv_errors());
echo $insquery . "<br>";
};
Of course it does. You're trying to replace the apostrophes in SQL itself. Consider this statement:
replace('don't','''', '')
How is SQL Server supposed to evaluate that? It opens a string, then after three letters closes that string, then encounters an errant t character resulting in a syntax error.
The query itself needs to be syntactically valid for SQL to execute it. SQL can't fix syntax errors in its own code. You would need to conduct the replacement for single-quotes in PHP, not in SQL.
In any event, there's a really neat solution to all of this. Prepared statements. Don't worry about quoting at all, let the engine handle that for you. For example:
$sql = "INSERT INTO Table_1 (id, data) VALUES (?, ?)";
$params = array(1, "some data");
$stmt = sqlsrv_query($conn, $sql, $params);
This, of course, has the added benefit of helping to protect you from SQL injection attacks, something to which your current code is very likely vulnerable.
Related
I am using the following code to strip out unwanted characters but it is not stripping out everything and throwing a MySQL error:
$commentmessage = strip_tags($commentmessage);
$commentmessage = htmlentities($commentmessage, ENT_QUOTES);
What code would I use to strip out anything that might cause a MySQL error?
The message I am receiving is:
Error message: SQLSTATE[42000]: Syntax error or access violation: 1064 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 'omg thats the one". One of the logo's we really liked was 1049859 where the f' at line 2**
Evidently you're building your query like so:
$query = "INSERT INTO foo VALUES ('$bar')";
which is breaking because the text of $bar contains single quotes. '
No. *hits you with a rolled-up newspaper* Bad developer.
I could just throw you a string escaping function, or I could show you to do it right like:
$bar = "I am a problematic string!'; DROP TABLE USERS -- "
$query = "INSERT INTO foo VALUES (?)";
$stmt = $dbh->prepare($query);
$stmt->execute(array($bar));
Or:
$bar = "I am a problematic string!'; DROP TABLE USERS -- "
$query = "INSERT INTO foo VALUES (:bar)";
$stmt = $dbh->prepare($query);
$stmt->execute(array('bar'=>$bar));
When you prepare a query like this PHP/PDO/MySQL get together and pre-agree on what types your placeholders are. So your strings are treated like strings without the need for escaping characters. This both prevents rogue single quotes from breaking your query, and help protect you from SQL injection attacks.
You can also re-use prepared statements to increase performance: [relative to un-prepared statements since the SQL only needs to be parsed once, rather than once per query]
$query = "INSERT INTO foo VALUES (?)";
$stmt = $dbh->prepare($query);
foreach( $bars as $bar ) {
$stmt->execute(array($bar));
}
I'm new to sql and PHP. So far have been able to figure things out but the PREPARE statement is giving me syntax issues (maybe because I'm trying to do several things in one step). If someone could let me know where my syntax is messing up that would be great.
In addition the code I'm writing is trying to update save files on a server and while I believe doing it with a prepare statement is the correct way I would be happy to hear if it is not. Note I plan to change INSERT INTO -> a conditional insert or update.
The error I get is unexpected T_STRING. I've marked the line of the error in the code.
$sql='PREPARE statement FROM "INSERT INTO buildings VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) WHERE id="$id" AND ind="$i""';
$result=mysql_query($sql);
for($i=0;$i<1600;$i+=1){
if(isset($_POST['ind'.$i])){
$bind=$_POST['bind'.$i];
$time=$_POST['time'.$i];
$level=$_POST['level'.$i];
$p1ind=$_POST['p1ind'.$i];
$p1state=$_POST['p1state'.$i];
$p1time=$_POST['p1time'.$i];
$p2ind=$_POST['p2ind'.$i];
$p2state=$_POST['p2state'.$i];
$p2time=$_POST['p2time'.$i];
$p3ind=$_POST['p3ind'.$i];
$p3state=$_POST['p3state'.$i];
$p3time=$_POST['p3time'.$i];
$p4ind=$_POST['p4ind'.$i];
$p4state=$_POST['p4state'.$i];
$p4time=$_POST['p4time'.$i];
$p5ind=$_POST['p5ind'.$i];
$p5state=$_POST['p5state'.$i];
$p5time=$_POST['p5time'.$i];
$sql = 'SET #bind="$bind",'. //<-line of error
'#time="$time",'.
'#level="$level",'.
'#p1ind="$p1ind",'.
'#p1state="$p1state",'.
'#p1time="$p1time",'.
'#p2ind="$p2ind",'.
'#p2state="$p2state",'.
'#p2time="$p2time",'.
'#p3ind="$p3ind",'.
'#p3state="$p3state",'.
'#p3time="$p3time",'.
'#p4ind="$p4ind",'.
'#p4state="$p4state",'.
'#p4time="$p4time",'.
'#p5ind="$p5ind",'.
'#p5state="$p5state",'.
'#p5time="$p5time",'.
'#id="$id",'.
'#ind="$i"';
$result=mysql_query($sql);
$sql='EXECUTE statement USING #id,#time,#level,#p1ind,#p1state,#p1time,#p2ind,#p2state,#p2time,#p3ind,#p3state,#p3time,#p4ind,#p4state,#p4time,
#p5ind,#p5state,#p5time,#ind,#bind';
$result=mysql_query($sql);
if(!$result){
die("saveArry[0]=".mysql_error().";");
}else{
die("saveArry[0]='saved';");
}
}
}
$sql='DEALLOCA PREPARE statement';
$result=mysql_query($sql);
Update I am unable to install PDO on my hosts servers and therefore PDO is unfortunately an unacceptable solution. My answer (now with no errors!):
if(isset($_POST['ind'])){
$ind=sanitizeString($_POST['ind']);
$bind=sanitizeString($_POST['bind']);
$time=sanitizeString($_POST['time']);
$level=sanitizeString($_POST['level']);
$p1ind=sanitizeString($_POST['p1ind']);
$p1state=sanitizeString($_POST['p1state']);
$p1time=sanitizeString($_POST['p1time']);
$p2ind=sanitizeString($_POST['p2ind']);
$p2state=sanitizeString($_POST['p2state']);
$p2time=sanitizeString($_POST['p2time']);
$p3ind=sanitizeString($_POST['p3ind']);
$p3state=sanitizeString($_POST['p3state']);
$p3time=sanitizeString($_POST['p3time']);
$p4ind=sanitizeString($_POST['p4ind']);
$p4state=sanitizeString($_POST['p4state']);
$p4time=sanitizeString($_POST['p4time']);
$p5ind=sanitizeString($_POST['p5ind']);
$p5state=sanitizeString($_POST['p5state']);
$p5time=sanitizeString($_POST['p5time']);
$rot=sanitizeString($_POST['rot']);
$sql="INSERT INTO buildings (id,ind,bind,time,level,p1ind,p1state,p1time,p2ind,p2state,p2time,p3ind,p3state,p3time,p4ind,p4state,p4time,p5ind,
p5state,p5time,rot) VALUES ('$id','$ind','$bind','$time','$level','$p1ind','$p1state','$p1time','$p2ind','$p2state','$p2time','$p3ind','$p3state',
'$p3time','$p4ind','$p4state','$p4time','$p5ind','$p5state','$p5time','$rot') ON DUPLICATE KEY UPDATE bind='$bind',time='$time',level='$level',
p1ind='$p1ind',p1state='$p1state',p1time='$p1time',p2ind='$p2ind',p2state='$p2state',p2time='$p2time',p3ind='$p3ind',p3state='$p3state',
p3time='$p3time',p4ind='$p4ind',p4state='$p4state',p4time='$p4time',p5ind='$p5ind',p5state='$p5state',p5time='$p5time',rot='$rot'";
$result=mysql_query($sql);
if(!$result){
die("saveArry[0]=".mysql_error().";");
}else{
die("saveArry[0]=saved;");
}
}
The single and double quotes are interchanged in that line, should be,
$sql = "SET #bind='$bind',
#time='$time',
#level='$level',
#p1ind='$p1ind',
#p1state='$p1state',
#p1time='$p1time',
#p2ind='$p2ind',
#p2state='$p2state',
#p2time='$p2time',
#p3ind='$p3ind',
#p3state='$p3state',
#p3time='$p3time',
#p4ind='$p4ind',
#p4state='$p4state',
#p4time='$p4time',
#p5ind='$p5ind',
#p5state='$p5state',
#p5time='$p5time',
#id='$id',
#ind='$i'";
I strongly recommend using PDO instead of deprecated mysql_* functions. It is doing the hard work with prepared statements for you transparently.
As EthanB pointed out in comment, your code is vulnerable to SQL injection as you are inserting the values directly from user input ($_POST variable).
With PDO your code would look something like this (simplified):
$statement = $pdo->prepare("INSERT INTO buildings VALUES(:ind, :bind, :time, :level, ...) WHERE id = :id AND ind = :ind");
for( ... ) {
$statement->execute(array(
":ind" => $_POST["ind" . $i],
":bind" => $_POST["bind" . $i], ...
));
}
The PDO will send the PREPARE and EXECUTE queries for you and escape all parameters to prevent SQL injection.
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.
I'm trying how best to prepare my SQLite SQL strings in PHP. The SQLite3 class comes with an escapeString() function, but here are my issues:
Try 1)
$sql = "INSERT INTO items ('id','content','title','created') VALUES ('4e7ce7c18aac8', 'Does this work', NULL, '2011-09-23T16:10:41-04:00');";
$sql = SQLite3::escapeString( $sql );
echo ($sql);
This results in a string that's all jacked up:
INSERT INTO items (''id'',''content'',''title'',''created'') VALUES
(''4e7ce7c18aac8'', ''Does this work'', NULL,
''2011-09-23T16:10:41-04:00'');
Those aren't double quotes, rather doubled-up single quotes. Obviously won't work.
Try 2)
$sql = 'INSERT INTO items ("id","content","title","created") VALUES ("4e7ce7c18aac8", "Does this work", NULL, "2011-09-23T16:10:41-04:00");';
$sql = SQLite3::escapeString( $sql );
echo ($sql);
This results in:
INSERT INTO items ("id","content","title","created") VALUES
("4e7ce7c18aac8", "Does this work", NULL,
"2011-09-23T16:10:41-04:00");
This query works fine, but the escapeString function hasn't modified anything as there's nothing to escape...
Try 3)
$sql = 'INSERT INTO items ("id","content","title","created") VALUES ("4e7ce7c18aac8", "Doesn't this work", NULL, "2011-09-23T16:10:41-04:00");'; $sql = SQLite3::escapeString( $sql ); echo ($sql);
Here's the big problem- Now I have an apostrophe in one of my values. It won't even make it to escapeString() because PHP will throw an error on the invalid string:
PHP Parse error: syntax error, unexpected T_VARIABLE, expecting ','
or ';'
How am I supposed to be approaching this? Keep in mind that in the actual code my parameter values will be variables, so am I supposed to escape each variable before I pass it into the string? If so, what function do I use?
Finally, what's the point of escapeString()?? I can't figure out how it's supposed to be used correctly.
You don't escape the entire query. You escape unsafe data you're inserting into the query, e.g.
$unsafe = $_GET['nastyvar'];
$safe = SQLite3::escapeString($unsafe);
$sql = "INSERT INTO table (field) VALUES ($safe);";
echo ($sql);
I am trying to insert values in database and values are not being inserted, here is the code i have:
$user_name = "username";
$password = "password";
$database = "database";
$server = "localhost";
$db_handle = mysql_connect($server, $user_name, $password);
$db_found = mysql_select_db($database, $db_handle);
if ($db_found) {
$SQL = 'INSERT INTO table (anInt, DomainName, URL, Rank, PageRank, Google, Bing, Boss, IndexedPage, Backlinks) VALUES ($anInt, $Domain, $URL, $Rank, $Pagerank, $Google, $Bing, $Yahoo, $Pages, $backlinks)';
$result = mysql_query($SQL);
mysql_close($db_handle);
print "Records added to the database";
it is printing that records added to the database but when looking at the database nothing is being added. some of the values are doubles, text, and ints. Is there anyway to debug this? I will be adding more information to the post if someone asks me to.
and of course I have an else statement i just thought it is not relevant since it is telling me that records are added.
First of all, you should escape the string values you are passing into the SQL query, using mysql_real_escape_string.
Then, you should add quotes, in your SQL query, arround the fields that are meant to contain strings.
I don't really know which fields are integers and which fields are strings, but you should be using something like this to build your SQL query :
// Escape the string data, and make sure integer really contain integers
$anInt = intval($anInt);
$Domain = mysql_real_escape_string($Domain);
$URL = mysql_real_escape_string($URL);
$Rank = intval($Rank);
$Pagerank = = intval($Pagerank);
$Google = intval($Google);
$Bing = intval($Bing);
$Yahoo = intval($Yahoo);
$Pages = intval($Pages);
$backlinks = intval($backlinks );
// Build the SQL query, using the "safe" variables
$SQL = 'INSERT INTO table (anInt, DomainName, URL, Rank, PageRank, Google, Bing, Boss, IndexedPage, Backlinks)
VALUES ($anInt, '$Domain', '$URL', $Rank, $Pagerank, $Google, $Bing, $Yahoo, $Pages, $backlinks)';
This is supposing that only DomainName and URL are meant to contain strings -- you might have to use mysql_real_escape_string and add quotes arround the values for some other fields too, if needed.
Then, you should take a look at the return value of mysql_query : for an insert query, in case of an error, it'll return false.
Here, if your $result variable is false, you should use mysql_error and mysql_errno : they'll allow you to know what error happened -- it will help detecting errors in your SQL query, for instance.
If this doesn't solve the problem, you should try outputting the SQL query, and run it using something like phpMyAdmin, to make sure it's OK.
I am no PHP expert, but I have 2 remarks.
You don't check the error (perhaps with mysql_errno()) so you don't know whether the records were added
I think the values, if they are strings, should be given like
'$Domain'
that is, escaped with ' characters.
better would be, of course, using something like
$sql = sprintf("INSERT ... VALUES(%d, '%s', '%s',...)",
$anInt, mysql_real_escape_string($Domain), ...);
if you insert user-supplied input.
You could examine the $result:
$result = mysql_query($query);
if (!$result) {
print "An error occured: " . mysql_error() . "\n";
}
My guess is that you're passing a string without quotes, like:
VALUES (Hello)
where you should pass it like:
VALUES ('Hello')
Like the commenter said, if the user can control these strings, you are open to an SQL Injection attack. You can prevent that attack by escaping the strings, for example:
$query = sprintf("INSERT INTO table (DomainName) VALUES ('%s')",
mysql_real_escape_string($domain_name));
In SQL queries, you need to enquote strings correctly, or it will produce an error. So all your variables that are used to store non-int or non-boolean values in the database need quotes around the values.
Additionally you should make sure that SQL injections are not a problem by escaping all values with mysql_real_escape_string first.
Apart from sql injections your error handling is not complete...
if (!$db_found) {
echo "datbase not found.";
}
else {
$SQL = 'INSERT INTO
table
(...)
VALUES
(...)
';
$result = mysql_query($SQL, $db_handle);
if ( !$result ) {
echo "error: ", mysql_error($db_handle);
}
else {
print "Records added to the database";
}
}
mysql_close($db_handle);
In case a query causes an error mysql_query() return FALSE and mysql_error() will tell you more about the error.
Well there are security issues with the code but to address one problem
you are not enclosing your string values in quotes in the SQL statement.
First of all, please regard everybody else's advice on safe database handling and avoiding injection.
The reason your query isn't doing anything is probably that you enclosed the string in single quotes. In PHP single quotes enforce the string to be literal. Unlike when using double quotes, variables will NOT be substituted. So '$foo' represents the sequence of characters '$'.'f'.'o'.'o'. "$foo" on the other hand represents the sequence of characters of whatever the variable $foo contains at the time of the string's definition.
You can use mysql_error() to catch most problems with MySQL. Even if the message isn't helping you, you at least know whether the query was parsed properly, i.e. on which end of the connection the problem lies.