No results from PL/SQL query, but there should be. - php

I know there are several question about this error, also for php.
I've tried most of the answers and nothing seems to work.
This is my query :
"select
id,
employeenr,
name,
section,
description,
duration,
to_date(substr(startdate,0,12)||' '||starttime, 'DD-MM-YYYY HH24:MI:SS') starttime,
to_date(substr(enddate,0,12)||' '||endtime, 'DD-MM-YYYY HH24:MI:SS') endtime,
worktime,
statement,
remark
from
data
where 1=1
".$vw."
AND startdate between to_date(':df 00:00:00', 'DD-MM-YYYY HH24:MI:SS') and to_date(':dt 23:59:59', 'DD-MM-YYYY HH24:MI:SS')
".$vw1."
order by nvl(employeenr,0), startdate";
$parameters = array(':df' => $date_from, ':dt' => $date_to);
Echo var vw:
AND ( employeenr between '100000' and '199999'OR employeenr between '400000' and '499999'OR employeenr between '700000' and '799999'OR (employeenr is not null AND employeenr between '100000' and '199999'OR employeenr between '400000' and '499999'OR employeenr between '700000' and '799999'))
$date_from and $date_to:
$date_from = $_POST["date_from"]; // jQuery datepicker value
$date_to = $_POST["date_to"]; // jQuery datepicker value
What am I doing wrong?

How is $Parameters used later? It looks as if you want to use it as a bind varibale array to pass later to Oracle. If so, then you use this incorrectly, because rather than holding a variable's value the string contains SQL. This is not how bind variables work in Oracle.
You must give Oracle a complete query to parse, only that values in the query can be unknown (a date, a number or a string). These you can pass later. You cannot parse half a query and add more SQL in a variable later.
So AND ? cannot be parsed, as no value makes sense here. Something like AND X = ? could be parsed on the other hand, as Oracle would expect to get the value to compare column X with later when the query gets executed.

New question, new answer.
Still you don't use your bind variable for a variable (date, number or string), but try to replace part of a string with it. This doesn't work.
':df 00:00:00' is a string containing a colon followed by a 'd', an 'f', etc.
Use a bind variable for a complete string, i.e.:
AND startdate >= to_date(:date_from, 'DD-MM-YYYY')
AND startdate < to_date(:date_to, 'DD-MM-YYYY') + 1
or
AND TRUNC(startdate) BETWEEN to_date(:date_from, 'DD-MM-YYYY')
AND to_date(:date_to, 'DD-MM-YYYY')
or
AND startdate between to_date(:date_from || ' 00:00:00', 'DD-MM-YYYY HH24:MI:SS')
and to_date(:date_to || ' 23:59:59', 'DD-MM-YYYY HH24:MI:SS')

SOLUTION
I have been able to fix my problem by stripping out the substr in the SELECT area of the query.
$sql_report = "
select
id,
employeenr,
name,
section,
description,
duration,
startdate,
starttime,
enddate,
endtime,
worktime,
statement,
remark
from
data
where 1=1
".$vw."
AND startdate BETWEEN to_date('$date_from', 'DD-MM-YYYY') AND to_date('$date_to', 'DD-MM-YYYY')
".$vw1."
order by nvl(employeenr,0), startdate";
$parameters = array();

Related

PHP oci_fetch_all from an Oracle DB converts date value

I'm having issues getting a value from an Oracle DB where the value is converted to a date format I don't want. I'd prefer to have the raw value, or at least know where I can change that converted date format. Curious if anyone could point me in the right direction here.
$conn = oci_connect(ORACLE_DB_USERNAME, ORACLE_DB_PASSWORD, '//' . ORACLE_DB_HOST . '/' . ORACLE_DB_SID);
$sql_query = "SELECT * FROM \"ASSET\".\"NAV\" WHERE sem = '2820' AND ROWNUM = 1 ORDER BY date_time DESC";
$stid = oci_parse($conn, $sql_query);
$row_count = oci_fetch_all($stid, $res, null, null, OCI_FETCHSTATEMENT_BY_ROW + OCI_ASSOC);
oci_free_statement($stid);
oci_close($conn);
The data in the DB should come back like:
CREATE_DATE => '23-07-2019 19:30:11'
Except, I get this:
CREATE_DATE => '23-JUL-19'
You are getting dates back in the default format of your database. One thing that you could to is alter the NLS setting of your session to the format that you expect. For this, you can run this command:
alter session set nls_date_format = 'dd-mm-yyyy hh24:mi:ss'
Once this command is executed, all dates will be fetched in this format during the lifetime of your Oracle session.
If you are dealing with timestamp datatype instead of date, then the nls parameter is nls_timestamp_format (and nls_timestamp_tz_format for timestamp with timezone).
Another option is to use to_char() to format the date to the desired format in the query itself:
$sql_query = "SELECT <column list>, to_char(create_date, 'dd-mm-yyyy hh24:mi:ss') create_date FROM ...";

