Is this query safe to use? Prepared statement? - php

Is this query safe to use? I'm not sure how I'd convert it to a prepared statement as it's not using any values from the user:
$result = mysqli_query($cxn, "SELECT * FROM table WHERE datetime > DATE_SUB(NOW(), INTERVAL 15 DAY) ORDER BY RAND() LIMIT 1");
while ($row = mysqli_fetch_array($result)) {
$title = $row['title'];
echo $title;
}
Is this safe to use? How can I improve it?
Thanks.

Yes, it's safe. There is no user input used there at all; nothing that has the potential to mess up the query syntax or manipulate the outcome in any way.
As for improvements, there is no need to return every field in the table if you are only using the title field. In general, you should avoid the wild-card (*) for SELECT queries, except for testing purposes.
Also, the DATE_SUB(NOW(), INTERVAL 15 DAY) can be reduced to just NOW() - INTERVAL 15 DAY. Shorter and sweeter; no unnecessary function calls.

The biggest improvement you can make is to change
SELECT * FROM table WHERE datetime > DATE_SUB(NOW(), INTERVAL 15 DAY) ORDER BY RAND() LIMIT 1
to
SELECT title FROM table WHERE datetime > DATE_SUB(NOW(), INTERVAL 15 DAY) ORDER BY RAND() LIMIT 1
because you are only using the title column in your code.

Yes it is safe. It's best to use prepared statement if you decided to pass parameter to your sql.
here is example for you with parameter :
$stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?');
$stmt->bind_param('s', $name);
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
// do something with $row
}
here is example/answer for your sql:
$stmt = $dbConnection->prepare('SELECT * FROM table WHERE datetime > DATE_SUB(NOW(), INTERVAL 15 DAY) ORDER BY RAND() LIMIT 1');
$stmt->execute();
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
// do something with $row
}

Related

PHP Postgres Using Special Input Values With Intervals

I'm trying to select a date within the time period of one day. A simple query like this will do the trick:
SELECT *
FROM table_name
WHERE table_name.the_date > DATE_SUB(CURDATE(), INTERVAL 1 DAY)
My problem is I am using prepared statements with pg_execute/PDO(the problem is the same in both). For example:
$query = "SELECT *
FROM table_name
WHERE table_name.the_date > $1";
$params = array('DATE_SUB(CURDATE(), INTERVAL 1 DAY)')
$results = pg_prepare($dbconn, '' , $query );
$results = pg_execute($dbconn, '', $params);
The result is that it always errors out with:
pg_execute(): Query failed: ERROR: invalid input syntax for type timestamp:
Now I now there is special postgres functions that can be used as indicated in this link: http://www.postgresql.org/docs/9.0/static/datatype-datetime.html#AEN5582 . Now I've replaced NOW() with the special input 'now' , but there is still an error with the 'INTERVAL 1 DAY' .
How can I get around this?
I don't get why you'd want to use bind variables here.
You can simply do:
$query = "SELECT *
FROM table_name
WHERE table_name.the_date > DATE_SUB(CURDATE(), INTERVAL 1 DAY)";
$params = array();
$results = pg_prepare($dbconn, '' , $query);
$results = pg_execute($dbconn, '', $params);
If you want the ability to change the interval, you must still hard-code any syntax elements, although you should be able to dynamically configure the size of the interval.
$query = "SELECT *
FROM table_name
WHERE table_name.the_date > DATE_SUB(CURDATE(), INTERVAL $1 DAY)";
$params = array('1');
$results = pg_prepare($dbconn, '' , $query);
$results = pg_execute($dbconn, '', $params);

SQL order by date, time [duplicate]

