Adding a variable interval to a variable timestamp - php

Ok, first of all I have very little clue how to use php, and only a slightly better understanding of sql. So if anything I do appears really, really stupid, please bear with me.
Given a user input of a date, a time and a time interval, I need to get two timestamps without timezones - a starting time, and an endtime.
e.g.
function myfunction($startdate, $starttime, $numhours){
$start = $startdate.' '.$starttime;
//I know this works for a timestamp because I have used this value in other sql statements and have been returned the correct results
$handler = $connection->prepare("SELECT TIMESTAMP :start + INTERVAL :numhours ' HOURS'");
$handler->bindParam(':start', $start);
$handler->bindParam(':numhours', $numhours);
$handler->execute();
$end = $handler->fetchAll();
This just gets me the following error:
Submitting booking.SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near "$1" LINE 1: SELECT TIMESTAMP $1 + INTERVAL $2 ' HOURS'
I haven't been able to find anything that really tells me what I'm doing wrong here (which is probably a lot). Help is appreciated.
EDIT: I'm using postgreSQL, through `pgAdmin III
EDIT: $start should have the form 'YYYY-MM-DD HH:MM:SS'

The problem is, you use the literal notation with values (parameters) and not with constants.
The literal notation only accepts contants, like:
SELECT TIMESTAMP '2014-05-25 14:29:59' + INTERVAL 3 HOUR;
It cannot accept values (expressions) other than constants (and bound parameters are not constants.):
-- this will throw a syntax error
SELECT TIMESTAMP CONCAT('2014-05-25', ' ', '14:29:59');
You can use the CAST form over the literal notation here:
$handler = $connection->prepare('SELECT CAST(:start AS TIMESTAMP) + ' .
'CAST(:numhours || \' hours\' AS INTERVAL)');
$handler->bindParam(':start', $start);
$handler->bindParam(':numhours', $numhours);
$handler->execute();
EDIT: or, you can use PDO::ATTR_EMULATE_PREPARES to use real literals inside your query, but I believe postgres' own prepare functionality is better a choice.

Related

mySQL Workbench Error: Syntax Error, unexpected single quotes

I was trying to make a SQL statement in PHP, to convert a string into a time(6). But I have tried everything, for the last 12 hours, and have not made an inch of progress. I have tried these statements, all yield the same error.
UPDATE scheduling SET start='03:42PM' WHERE activityid=2;
UPDATE scheduling SET start=CONVERT(TIME(6),'03:42PM');
INSERT INTO scheduling(start) VALUES (start=CONVERT(TIME(6),'03:42PM'));
INSERT INTO scheduling(start) VALUES (start=CONVERT(TIME(6),'03:42PM'));
INSERT INTO scheduling(start) VALUES (start=CONVERT(TIME(6),'15:42'));
The error is
Syntax Error: unexpected '03:42PM'(single quoted text)"
I do not know how to fix this, the table exists, and i have sucesfully got other info using statements like SELECT activityid=2 FROM xxxxxx.scheudling
I guess I have two questions, either answer would work.
In my PHP document, how would I convert a string I get in from an Android Studio volley to a date. (I get the variable correctly, with $start=$_Post("start"), so that works, but I cant convert it into a time. I looked online, and tried everything that looked like it work work.
Conversion through SQL Code, I already tried CAST and CONVERT, neither works. My start column is type TIME(6).
I recommend testing expressions using a SELECT statement.
Firstly, the MySQL CONVERT function arguments are flipped around backwards.
The syntax is CONVERT(expr,type)
And type is supplied as a keyword, not a string literal. For example:
SELECT CONVERT('235',SIGNED)
To convert to a TIME datatype
SELECT CONVERT( '15:42' ,TIME(6)) // => 15:42:00.000000
The 'PM' part of the string literal will be ignored.
SELECT CONVERT( '03:42PM' ,TIME(6)) // => 03:42:00.000000
We can use the STR_TO_DATE function to return a TIME value from a string that contains the AM/PM indicator
SELECT STR_TO_DATE( '03:42PM' ,'%h:%i%p')
And there's no need to cast that to TIME(6), we can do this:
UPDATE scheduling
SET start = STR_TO_DATE( '03:42PM' ,'%h:%i%p')
WHERE activityid = 2
The STR_TO_DATE function is documented here:
https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_str-to-date
The format patterns for STR_TO_DATE are documented here, under DATE_FORMAT:
https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-format
FOLLOWUP
Demonstration:
setup
USE test;
CREATE TABLE scheduling (activityid INT PRIMARY KEY, start TIME(6));
-- 0 row(s) affected
INSERT INTO scheduling (activityid) VALUES (2);
-- 1 row(s) affected
execute the update statement in the answer above
UPDATE scheduling SET start = STR_TO_DATE( '03:42PM' ,'%h:%i%p') WHERE activityid = 2 ;
-- 1 row(s) affected
results
SELECT * FROM scheduling WHERE activityid = 2;
-- activityid start
-- ---------- ---------------
-- 2 15:42:00.000000
SECOND FOLLOWUP
Use same sql_mode setting reported by OP:
SET ##sql_mode = 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' ;
Test:
SELECT STR_TO_DATE( '03:42PM' ,'%h:%i%p')
returns
(NULL)
But this more complicated expression:
SELECT TIME(STR_TO_DATE(CONCAT(CURRENT_DATE(),' ', '03:42PM' ),'%Y-%m-%d %h:%i%p'))
returns
15:42:00
The more complicated expression is a workaround to avoid behavior imposed by the STRICT_TRANS_TABLES and NO_ZERO_DATE in the sql_mode.

oci_execute(): ORA-01840: input value not long enough for date format

I am currently receiving the following error message from oci in php (I've been on it for a few hours).
oci_execute(): ORA-01840: input value not long enough for date format
It strange, because when I run the query within SQL Developer it seems to work fine.
This makes me think that when I bind the parameter it is turning the dates into a type that is not able to calculate using conventional operators in oracle.
$startDateTime = '2015-03-06 00:00:00';
$endDateTime = '2015-04-06 00:00:00';
$value = '20';
$type = '$';
$SQL = "SELECT count(*) AS \"COUNT\"
FROM bonus where value = :d_value
AND TYPE = :d_type
AND ((:d_valid_from between valid_from AND valid_till) OR (:d_value_till between valid_from AND valid_till) OR (:d_valid_from < valid_from AND valid_till < :d_valid_till))";
$this->stmnt = $this->conn->prepare($SQL);
$this->stmnt->bindParam('d_valid_from', $startDateTime);
$this->stmnt->bindParam('d_valid_till', $endDateTime);
$this->stmnt->bindParam('d_value', $value);
$this->stmnt->bindParam('d_type', $type);
$this->stmnt->execute();
I am unable to find many resources that deal with php directly with this problem in hand. Does anybody have any experience with it?
I think that your dates are being bound as strings in the query. Assuming that the columns you are comparing it to (e.g. valid_from) are dates, then the string value is being converted to a date using the default date format for the sessions. The difference in behavior in SQL Developer is probably because the default format is different.
Anyway, the solution is to follow a very simple and important rule, which is not to rely on default type conversion. Explicitly convert the string to a date in your query, specifying the appropriate format:
TO_DATE( :d_valid_from, 'YYYY-MM-DD HH24:MI:SS' )

Filtering by date range in SQL query

I am unable to get the following code to work:
// dd/mm/yyyy for dates in SQL queries
$todayforw = date('d/m/Y');
$aweekago = date('d/m/Y', time() - 604800);
$week_e_check = mysql_query("SELECT * FROM earningslog WHERE user_id = '".$info['id']."' WHERE day >='".$aweekago."' AND day <'".$todayforw."'");
while ($week_e_info = mysql_fetch_array($week_e_check)) {
$week_e = $week_e + $week_e_info['user_earnings_amnt'];
}
The query returns zero rows, however, it should be returning data that matches the criteria.
Check your date format:
Should be:
YYYY-mm-dd HH:mm:ss
E.G.
2012-01-01 00:00:00 (January 1, 2012 at midnight local time)
Other date formats MAY work, but the best way to go about it is to use the same format that MySQL uses when they display the date, that's the only way I know that works every time.
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html
Also your syntax is incorrect, you have two wheres, you should use AND.
Take a closer look at your query:
SELECT * FROM earningslog WHERE user_id = '".$info['id']."' WHERE day >='".$aweekago."' AND day <'".$todayforw."'"
Your Where clause appears twice.
Two things to think about - when you are selecting data, try and stay away from select * - you may get unexpected results of the table is ever modified.
Second, try and create the query as a parameterized query, instead of injecting the parameters directly into the where clause. By directly injecting your criteria the way you have, you are opening yourself up to a SQL injection attack.
By turning it into a parameterized query, you get the side benefit of being able to debug the queries directly against the database, reducing the amount of effort needed to copy it from a query tool into your code.
Your issue appears to be with your query syntax. You are stating WHERE twice, whereas you should only state it once and then use the AND or OR operators for further criteria. I would also suggest that you either move your statement into a variable or use die() to assist with debugging.
$week_e_check = mysql_query("SELECT * FROM earningslog WHERE user_id = '".$info['id']."' AND day >='".$aweekago."' AND day <'".$todayforw."'") or die(mysql_error());
In addition, you should not be using the mysql extension as use of this extension is discouraged. Instead, use the MySQLi or PDO_MySQL extension. Using one of these alternative extensions will help serve as the first step in preventing SQL injection. I would also suggest that you avoid using * and specify the column names to be returned instead.
Using PDO:
<?php
/* Execute a prepared statement by passing an array of values */
$sth = $dbh->prepare('SELECT * FROM earningslog WHERE user_id = ? AND day >= ? AND day < ?');
$sth->execute(array($info['id'], $aweekago, $todayforw));
$results = $sth->fetchAll();
?>
Try change the format of your strings from from d/m/Y to Y-m-d.
MySQL might be expecting it year first. In which case it could be doing the wrong thing with d/m/Y.
Also don't use the WHERE clause twice. Instead, combine conditions using AND, eg:
WHERE user_id = '".$info['id']."'
AND day >='".$aweekago."'
AND day <'".$todayforw."'
By the way, you can also try saying WHERE day BETWEEN ".$aweekago." AND ".$todayforw.", which might be easier syntax to read (as long as you change $todayforw to be the day before).

Compare string datatype to a date datatype PHP MYSQL

In my MySQL database, I have this Time data type as one of my values: 06:00:00. I have the following query that checks the time as one of the conditions that has to be satisfied
$time = "06:00:00";
$getdetails=SELECT First_Name, Last_Name, EMAIL
FROM parents
WHERE Email_Receive_Time = $time;
$results=mysql_query($getdetails);
However I do not get any results. On further research I have seen that it is because I am comparing a STRING type value ($time) to a TIME type value (value in my database). Is there a way i can compare the two without changing my database structure to a varchar? All help will be appreciated.
MySQL is perfectly capable of comparing a string to a TIME value. You just need to have the proper query syntax. In your case, you need to quote the comparison value:
$time = "06:00:00";
$getdetails = "SELECT First_Name, Last_Name, EMAIL
FROM parents
WHERE Email_Receive_Time = '$time'";
$results=mysql_query($getdetails);
And if it is user-supplied, well you should escape it.
You are wrong.
Your mistake is much simpler, it has nothing to do with data formats, but with query format.
Ask yourself what does mean 06:00:00 in terms of SQL syntax.
Btw, running query this way will help you A LOT:
$results=mysql_query($getdetails) or trigger_error(mysql_error()." in ".$getdetails);
always run all your queries this way and get in touch with every error occurred
This will work when comparing against TIME type of field:
To compare against DATETIME or TIMESTAMP, I'd suggest running the $time variable through strotime() first.
$time = "06:00:00";
$getdetails = "SELECT First_Name,
Last_Name,
EMAIL
FROM parents
WHERE Email_Receive_Time = '$time'";
$results = mysql_query($getdetails);
Try using STR_TO_DATE function, it should work for you.
Thanks
Ravi Mudaliar

Format Date field type

i have a csv file that i'm interest and the date format is 20-Nov-2010 how do I format it for insertion into mysql accepted format for a field with Date as its type?
date("Y-m-d", strtotime("20-Nov-2010"));
Andreas' answer is a bit terse - in PHP this will return a string which you can splice
into your query:
$d=date("Y-m-d", strtotime("20-Nov-2010"));
$qry="INSERT INTO sometable (adate) VALUES('$d')";
But if you omit the punctuation, you can ad it without the quotes:
$d=date("Ymd", strtotime("20-Nov-2010"));
$qry="INSERT INTO sometable (adate) VALUES($d)";
A drawback of this approach is that strtotime() tends to always return some sort of date value - and sometimes not what you expect.
However you could do the parsing in MySQL, which is a lot more strict:
$d='20-Nov-2010';
$qry="INSERT INTO sometable (adate) VALUES(STR_TO_DATE($d, '%d-%b-%Y'))";
But remember to check for errors when mysql tries to parse the date.

Categories