I've a database with lon and lat geo location data.
Both are saved as float / decimal attribute in the mysql table.
Now I want to compare this stuff like:
(u.user_location_lat <= ".$lat_max." AND u.user_location_lat >= ".$lat_min.") AND
(u.user_location_long <= ".$long_max." AND u.user_location_long >=".$long_min.")
But it does not show any result (and it should!) - but also no error.
How to EASILY solve this (I actually don't want to work with spatial indexes - at least I do not understand how to do)?
Thanks.
I recommend you verify what that statement looks like, after you do the variable substitution.
That is, echo or vardump the contents of the variable containing the SQL text, before you prepare/execute the SQL statement.
There doesn't appear to be anything wrong with the form of the predicates. (These could be written using equivalent BETWEEN comparators, but it's not a problem what you have written.)
It's possible you have the min and max values swapped, or have the longitude and latitude swapped. If that's not the issue, then I suspect that the variables being substituted may be represented in scientific notation, rather than as decimal values.
e.g. the SQL text gets generated
... u.lat <= 1.241E+2 ...
rather than
... u.lat <= 124.1 ...
In the former case, MySQL is going to evaluate that literal as decimal value of 1.241.
(There's a corner case issue when the bounding box crosses the +180/-180 boundary, but I don't see that's likely a problem for most of your values, that's going to be an exceptional case, which you would probably need to setup special test case to actually have happen.)
In order to debug this, you need the actual SQL text that's being sent to the database to be prepared/executed.
(There's not enough information in your question to identify the actual problem.)
Q: How do I get the actual SQL text?
A: Construct your SQL statement as a string into a variable; and then var_dump that variable for debugging:
$sqltext = "SELECT ... WHERE u.lat <= ". $lat_max . " AND u.lat ... ";
var_dump($sqltext);
$stmt = mysqli_prepare($db, $sqltext);
Related
I'm trying to update a table called RAC_PV at my oracle database but the query is returning that error when i run my application. I thing everyting is right because i run the same query on sqldeveloper (but with manual values) and when i change the variable $preco_medio to a number like 1, it works on the application. Here's my code:
$preco_medio = number_format(($v_interna_real / $encargo + $vipe_real) / $v_interna_t + $vipe_t , 2, ",", ".") ;
sc_exec_sql("update RAC_PV set PRECO_MEDIO = $preco_medio where rac_anopv = {ano} and rac_mespv = {mes} and codempresa = $id_empresa and codpainel = 6 and cod_prod1 = '$id_produto'");
My table name and the column names are right and checked, my variables like {ano}, {mes}, $id_produto and $preco_medio are all corretly seted. This sc_exec_sql("query here") works fine. Maybe the problem is in the $preco_medio ? I've never used that number_format but when a echo this the number shows right for me like 3,123.03 .
Can anyone help me?
3,123.03
That's not a number literal, that's two numbers, 3 and 123.03, one of which is apparently interpreted as column name. Remove the grouping , in the number literal expression or use TO_NUMBER() and a string literal with the formatted number representation.
The best way however would be not to build queries by string concatenation but parametrized queries. String concatenation is prone to SQL Injection. Also parametrized queries find the right representation for the DBMS (usually and mostly) automatically, avoiding such problems you have here.
In my database i have 2 columns namely: Min and Max they are varchar and they have number values which i need to compare with. My query is something like this
SELECT * FROM Pricing_tbl WHERE Productid='10'
and i have this to compare the price
while ($selected_row = $stmt - > fetch(PDO::FETCH_ASSOC)) {
if ($marketval > $selected_row['Min'] && $marketval < $selected_row['Max']) {
$price[] = array('price_level' => $selected_row['price_level']);
}
}
This is ok if values of Min and Max are always numbers. But there is an instance where the value of Max is above. How to compare this situation?
Example values will be
Or should i just change the Max value. Any suggestion is appreciated
Assuming a maximum of above means all the way to infinity and you want to keep the data as is 1, you can just change the condition:
$marketval > $selected_row['Min'] && $marketval < $selected_row['Max']
into something like:
$marketval >= $selected_row['Min'] &&
($selected_row['Max'] == 'above' || $marketval < $selected_row['Max'])
In other words a value is considered under the maximum always if the maximum is the word above. Otherwise the actual (original) comparison decides.
PHP short-circuiting on logical operators will ensure that the second half of the or section will never be evaluated if the first half is true.
Note the change I made to the minimum comparison as well, the use of >= rather than >. As it was, a value like 300000.01 would not have been caught.
You may also want to coerce the numerics in the comparisons with $marketValue. If both $marketValue and $selectedRow['whatever'] are strings, I think they'll still use numeric comparison but I usually try to be explicit so I don't have to think about it :-)
1 There are probably better ways to do this, other than storing what's mostly numeric data as strings just because you want to be able to store the value 'above'.
Both methods below involve converting the column type to a numeric one which will allow better comparisons, including having the DBMS itself work it out rather than having to get all data and post-process it with PHP. Data manipulation is what a DBMS does best so it's generally better to leave that manipulation up to the DBMS for efficiency.
The first is to put a ridiculously large number in the maximum for the 'above' row so that your simple 'in between min and max' check will work. Using the DBMS itself to get the pricing level would be a simple:
select pricing_level
from pricing_tbl
where product_id = '10'
and $market_val >= minval
and $market_val < maxval
That will give you a single row containing the correct pricing level.
The second is to store NULL in that column instead of a string. A nullable numeric column will still work with a slight modification:
select pricing_level
from pricing_tbl
where product_id = '10'
and $market_val >= minval
and ($market_val < maxval or maxval is null)
In both those cases, you may want to translate the upper region (large number or null) to and from the word above when presenting or editing the table itself. This will make the process look the same even though the underlying data has changed.
i have 2 columns namely: Min and Max they are varchar
this is wrong. It should be int or at least decimal values
My query is something like this
this is wrong. Your query should include $marketval to do all the calcs on the database side.
here is an instance where the value of Max is above.
this is wrong. No numerical column should ever contain a string. you can store a big number there. or a NULL, but not a string.
I've been trawling the web for hours now and trying different methods, and I can't work out why PDO can't insert any row where one of the values contains a decimal.
For example, if the value entered into the cost field has no decimal value then it works fine. But anything like with a decimal and it just ignores the whole row.
200 works, even 200.00 works. But things like 39.99 don't.
Here's the code:
$invoice_id = $db->lastInsertId('id');
$item_name = $_POST['item_name'];
$item_qty = $_POST['item_qty'];
$item_cost = $_POST['item_cost'];
$item_vat = $_POST['item_vat'];
for($i = 0; $i < count($item_name); $i++) {
$item_query = $db->prepare("INSERT INTO hm_invoice_items(invoice, item, qty, amount, vat) VALUES(:invoice, :item, :qty, :amount, :vat)");
$item_query->bindParam(":invoice", $invoice_id);
$item_query->bindParam(":item", $item_name[$i]);
$item_query->bindParam(":qty", $item_qty[$i]);
$item_query->bindParam(":amount", $item_cost[$i]);
$item_query->bindParam(":vat", $item_vat[$i]);
if (!$item_query->execute())
{
die(showMessage("There has been a problem adding the invoice items.", "Error!"));
}
}
A var_dump tells me that the insert query is receiving the values, but it does not like dealing with decimals.
There could be an issue with decimal separator.
When debugging such cases it's essential to var_dump() e-ve-ry-thing!
Why don't you var_dump your values for the closer inspection?
Why didn't you play with decimals only, without POST, without other values?
A question titled "Can't insert decimal value with PDO" should contain short reproduceable code with decimal value present to readers and the result.
Judging by indirect measures will do no help for you and - especially - won't bring you help from strangers.
"var_dump your values" means every suspicious value, like
var_dump($item_cost[$i]);
inside your loop
if you get no output - then there is empty value, so, no wonder nothing inserted.
By the way, you're binding apparently decimal item_cost value to apparently integer amount field. Is it a typo?
But again - where is a certain reproduceable proofcode contains one insert query, one hardcoded decimal value and one result? Ugh - and table definition of course.
Try this?
$item_query->bindParam(":amount", floatval($item_cost[$i]));
At least it works for me when I deal with MySQL decimal data type with PDO.
Use the following to display the content of all the values POSTed to your PHP script:
print_r($_POST);
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.
i am using $_GET['var'] to get a variable then compare it with a variable in my database. the variable is 1.1 the var is set to "float" on the database so i know it can handle decimals but when i compare them with the code below i get nothing.
include 'connect.php';
$sql=mysql_query("SELECT * FROM table WHERE stuff='$stuff'");
while ($row=mysql_fetch_assoc($sql)) {
$start=$row['start'];
}
echo $start; //nothing happens
From what I know float type isn't precise. It doesn't show you that actual value so 1.1 that you saved may not be the actual value stored. Trying setting your field as decimal and give it a length of say, 10,1 where 10 is the maximum number of digits (the precision) and 1 is the number of digits to the right of the decimal point (the scale). It should work doing query like stuff='1.1' or stuff=1.1.
WHERE stuff = '$stuff' is a String comparison.
Compare number like so
WHERE stuff = $stuff
Don't use float( even if you insert 1.1 into the table, the actual value for float type is not 1.1, but something like 1.100000023841858) . Change it to double in database (or decimal)
You might not be seeing any output because your echo is outside the loop.
The scope of your variable $start would be confined to the loop.
Change the stuff field to DOUBLE type.
Then,
SELECT * FROM table WHERE stuff=$stuff
this should be the sql query