Sum Column with Oracle 11 and PHP - what's wrong? - php

Trying to get a simply query going through and its not working - newbie here.
Other php files and queries do run well.
$sql = "select sum(rese_nshw) as noshows from tnht_eseo where edta_data = '19.10.01'" ;
$sumParse = oci_parse($conn, $sql);
oci_define_by_name($sumParse, "noshows", $total);
oci_execute($sumParse);
while(oci_fetch($sumParse)){
echo "noshows:". $total;
}
what's wrong ? just outputs blank.
Running the SQL query in Oracle directly, it outputs 6 as NOSHOWS for this query.

If EDTA_DATA is date (datatype), don't compare it to a string as '19.10.01' is a string. Oracle will implicitly try to convert it to appropriate date, but that doesn't have to work always. Besides 19.10.01 can be anything (2019 Oct 01, or 19 Oct 2001, or ...), depends on NLS settings.
Take control over it; see whether using date literal helps (it always has yyyy-mm-dd format):
where edta_data = date '2019-10-01'
Furthermore, if edta_data contains time component (hours, minutes, seconds), then the simplest option is to truncate it, e.g.
where trunc(edta_data) = date '2019-10-01'
but it'll prevent Oracle from using index on that column (if it exists). It can be fixed, no problem; but - first see whether anything of above helps.

You have to use Upper Case as defined here:
column_name The column name used in the query.
Use uppercase for Oracle's default, non-case sensitive column names.
Use the exact column name case for case-sensitive column names.
from: https://www.php.net/manual/en/function.oci-define-by-name.php
Then:
oci_define_by_name($sumParse, "NOSHOWS", $total);

Related

Problematic DateTime Comparison SQL Query Not Working