This question already exists:
SQL order by date, time [duplicate]
Closed 9 years ago.
I have table named notify with (seeker, donor, date) columns
the date column of type (datetime) and it stores the following format YYYY-MM-DD HH:MM:SS I'm trying to SELECT 1 record with the latest date from notify table and then compare the date with the current date and calculate the number of days between tow dates..
<?php
session_start();
$email = $_GET['email'];
date_default_timezone_set('Asia/Riyadh');
$time = date("Y-m-d H:i:s");
$note = "SELECT * FROM notify WHERE seeker='".$_SESSION['email']."'AND donor='".$email."' ORDER_BY `date` DESC LIMIT 1";
$st = $conn->prepare($note);
$st->execute();
if($found = $st->fetch(PDO::FETCH_ASSOC)){
$now = $time;
$old_date = strtotime($found['date']);
$dateif = $now - $old_date;
if(floor($dateif/(60*60*24)) >= 7){
echo "the difference between tow dates is 7 days or more";
} else { echo "difference between tow dates is less than 7 days";}
}
?>
the code is not working ! i have only one record in my notify table with this value in date 2013-04-22 09:15:47
First of all, you should use prepared statements like this:
$note = "SELECT *
FROM notify
WHERE seeker=:seeker AND donor=:donor
ORDER BY `date` DESC
LIMIT 1";
$st = $conn->prepare($note);
$st->execute(array(
':seeker' => $_SESSION['email'],
':donor' => $email,
);
Without the place holders you're still open to SQL injection.
Second, you can't compare a string with an integer in this way:
$now = $time; // string
$old_date = strtotime($found['date']); // integer
$dateif = $now - $old_date; // dunno?
You should compare apples with apples:
$seven_days_ago = strtotime('-7 days');
$old_date = strtotime($found['date']);
if ($old_date > $seven_days_ago) {
echo "difference between tow dates is less than 7 days";
} else {
echo "the difference between tow dates is 7 days or more";
}
Since your date column doesn't exist, there's no point in ordering by it. Also, you're exposed to SQL injection in the case where $_SESSION['email'] is not secured.
So, the correct form would be to use prepared statements, as well as order by the right column. (assuming PDO, you can use mysqli as well):
/** #var PDO $pdo - Assuming a PDO connection. */
$query = "SELECT * FROM `user` WHERE `ID` = :email ORDER BY `time` DESC";
$stmt = $pdo->prepare($query);
$stmt->execute(array($_SESSION['email']));
$result = $stmt->fetchAll(PDO::FETCH_ASSOC); //Get all results in an associated array form.
Jack's answer shows you how to use prepared statements correctly. Here is the code to simplify the date calculation using DATEDIFF().
$note = "SELECT *, DATEDIFF(NOW(), `date`) AS date_diff
FROM notify
WHERE seeker=:seeker AND donor=:donor
ORDER_BY `date` DESC
LIMIT 1";
$st = $conn->prepare($note);
$st->execute(array(
':seeker' => $_SESSION['email'],
':donor' => $email,
);
$row = $st->fetch(PDO::FETCH_ASSOC);
// do something with $row
If you are attching any variables to string then you need to concatinate them using dot and oder by will come after where condition and inside $_SESSION you missed quotes
$query = "SELECT * FROM user WHERE ID='".$_SESSION['email']."' ORDER_BY date, time";
For retrieving latest date from database please try executing following sql query
$query="SELECT * FROM user WHERE ID='".mysql_real_escape_string($_SESSION[email])."' ORDER_BY date,time desc limit 1";
In order to retrieve latest date you need to sort field for date in descending order
$note = "SELECT * FROM notify WHERE seeker=' ".$_SESSION['email']. " ' AND donor=' ".$email." ' ORDER_BY date DESC LIMIT 1";
have you try to order by desc? as shown bellow:
$note = "SELECT * FROM notify
WHERE
seeker=' ".$_SESSION['email']. " '
AND
donor=' ".$email." ' ORDER_BY date DESC LIMIT 1";
you forgot ` here around date. date is reserved word in mysql,
if you want to use it as column name place ` around it.
EDIT also you have extra space remove it
$note = "SELECT * FROM notify WHERE seeker='".$_SESSION['email']. "'
AND donor='".$email."' ORDER_BY `date` LIMIT 1";

ORDER_BY date LIMIT 1 [duplicate]

This question already exists:
SQL order by date, time [duplicate]
Closed 9 years ago.
I have table named notify with (seeker, donor, date) columns
the date column of type (datetime) and it stores the following format YYYY-MM-DD HH:MM:SS I'm trying to SELECT 1 record with the latest date from notify table and then compare the date with the current date and calculate the number of days between tow dates..
<?php
session_start();
$email = $_GET['email'];
date_default_timezone_set('Asia/Riyadh');
$time = date("Y-m-d H:i:s");
$note = "SELECT * FROM notify WHERE seeker='".$_SESSION['email']."'AND donor='".$email."' ORDER_BY `date` DESC LIMIT 1";
$st = $conn->prepare($note);
$st->execute();
if($found = $st->fetch(PDO::FETCH_ASSOC)){
$now = $time;
$old_date = strtotime($found['date']);
$dateif = $now - $old_date;
if(floor($dateif/(60*60*24)) >= 7){
echo "the difference between tow dates is 7 days or more";
} else { echo "difference between tow dates is less than 7 days";}
}
?>
the code is not working ! i have only one record in my notify table with this value in date 2013-04-22 09:15:47
First of all, you should use prepared statements like this:
$note = "SELECT *
FROM notify
WHERE seeker=:seeker AND donor=:donor
ORDER BY `date` DESC
LIMIT 1";
$st = $conn->prepare($note);
$st->execute(array(
':seeker' => $_SESSION['email'],
':donor' => $email,
);
Without the place holders you're still open to SQL injection.
Second, you can't compare a string with an integer in this way:
$now = $time; // string
$old_date = strtotime($found['date']); // integer
$dateif = $now - $old_date; // dunno?
You should compare apples with apples:
$seven_days_ago = strtotime('-7 days');
$old_date = strtotime($found['date']);
if ($old_date > $seven_days_ago) {
echo "difference between tow dates is less than 7 days";
} else {
echo "the difference between tow dates is 7 days or more";
}
Since your date column doesn't exist, there's no point in ordering by it. Also, you're exposed to SQL injection in the case where $_SESSION['email'] is not secured.
So, the correct form would be to use prepared statements, as well as order by the right column. (assuming PDO, you can use mysqli as well):
/** #var PDO $pdo - Assuming a PDO connection. */
$query = "SELECT * FROM `user` WHERE `ID` = :email ORDER BY `time` DESC";
$stmt = $pdo->prepare($query);
$stmt->execute(array($_SESSION['email']));
$result = $stmt->fetchAll(PDO::FETCH_ASSOC); //Get all results in an associated array form.
Jack's answer shows you how to use prepared statements correctly. Here is the code to simplify the date calculation using DATEDIFF().
$note = "SELECT *, DATEDIFF(NOW(), `date`) AS date_diff
FROM notify
WHERE seeker=:seeker AND donor=:donor
ORDER_BY `date` DESC
LIMIT 1";
$st = $conn->prepare($note);
$st->execute(array(
':seeker' => $_SESSION['email'],
':donor' => $email,
);
$row = $st->fetch(PDO::FETCH_ASSOC);
// do something with $row
If you are attching any variables to string then you need to concatinate them using dot and oder by will come after where condition and inside $_SESSION you missed quotes
$query = "SELECT * FROM user WHERE ID='".$_SESSION['email']."' ORDER_BY date, time";
For retrieving latest date from database please try executing following sql query
$query="SELECT * FROM user WHERE ID='".mysql_real_escape_string($_SESSION[email])."' ORDER_BY date,time desc limit 1";
In order to retrieve latest date you need to sort field for date in descending order
$note = "SELECT * FROM notify WHERE seeker=' ".$_SESSION['email']. " ' AND donor=' ".$email." ' ORDER_BY date DESC LIMIT 1";
have you try to order by desc? as shown bellow:
$note = "SELECT * FROM notify
WHERE
seeker=' ".$_SESSION['email']. " '
AND
donor=' ".$email." ' ORDER_BY date DESC LIMIT 1";
you forgot ` here around date. date is reserved word in mysql,
if you want to use it as column name place ` around it.
EDIT also you have extra space remove it
$note = "SELECT * FROM notify WHERE seeker='".$_SESSION['email']. "'
AND donor='".$email."' ORDER_BY `date` LIMIT 1";

php MySQL query not returning anything

I'm not sure exactly how to explain what the query does, however the problem isn't entirely with how it's set up, because it does work, in another instance, when I use it as an array, however it's not working when I use it with mysql_fetch_assoc(), so here is what my original query is(not the one im having trouble with):
SELECT * FROM
(SELECT * FROM comments
WHERE postID='$id' AND state='0'
ORDER BY id DESC LIMIT 3
) t ORDER BY id ASC
what this does is selects the last 3 comments on a post, then orders them in another way (so they show up in the correct order, old to new) Now this is the query for echoing out the array of comments directly.
But now what I want to do, is to just get the first id out of the 3 comments.
here's what I have tried to do (and by the way, this query DOES work, when i replace my previous query to echo out the results in an array, but i need to get just the id for use, i don't want an array):
$previousIDq = mysql_fetch_assoc(mysql_query("
SELECT * FROM
(SELECT * FROM comments
WHERE postID='$id' AND state='0'
ORDER BY id DESC LIMIT 3
) t ORDER BY id ASC LIMIT 1"));
$previousID = $previousIDq['id']; //this doesn't return the id as I want it to.
Your problem may be that there are no matching rows.
Also, I think you could also improve your query to this:
SELECT * FROM comments WHERE postID='$id' AND state='0' ORDER BY id DESC LIMIT 2,1
But as others say, use PDO or MySQLi, and with prepared statements. And don't SELECT * ever.
try a var_dump($previousID) to see what you get
It is probably giving you back an object, and you need to get your id from that object
You script is too condensened for error handling, let alone debugging
$mysql = mysql_connect(...
$query = "
SELECT * FROM
(SELECT * FROM comments
WHERE postID='$id' AND state='0'
ORDER BY id DESC LIMIT 3
) t ORDER BY id ASC LIMIT 1
";
$result = mysql_query($query, $mysql);
if ( !$result ) { // query failed
die('<pre>'.htmlspecialchars(mysql_error($mysql)).'</pre><pre>'.htmlspecialchars($query).'</pre>');
}
$previousIDq = mysql_fetch_assoc($result);
if ( !$previousIDq ) {
die('empty result set');
}
else {
$previousID = $previousIDq['id'];
}
You need to separate your code to be able to debug
$query = "SELECT * FROM
(SELECT * FROM comments
WHERE postID='$id' AND state='0'
ORDER BY id DESC LIMIT 3
) t ORDER BY id ASC LIMIT 1";
$result = mysql_query($query);
echo mysql_error(); //what eror comes out here
while($previousIDq = mysql_fetch_assoc($result))
{
print ($previousIDq['id']);
}
NOTE: mysql_* is depreciated, upgrade to mysqli or PDO
Please stop using mysql_ functions to write new code, it is being deprecated. Use mysqli_ or PDO functions (mysqli below).
Bind your parameters to prevent SQL injection
Always use a column list (don't use SELECT *)
If you're returning > 1 row, use a while loop
mysqli_ solution
$link = mysqli_connect("localhost", "user_name", "password", "stock");
if (mysqli_connect_error()) {
die('Connect Error (' . mysqli_connect_errno() . ') ' . mysqli_connect_error());
}
$stmt = mysqli_prepare($link, "SELECT t.id FROM
(SELECT id FROM comments
WHERE postID = ? AND state = 0
ORDER BY id DESC
LIMIT 3) t
ORDER BY id ASC");
mysqli_bind_param($stmt, 's', $id) or die(mysqli_error($dbh));
$result = mysqli_stmt_execute($stmt) or die(mysqli_error($link));
while($row = mysqli_fetch_assoc($result)) {
echo $row[id];
}
mysqli_close($link);
mysql_ solution
$stmt = "SELECT t.id FROM
(SELECT id FROM comments
WHERE postID = $id AND state = 0
ORDER BY id DESC
LIMIT 3) t
ORDER BY id ASC";
$result = mysql_query($stmt) or die(mysql_error());
$row = mysql_fetch_assoc($result);
while($row = mysql_fetch_assoc($result)) {
echo $row[id];
}

Echoing out a date from a query

I would like $minutes below to be the oldest datecommented from the query (expressed in minutes). When I echo $minutes out, I get a blank result. What am I doing wrong?
$queryuidcount = "SELECT loginid, datecommented
FROM comment
WHERE (HOUR(NOW()) - HOUR(datecommented)) <= 1
AND loginid = '$uid'
ORDER BY datecommented ASC
LIMIT 1'";
$row2 = mysql_fetch_array($queryuidcount);
$minutes = $row2["datecommented"];
You need to execute mysql_query() on your query before you call mysql_fetch_array() on the result. Try this:
$result = mysql_query('SELECT loginid, datecommented FROM comment WHERE (HOUR(NOW()) - HOUR(datecommented)) <= 1 AND loginid = '$uid' ORDER BY datecommented ASC LIMIT 1');
$row = mysql_fetch_array($result);
$minutes = $row['datecommented'];
If your query returns multiple rows, you'll need to iterate through them with a while loop:
while($row = mysql_fetch_array($result)) {
//Fetch values from $row
}
Also, consider using PDO instead of the mysql function family.
I think you are doing it in the wrong way. Here you can find some examples.
mysql_fetch_array is not for DB connection or sql query.
http://php.net/manual/en/function.mysql-fetch-array.php

Categories