Error while calling stored procedure through php. Literal does not match format string

I am using Oracle 10g Express Edition with PHP codeigniter.
I have a table tbl_movie:-
CREATE TABLE tbl_movie (movie_id NUMBER(11) PRIMARY KEY,
movie_title VARCHAR2(255) NOT NULL,
movie_image VARCHAR2(255) NOT NULL,
language_id NUMBER(11) NOT NULL REFERENCES tbl_language(language_id) ON DELETE CASCADE,
showtime_id NUMBER(11) NOT NULL REFERENCES tbl_showtime(showtime_id) ON DELETE CASCADE,
movie_sdate DATE NOT NULL,
movie_edate DATE NOT NULL,
movie_add_date DATE NOT NULL
);
Now I have created a procedure by running it through the Oracle Command Line:-
CREATE OR REPLACE PROCEDURE
insertMovie (id IN NUMBER, title IN VARCHAR2, image IN VARCHAR2, language IN NUMBER, showtime IN NUMBER, sdate IN DATE, edate IN DATE, adate IN DATE, message OUT NUMBER)
IS
BEGIN
INSERT INTO tbl_movie (movie_id, movie_title, movie_image, language_id, showtime_id, movie_sdate, movie_edate, movie_add_date)
VALUES ( id, title, image, language, showtime, TO_DATE(sdate, 'YYYY-MM-DD hh24:mi:ss'), TO_DATE(edate, 'YYYY-MM-DD hh24:mi:ss'), TO_DATE(adate, 'YYYY-MM-DD hh24:mi:ss'));
message := 1;
EXCEPTION
WHEN OTHERS THEN
message := 0;
END;
/
This is the code from my codeigniter controller:-
public function testMovie()
{
$insertData['movie_id'] = 1;
$insertData['movie_title']= 'test';
$insertData['movie_image']= 'rfgt';
$insertData['language_id']= 1;
$insertData['showtime_id']= 1;
$insertData['movie_sdate']= '2017-02-24 00:00:00';
$insertData['movie_edate']= '2017-02-27 00:00:00';
$insertData['movie_add_date']= '2017-02-20 00:00:00';
$this->load->model('oracle_model');
$return = $this->oracle_model->add_movie('movie',$insertData,'');
}
And this is the model function which is for calling the procedure:-
function add_movie($entity,$insertData,$time)
{
print_r($insertData);
$conn = oci_connect("xxxxxx", "xxxxxx","xxxxxxxxx");
if(!$conn)
{
echo "connect failed".oci_error();
}
else
{
echo "connect done at".date('d-m-y');
// calling stored procedure insertMovie
$insertMovieProcedureSQL = "BEGIN insertMovie(:id, :title, :image, :language, :showtime, :sdate, :edate, :adate, :message); END;";
$stmt = oci_parse($conn, $insertMovieProcedureSQL);
// Bind the input parameter
oci_bind_by_name($stmt,':id',$insertData['movie_id']);
oci_bind_by_name($stmt,':title',$insertData['movie_title']);
oci_bind_by_name($stmt,':image',$insertData['movie_image']);
oci_bind_by_name($stmt,':language',$insertData['language_id']);
oci_bind_by_name($stmt,':showtime',$insertData['showtime_id']);
oci_bind_by_name($stmt,':sdate',$insertData['movie_sdate']);
oci_bind_by_name($stmt,':edate',$insertData['movie_edate']);
oci_bind_by_name($stmt,':adate',$insertData['movie_add_date']);
// Bind the output parameter
oci_bind_by_name($stmt,':message',$message);
oci_execute($stmt);
// $message is now populated with the output value
echo "$message\n";
}
}
When I am running the function, I am getting the following error:-
oci_execute(): ORA-01861: literal does not match format string ORA-06512: at line 1
When I tried to run the procedure by eliminating all the date datatype columns, the code is running fine. I think the main problem is with the Date columns.
But when I run this query from the command line, data gets successfully inserted:-
INSERT INTO tbl_movie (movie_id, movie_title, movie_image, language_id, showtime_id, movie_sdate, movie_edate, movie_add_date)
VALUES ( 2, 'title', 'image', 2, 3, TO_DATE('2017-02-24 00:00:00', 'YYYY-MM-DD hh24:mi:ss'), TO_DATE('2017-02-27 00:00:00', 'YYYY-MM-DD hh24:mi:ss'), TO_DATE('2017-02-20 00:00:00', 'YYYY-MM-DD hh24:mi:ss'));
What am I doing wrong? I am stuck for nearly 4 hours.
The procedure parameters sdate etc. are of DATE data type. Within your procedure, you apply TO_DATE( ...., 'yyyy-mm-dd hh24:mi:ss') to them.
TO_DATE is used to convert strings to dates, not dates to dates. If you apply TO_DATE to a date, Oracle first converts the date to a string, so that it can be passed to TO_DATE. Unfortunately, when Oracle does that implicit conversion, it doesn't use the same format model you have in TO_DATE; rather, it uses the nls_date_format of the session that invoked the procedure. Which is not the same as the model in TO_DATE - which causes the error you saw.
There are two ways to solve this. One is to not use TO_DATE(sdate, ...) but use just sdate in the INSERT statement. sdate and the others are dates already (if they were passed correctly as dates to the procedure in the first place).
The second is, if in fact you meant that the arguments are passed in as strings, don't declare them as DATE in the procedure declaration; declare them VARCHAR2. (And make double-sure those strings are exactly in the correct format - you should be able to control that from the front-end.)
Whenever you see TO_DATE(....) applied to a DATE input, expect an error like the one you saw. Conversely, whenever you see an error like that, suspect code like TO_DATE(....) applied to a date.
Added: There is also another possibility. If in fact you are passing strings to the procedure, Oracle must convert them to dates (because they are declared as such). If the strings aren't exactly in the format of the nls_date_format of the session invoking the procedure, this initial conversion of the parameters from strings to dates will fail and the INSERT statement won't even be reached.
Change the datatype of input parameters from date to varchar. In current scenario, you are basically applying to_date on a date datatype. Once you replace date with varchar, your rest of the logic should work.
CREATE OR REPLACE PROCEDURE
insertMovie (id IN NUMBER, title IN VARCHAR2, image IN VARCHAR2, language IN NUMBER, showtime IN NUMBER, sdate IN VARCHAR2, edate IN VARCHAR2, adate IN VARCHAR2, message OUT NUMBER)
IS
BEGIN
INSERT INTO tbl_movie (movie_id, movie_title, movie_image, language_id, showtime_id, movie_sdate, movie_edate, movie_add_date)
VALUES ( id, title, image, language, showtime, TO_DATE(sdate, 'YYYY-MM-DD hh24:mi:ss'), TO_DATE(edate, 'YYYY-MM-DD hh24:mi:ss'), TO_DATE(adate, 'YYYY-MM-DD hh24:mi:ss'));
message := 1;
EXCEPTION
WHEN OTHERS THEN
message := 0;
END;
/