I have a problem with executing ODBC query. I am trying to achieve something simple.
SELECT t.* FROM table t WHERE DateTime > '#2014-05-05 00:00:00#'
I have tried to execute with or without hashes (#) and quotes around the datetime, but no success with that. Also, instead of using >, < and other comparison operators I have tried to use BETWEEN.
In addition several formats "dd/mm/yyyy", "mm/dd/yyyy", "dd.mm.yyyy", etc. plus standard sql format (iso) were tested and the result is the same.
The approach looks like:
$sql = "SELECT t.* FROM table t WHERE DateTime > '#...#'";
$result = odbc_fetch_array(odbc_exec($odbc_connection, $sql));
After this execution I receive some 5-10 symbol binary error, but no error message (with odb_error and odbc_errormsg), in addition to the:
No tuples available at this result index
(The topic: ODBC error in PHP: “No tuples available at this result index” is not helping)
Could it be some ODBC issue (old version etc.) or we should cast another black magic through odbc_exec?
Maybe ODBC have trouble with reserved word datetime.
I don't know how to escape quotes in PHP, try
SELECT t.* FROM table t WHERE t."DateTime" > '20140505'";
You should use ODBC syntax for datetimes which is { ts '1998-05-02 01:23:56.123' }. You can omit the partial seconds. See here.
Have you tried using the TO_DATE() function? You can specify the format you are using.
SELECT t.* FROM table t WHERE DateTime > TO_DATE('2014-05-05 00:00:00','YYYY-MM-DD HH24:MI:SS')

phpAdmin shows rows, MySQL statement doesn't?

EDIT
Provided as requested is here how the Date column looks:
Jan 15, 2014
Jan 16, 2014
Aug 10, 2014
So what i am trying to achieve, is extract every row that contains Jan 2014, so i get every row for that month in that year.
Here is my PHP code that generates the query:
$monthYearString = $month . "%" . $year;
$query_current = "SELECT * FROM {$table_omsaetning} WHERE 'Date' LIKE " . "'{$monthYearString}'";
echo $query_current;
The echo gives me this query: SELECT * FROM table_name_here WHERE 'Date' LIKE 'Jan%2014'
Original question
I have a very weird issue here.
If i perform a search using phpAdmin provided by my hosting site, and search for rows that are like a certain date, it conjures up this SQL statement, and it finds 3 rows:
SELECT *
FROM `table_name`
WHERE `Date` LIKE 'Jan%2014'
BUT, when I try to do the same thing either using SQL statements in phpAdmin or my own code, it shows NOTHING? How come? It is 100% the same statement. Really can't understand how I can search using the built-in phpAdmin function, and then it generates that SQL statement, and then when I try to inject it myself, it just returns 0 rows instead of 3.
Hope it makes sense.
The difference between single quotes and backticks is important here. You have quoted your column name instead of using backticks. It should be:
SELECT * FROM table_name_here WHERE `Date` LIKE 'Jan%2014'
The backtick character (see the Date column in the query above) allows you to indicate it's a name rather than a string. In this case, if you didn't have these, you would get an error because Date is a reserved word. The backtick allows you to use reserved words for table and column names.
Where as the single quote means it's a string. In the case of your query, you were essentially searching for any records where the string 'Date' contains the string 'January 2014' which isn't possible and will always return zero results.
For more information, check out this SO question: When to use single quotes, double quotes, and backticks in MySQL
Your code should look like this:
$monthYearString = $month . "%" . $year;
$query_current = "SELECT * FROM {$table_omsaetning} WHERE `Date` LIKE '{$monthYearString}'";
echo $query_current;

mysql date compare query gives wrong results

I have this table and the query I give returns wrong results, I am not sure where the problem is
the date comparisons
or
structure of the query
The query if not clear in the image is :
select * from transact where item_code='msft234' or item_code='hp550x' and transact_date>=STR_TO_DATE('06-07-2013','%d-%m-%Y') and transact_date<=STR_TO_DATE('12-07-2013','%d-%m-%Y')
Your query employs a wrong syntax:
WHERE item_code='msft234' OR item_code='hp550x'
AND transact_date>=STR_TO_DATE('06-07-2013','%d-%m-%Y')
AND transact_date<=STR_TO_DATE('12-07-2013','%d-%m-%Y')
since AND priority is higher, it means that it will be satisfied if either you get hp550x in that date interval, or you get msft234 regardless of the date.
You have to put the OR'ed item codes in parentheses: (item_code='..' OR item_code='..' OR ..), or use IN: e.g.
SELECT * FROM transact
WHERE item_code IN ('msft234', 'hp550x')
AND transact_date BETWEEN
STR_TO_DATE('06-07-2013','%d-%m-%Y')
AND
STR_TO_DATE('12-07-2013','%d-%m-%Y')
Also, depending on the type you select for the date fields, consider that for a date to be "less or equal than 12-07-2013", it has to be less or equal than 12-07-2013 at 00:00, i.e., almost the latest date that will match is 11-07-2013 at 23:59:59.
So "less or equal than 12-07" will actually never select any row from 12-07-2013 unless it happens to have been inserted exactly at midnight.
If you insert rows by only specifying the date, then it will very probably work - the rows will be input at midnight and matched at midnight. But if (some) rows are entered with the full datetime, e.g. because they're type datetime and updated with NOW(), then they will not match.
put the item conditions between ()
(ítem_code = 'msft234' OR ítem_code = 'hp550x') AND transact_date>=STR_TO_DATE('06-07-2013','%d-%m-%Y') and transact_date<=STR_TO_DATE('12-07-2013','%d-%m-%Y')
(ítem_code = 'msft234' OR ítem_code = 'hp550x') AND transact_date BETWEEN STR_TO_DATE('06-07-2013','%d-%m-%Y') and STR_TO_DATE('12-07-2013','%d-%m-%Y')
For security I will put with 2 ()
(ítem_code = 'msft234' OR ítem_code = 'hp550x') AND (transact_date BETWEEN STR_TO_DATE('06-07-2013','%d-%m-%Y') and STR_TO_DATE('12-07-2013','%d-%m-%Y'))

How to Handle (Escape) a % sign in mysqlclient (C Library)

i am using mysqlclient,
in one of my query, as shown below
sprintf (query, "select user from pcloud_session where id = '%s'", sid);
here some time this sid is with % sign in it like the example
2Cq%yo4i-ZrizGGQGQ71eJQ0
but when there is this % this query always fail, i think i have to escape this %, but how ?
i tried with \ and %% , but both of this not working, please help me here
UPDATE:
When using session.hash_bits_per_character = 6, in php session ,the default charset contains a character (comma) that will always be urlencoded(here it is %2C). This results in cookie values having this %2C in it, but session db having a comma instead of it. any idea about fixing this problem ?.. sorry for the confusion
Thanks
There's no need to escape a literal '%' in MySQL query text.
When you say the query "always fail", is it the call to the mysql_query function that is returning an error? Does it return a SQL Exception code, or is it just not returning the resultset (row) you expect?
For debugging, I suggest you echo out the contents of the query string, after the call to sprintf. We'd expect the contents of the string to be:
select user from pcloud_session where id = '2Cq%yo4i-ZrizGGQGQ71eJQ0'
And I don't see anything wrong with that SQL construct (assuming the id column exists in pcloud_session and is of character datatype. Even if id was defined as an integer type, that statement wouldn't normally throw an exception, the string literal would just be interpreted as integer value of 2.)
There should be no problem including a '%' literal into the target format of an sprintf. And there should be no problem including a '%' literal within MySQL query text.
(I'm assuming, of course, that sid is populated by a call to mysql_real_escape_string function.)
Again, I suggest you echo out the contents of query, following the call to sprintf. I also suggest you ensure that no other code is mucking with the contents of that string, and that is the actual string being passed as an argument to mysql_query function. (If you are using the mysql_real_query function, then make sure you are passing the correct length.)
UPDATE
Oxi said: "It does not return a SQL Exception code, it just does not return the result[set] I expect. I did print the query, it prints with % in it."
#Oxi
Here's a whole bunch of questions that might help you track down the problem.
Have you run a test of that query text from the mysql command line client, and does that return the row(s) you expect?
Is that id column defined as VARCHAR (or CHAR) with a length of (at least) 24 characters? Is the collation on the column set as case insensitive, or is it case sensitive?
show create table pcloud_session ;
(I don't see any characters in there that would cause a problem with characterset translation, although that could be a source of a problem, if your application is not matching the database charactarset encoding.)
Have you tested queries using a LIKE predicate against that id column?
SELECT id, user FROM pcloud_session WHERE id LIKE '2Cq\%yo4i-%' ESCAPE '\\'
ORDER BY id LIMIT 10 ;
SELECT id, user FROM pcloud_session WHERE id LIKE '2Cq%'
ORDER BY id LIMIT 10 ;
Are you getting no rows returned when you expect one row? Are you getting too many rows returned, or are you getting a different row than the one you expect?
That is an oddball value for an id column. At first, it looks almost as if the value is represented in a base-64 encoding, but it's not any standard encoding, since it includes the '%' and the '-' characters.
If you're going to do this in C without an interface library, you must use mysql_real_escape_string to do proper SQL escaping.
There shouldn't be anything intrinsically wrong with using '%inside of a string, though, as the only context in which it has meaning is either directly inprintftype functions or as an argument toLIKE` inside of MySQL.
This proves to be really annoying, but it's absolutely necessary. It's going to make your code a lot more complicated which is why using low-level MySQL in C is usually a bad idea. The C++ wrapper will give you a lot more support.
You really shouldn't escape the string yourself. The safest option is to let the MySQL API handle it for you.
For a string of maximum length n, start by allocating a string of length 2*n+1:
int sidLength = strlen(sid);
// worst-case, we need to escape every character, plus a byte for the ASCIIZ
int maxSafeSidLength = sidLength * 2 + 1;
char *safeSid = malloc(maxSafeSidLength);
// copy "sid" to "safeSid", escaping as appropriate
mysql_real_escape_string(mysql, safeSid, sid, sidLength);
// build the query
// ...
free(safeSid);
There's a longer example at the mysql_real_escape_string page on dev.mysql.com, in which they build the entire query string, but the above approach should work for supplying safeSid to sprintf.

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).

Categories