How can I filter record by start time / end time in mysql + codeigniter

The table structure is like that
start_time TimeStamp null
end_time TimeStamp null
The problem is , I would like to get all record within the start time and endtime, and all the value that has null start time & end time value (that means the record is not restrict by time)
$this->db->where('start_date <=', now());
$this->db->where('end_date >', now());
tried some sql for the first requirement but no luck , thanks for helping
It sounds like the query logic you need would go something like this:
...
WHERE NOW() BETWEEN start_date AND end_date
OR (start_date IS NULL AND end_date IS NULL)
To do this with Codeigniter's Active Record, try:
$this->db->where('NOW() BETWEEN start_date AND end_date');
$this->db->or_where('start_date IS NULL AND end_date IS NULL');
Alternatively, you could put the whole thing into one statement:
$where = 'NOW() BETWEEN start_date AND end_date OR (start_date IS NULL AND end_date IS NULL)';
$this->db->where($where);
You would probably need to have a compound query.
$within_range = array('start_date <=' => now(), 'end_date =>' => now());
$not_restricted = array('start_date IS NULL' => null, 'end_date IS NOT NULL' => null)
$this->db->where($within_range)->or_where($not_restricted);
see more about the associative array and or_where syntax at https://ellislab.com/codeigniter/user-guide/database/active_record.html#select
of course you can query using raw sql:
$this->db->select('select ...');

Does MySQL automatically re-format dates inserted in to a column of type DATETIME?

I understand the format of DATETIME in MySQL is YYYY-MM-DD HH:MM:SS.
I am using Bootstrap datepicker which posts a value like 07/30/2014. How can I get that changed to '2014-07-30 00:00:00`?
I don't want the user to see hours etc. but it must be in the string. Is datepicker able to output a string like this?
SQL
$stmt = $dbh->prepare("INSERT INTO bookings (forename, surname, site, badge, start, end) VALUES (:forename, :surname, :site, :badge, :start, :end)");
...
$stmt->bindParam(':start', $start);
$stmt->bindParam(':end', $end);
yes it is ,but if its a string you should you use STR_TO_DATE() to convert it like this :
$msql ="insert into table (birthdate)value(STR_TO_DATE('$yourdate','%d/%m/%Y'))";
mysql_query($msql);
what i did :
i converted the string $yourdate to a DateTime value.
PS : the %d/%m/%Y should be the format of the date in your string not the one on the server example :
if you had a date like this 22/2/2014 that should work fine, but if you had it like this : 2/22/2014 you should give it this :'%m/%d/%Y'

How to split time left in days,hours,minutes,seconds in query

Below is my table structure
Now I am in need of a query in whicn I can display the days,hours,minutes,second left for that event.
I have use this query
select title,`date`,subject ,TIMESTAMPDIFF(DAY, CONVERT_TZ(NOW(),##session.time_zone, '+05:30'),'2013-05-25 12:00:00') as dayleft ,TIMESTAMPDIFF(HOUR, CONVERT_TZ(NOW(),##session.time_zone, '+05:30'),'2013-05-25 12:00:00') as hourleft from jos_holidays where `date` > CONVERT_TZ(NOW(),##session.time_zone, '+05:30')
and the above results me
But my need to get exact time left includes days,hours,minutes and seconds and display it in seperate columns. Can I achive this in query? Though this can be achievable in PHP.
Also the date "2013-05-25 12:00:00" value in query is hard coded . Can be make it dynamic too.
Thanks
Query:
SQLFIDDLEExample
SELECT title,
`date`,
subject ,
TIMESTAMPDIFF(DAY, CONVERT_TZ(NOW(),##session.time_zone, '+05:30'), `date`) AS dayleft,
TIMESTAMPDIFF(HOUR, CONVERT_TZ(NOW(),##session.time_zone, '+05:30'), `date`)
- TIMESTAMPDIFF(DAY, CONVERT_TZ(NOW(),##session.time_zone, '+05:30'), `date`)*24 AS hourleft,
TIMESTAMPDIFF(MINUTE, CONVERT_TZ(NOW(),##session.time_zone, '+05:30'), `date`) -
TIMESTAMPDIFF(HOUR, CONVERT_TZ(NOW(),##session.time_zone, '+05:30'), `date`)* 60 AS minuteleft,
TIMESTAMPDIFF(SECOND, CONVERT_TZ(NOW(),##session.time_zone, '+05:30'), `date`)-
TIMESTAMPDIFF(MINUTE, CONVERT_TZ(NOW(),##session.time_zone, '+05:30'), `date`)*60 AS secondleft
FROM jos_holidays
WHERE `date` > CONVERT_TZ(NOW(),##session.time_zone, '+05:30')
Try like
$diff = strtotime($date) - time();
echo "tile left is ".date('Y-m-d H-m-i',$diff);
In PHP you can use
$now = new DateTime(); // or use any start date you want
$date = new DateTime($row['date']); // your sql query result
$diff = $now->diff($date);
This makes $diff a DateInterval object that contains all the information you are looking for. It does require PHP 5.3+.
I'm not sure if it would be possible to get the same information directly from MySQL. But I would assume that it's mainly for display purposes, so calculating this in PHP from available information is not too much overhead.
its work i have used this query
SELECT
TIMESTAMPDIFF(DAY,NOW(),'2013-06-23') AS dafLeft,
TIMESTAMPDIFF(HOUR,NOW(),'2013-06-23')-TIMESTAMPDIFF(DAY,NOW(),'2013-06-23')*24 AS hourLeft,
TIMESTAMPDIFF(MINUTE,NOW(),'2013-06-23')-TIMESTAMPDIFF(HOUR,NOW(),'2013-06-23')*60 AS minLeft,
TIMESTAMPDIFF(SECOND,NOW(),'2013-06-23')-TIMESTAMPDIFF(MINUTE,NOW(),'2013-06-23')*60 AS secLeft;
For dynamic just '2013-06-23' to your field name (date field name) and fetch like you do in other table.
Happy coding!! :)

Categories