Unable to subtract a table value via variable - php

I can not get an SQL update statement to subtract a variable from a table value. Here is my code:
$_SESSION_Job101=mysql_fetch_array(mysql_query("SELECT * FROM job_101 WHERE job_101.username='$_SESSION_User'"));
mysql_query("UPDATE characters SET currenergy=currenergy-$_SESSION_Job101['ecost'] WHERE username='$_SESSION_User'");
$_SESSION_Job101 is a perfectly valid result, as I pull from it on another page; I even pull the 'ecost' on said page. I also update currenergy this way in another script, except I use the number 1 instead of the variable. So I've narrowed it down to that variable.
It wouldn't matter that $_SESSION_Job101 is the result from a second table (job_101), and that query is updating to the table characters, would it?

We don't have enough information, but since you don't perform ANY error handling or validation that SQL resultset is returned, it could be an error caused by issues such as:
no rows returned in first query
some other parsing issue not directly evident
I would propose that you use temporary strings and echo the actual SQL queries.
Continue by actually testing them with MYSQL (through workbench, queryviewer, or console) in order to see where and what the error is.
Also, it's not recommended to skip error checking and try to combine so many lines/steps into 2 lines.
Imagine the first query does not return any results for example...
Debugging:
$query1 = "SELECT * FROM job_101 WHERE job_101.username='$_SESSION_User'";
echo $query1."<br/>";
$_SESSION_Job101=mysql_fetch_array(mysql_query($query1 ));
$query2 = "UPDATE characters SET currenergy=currenergy-$_SESSION_Job101['ecost'] WHERE username='$_SESSION_User'";
echo $query2."<br/>";
mysql_query($query2);
Update
Based on your comment I suggest you try the following two options:
1) Add a space between the - and $_SESSION_Job101['ecost'].
2) If that doesn't work, change your string to:
mysql_query("UPDATE characters SET currenergy=currenergy-".$_SESSION_Job101['ecost']." WHERE username='".$_SESSION_User."'";`

Related

Why comparing Strings in MySQL query is not working

I am running a very simple SELECT query in MySQL and it's not working.
SELECT string_name FROM table_name;
This is giving me required output. Like
This is string one.
This is string two.
This is string three.
and so on...
But if I am running a query like this
SELECT * FROM table_name WHERE string_name='This is string one'
It's not giving any output. I even tried TRIM function.
SELECT * FROM table_name WHERE TRIM(string_name)=TRIM('This is string one')
But it's still not giving any output.
Please suggest what I am missing here. Is it because of some formatting or am I doing any silly mistake. By the way, Strings are saved as VARCHAR in the database.
To reiterate from comments; sometimes "non-printing" control characters (like newlines) can make their way into data they were never intended to be a part of. You can test for this by checking CHAR_LENGTH of field values versus what you actually see. Obviously, on large amounts of data this can be difficult; but if you know of one problematic value already, you can use this method to confirm this is the problem on that row before attempting to identify the offending character.
Once this problem is confirmed, you can use queries with MySql's ASC() and substring functions to identify character codes until you find the character; it can be best to start from the end of the string and work back, as often the offending characters are at the end.
The character or characters identified in known problem rows are often the cause of other problem rows as well, so identifying the issue in one known row can actually help resolve all such problems.
Once the character code(s) are identified, queries like WHERE string_name LIKE CONCAT('%', CHAR(13), CHAR(10)) should work (in this case for traditional Windows newlines) to identify other similar problem rows. Obviously, adjust character codes and wildcards according to your circumstances.
If no row should ever have those characters anywhere, you should be able to clean up the data with an update like this:
UPDATE theTable SET theString = REPLACE(REPLACE(theString, CHAR(10), ''), CHAR(13), '') to remove the offending characters. Again, use the codes you've actually observed causing the problem; and you can convert them to spaces instead if circumstances are better handled that way, such as a newline between two words.
Have you tried using LIKE for debugging purposes?
SELECT * FROM table_name WHERE string_name LIKE 'This is string one'
/!\ Don't just switch from = to LIKE, read about why here
TLDR:
= is apparently 30x faster.
Use = wherever you can and LIKE wherever you must.
First of all, I must acknowledge the points made by #Uueerdo were actually the the main cause of this issue. Even I was somewhat sure that there are some hidden characters in the string causing all the issue but I was not sure how to find and fix that offending character.
Also, the approach suggested by #Uueerdo to check and replace the offending character using the ASCII code seems quite legit but as he himself mentioned that this process will take lot's of time and one have to manually check every string for that one offending character and then replace it.
Luckily after spending couple of hours on it, I came up with a much faster approach to fix the issue. For that, first of all I would like to share my use case.
My first query was for selecting all the strings from a database and printing the result on page.
$result = mysqli_query($conn, "SELECT * from table_name");
while($row = mysqli_fetch_array($result)){
$string_var = $row["string_name"];
echo $string_var;
echo "<br>";
}
The above code was working as expected and printing all the string_name from the table. Now, if I wanted to use the variable $string_var for another SELECT query in the same table, it was giving me 0 results.
$result = mysqli_query($conn, "SELECT * FROM table_name");
while($row = mysqli_fetch_array($result)){
$string_var = $row["string_name"];
echo "String Name : ".$string_var."";
$sec_result = ($conn, "SELECT * FROM table_name WHERE string_var='$string_name'");
if(mysqli_num_rows($sec_result) > 0){
echo "Has Results";
} else {
echo "No Results";
}
}
In this snippet, my second query $sec_result was always giving me No Results as output.
What I simply did to fix this issue.
$result = mysqli_query($conn, "SELECT * FROM table_name";
while ($row = mysqli_fetch_array($result)){
$string_var = $row["string_name"];
$row_id = $row["id"];
$update_row = mysqli_query($conn, "UPDATE table_name SET string_name='$string_var' WHERE id=$row_id");
}
This step updated all the strings from the table without any hidden/problem causing character.
I am not generalising this approach and I am not sure if this will work in every use case but it helped me fix my issue in less than a minute.
I request #Uueerdo and others with better understanding on this to post a more generic approach so that it can help others because I think many people who can't find a right approach in such conditions, end up using LIKE in place of = but that completely changes the core idea of the query.

foreach loop returns nothing

I am trying to pull user data from a Cart66 table I have and put it into a shortcode in wordpress. $account is an integer pulled from session data. The code below returns nothing.
$account =Cart66Session::get(Cart66AccountId);
global $wpdb;
$fname=$wpdb->get_results("SELECT * FROM 'vfp_cart66_accounts' WHERE id = '$account', ARRAY_N");
foreach ($fname AS $row)
{
echo $row;
}
This returns "Array"
return $fname;
Ok firstly, maybe I am the only one who saw this, and it could be the source of your entire problem, but you have a misplaced double quote, at the end of your SQL line, which should live at the end of the actual SQL string, not after the requested return type:
// at the end of this line you have: '$account', ARRAY_N");
// this should be changed to: '$account'", ARRAY_N);
$fname=$wpdb->get_results("SELECT * FROM 'vfp_cart66_accounts' WHERE id = '$account', ARRAY_N");
Even the first person who answered the question did not correct you, so I am assuming he didn't see it either. Secondly, using single quotes (') to escape a table name is invalid. If it is quoted at all, use backticks (`). Single quotes indicate a string, not an database, table, or field, all three of which should only be quoted with backticks (except on utility queries like SHOW). Use this instead:
select * from `vfp_cart66_accounts` where id = '$account'
Thirdly, as your commenters point out, you could be vulnerable to SQL Injection. Make sure to use the tools that WP gives you, and do this, or similar, instead:
$fname = $wpdb->get_results(
$wpdb->prepare(
'select * from `vfp_cart66_accounts` where id = %d',
$account
),
ARRAY_N
);
Lastly, you are requesting an array from the DB, but you are trying to echo it as if it were a scalar value. This explains why printing the value of $row yields "Array". When you convert an array() to a string, by default, you get "Array", since arrays can be complex data that may not be beautifully converted to a string. As a correction of this, you can do one of two things.
First, if you need the entire resulting array that represents the entire row of the table, then you can simply change your echo code to this:
foreach ($fname as $row) {
// print the fname of the row
echo $row['fname'];
// do the other stuff you need to do with $row
...
}
OR, if you simply need the fname field out of that table, for the given id, you could use a different $wpdb function, called $wpdb->get_var(), which gets one specific field from the first entry of the resulting data from the database, coupled with some minor SQL changes:
// use the get_var() function instead
$fname = $wpdb->get_var(
$wpdb->prepare(
// 1) change the 'fields' of your sql to only get the `fname` field
// 2) also add limit 1, to reduce load by only asking for one row
// NOTE: #2 is optional really, because WP does this for you when using get_var,
// but is good practice to only ask for what you need. so do it
'select fname from `vfp_cart66_accounts` where id = %d limit 1',
$account
),
ARRAY_N
);
echo $fname; // print the value of field fname from vfp_cart66_accounts for id $account
Now. I don't have specific knowledge of Cart66. That being said, if the above changes to PHP, WordPress, and SQL syntax do not yield results, then you are probably having one of the following other problems instead:
there is a different PHP error somewhere in the code, causing this to never run
this code is never called, and thus it is never executed
you misspelled the table name, which is causing an SQL error
the table exists, but does not have a field named id
both table and field exist, but there are no entries in the table
some other random thing that is not coming to mind
DEBUG #1
For #1, you could try turning on error_reporting() and display_errors early in the code execution. In a normal, run of the mill PHP script you could add the following two lines somewhere early in the code:
error_reporting(E_ALL);
ini_set('display_errors', 1);
However, you are using WordPress, so you will need to do something like this in your wp-config.php file:
// find the line that looks like this and comment it out
// define('WP_DEBUG', false);
// add these two lines directly below it
define('WP_DEBUG', true);
ini_set('display_errors', 1);
DEBUG #2
Make sure your code is running. Don't be afraid to throw a die() statement directly above it, to make sure it is running. Something like this:
// add a die() before everything
die('I am running. Awesome!');
// revised code
$account = Cart66Session::get(Cart66AccountId);
global $wpdb;
$fname = $wpdb->get_var(
$wpdb->prepare(
'select fname from `vfp_cart66_accounts` where id = %d limit 1',
$account
),
ARRAY_N
);
echo $fname;
DEBUG #3
To debug #3, you need either access to a commandline tool for MySQL or some type of GUI interface like phpMyAdmin, so that you can run a query directly from the database. Here is the query you should run:
show tables like 'vfp_cart66_%';
This is an example of one of the only places in SQL that you should ever quote a table name in single quotes. Running this will yield a list of all the tables that start with vfp_cart66_. If you get no results, then your table name is wrong. If your results do not include vfp_cart66_accounts, then your table name is wrong. If you see vfp_cart66_accounts, you are good to go.
DEBUG #4
This one will need to be run directly from the DB or through something like phpMyAdmin also. You are trying to make sure you have the correct field name. The way you do that is:
show create table `vfp_cart66_accounts`;
Assumedly, the field you are calling id would be the auto_incremented field in the table. Thus you are looking for a line, similar to this one:
`id` bigint(20) NOT NULL AUTO_INCREMENT,
Make sure that the line that has AUTO_INCREMENT on it, begins with:
`id`
If it does not, and the name is something else other than id, then you probably have the wrong field name.
DEBUG #5
Make sure you actually have data to display. From your mysql console or phpMyAdmin, run:
select * from `vfp_cart66_accounts` limit 1;
If you bet any results, then you have data, and you are good.
DEBUG #3 - #5 (alternate methods)
Another option you have is to dump the $wpdb object, directly after you run the query, because it contains the last error you received from MySQL. You can do this like so:
$fname = $wpdb->get_var(
$wpdb->prepare(
'select fname from `vfp_cart66_accounts` where id = %d limit 1',
$account
),
ARRAY_N
);
// dump a readable version of the $wpdb object
echo '<pre>';
print_r($wpdb);
die('</pre>');
Often times, reading the MySQL error message helps narrow down the problem in your SQL syntax.
DEBUG #6
If none of this has helped at all, then you will need to use your experience to trackdown a random bug in either your plugins or theme, what could literally be anything. You may as well not even dig in core WP code because, while it does have a couple minor bugs unrelated to your problem, which are getting repaired as we speak, it is one of the most stable CMS platforms out there. It is used by more of the top 10 million sites on the internet than any other CMS, for a good reason. It works, it is up-to-date, and most of all, it is stable.
I really hope you found this helpful or at least learned something from it. Hopefully others find it useful as well.
$fname=$wpdb->get_results(
"SELECT * FROM `vfp_cart66_accounts` WHERE id = '$account'",
ARRAY_N"
);

MySQL returning an empty result set

I tried doing this in PHP but I got 0 rows returned all the time. Then after some time searching around on StackOverflow, I saw a tip to try doing it in SQL first to see if the results are returned properly.
I tried to do it in SQL and it's returning an empty result set all the time, even tho the values are there.
SQL
SELECT * FROM `serials_table` WHERE `ser_key`='ABCD-EFGH-IJKL-MNOP'
PHP
$result = $link->query("SELECT * FROM serials_table WHERE ser_key='$key'");
Both are returning null value.
ser_key column is set to text type, coallition: utf8_unicode_ci, Null: No, Default: None
The serial key entry is in there and the column 'ser_key' exists as well as the table 'serials_table'. Also I directly copy-pasted the serial key from the table and placed it into the query to avoid any typos.
Did I make some errors with the table structure or something?
I have no idea what to do here, any help would be appreciated.
When this works
SELECT * FROM serials_table WHERE ser_key like '%ABCD-EFGH-IJKL-MNOP%'
Then you have leading or trailing spaces in your data.
To revert that update your existing table data like this
update serials_table
set ser_key = trim(ser_key)
After that check where you insert or update the ser_key. In that code segment check if you put only trimmed data in there.
Try
SELECT * FROM `serials_table` WHERE TRIM(`ser_key`)='ABCD-EFGH-IJKL-MNOP'
Remove white spaces
UPDATE `serials_table` set `ser_key`= TRIM(`ser_key`);

Using a SELECT Query to look up a UPDATE Query on MySQL

I'm using a SELECT query to obtain a variable using mysql_fetch_assoc. This then puts the variable into an UPDATE variable to put the returned value back into the database.
If I hard code the value, or use a traditional variable and it goes in just fine, but it doesn't work when using a value previously retrieved from the database. I've tried resetting the array variable to my own text and that works.
$arrgateRetrivalQuery = mysql_query(**Select Query**);
$arrGate = mysql_fetch_assoc($arrgateRetrivalQuery);
$arrivalGateTest = $arrGate['gatetype'];
$setGateAirportSQL = "UPDATE pilots SET currentgate = '".$arrivalGateTest."' WHERE pilotid = '".$pilotid."'";
$setGateAirportQuery = mysql_query($setGateAirportSQL);
// Close MySQL Connection
mysql_close($link);
This will just make the field to update have nothing in it, however whenever I remove the variable from the SELECT to one I define, array or not, it will work.
Hope this is clear enough. Thanks in advance.
Is arrivalGateTest a number or a string? How did you try to put another value in the query? If you are sure the previous query returns a value, try to write: $setGateAirportSQL = "UPDATE pilots SET currentgate = '$arrivalGateTest' WHERE pilotid = '$pilotid'";.
Just change your sql to inlcude a subquery.
You could use the following general syntax:
UPDATE pilots SET currentgate = (SELECT gate FROM airport WHERE flight='NZ1') WHERE pilotid='2';
which is demonstrated on this fiddle
This saves the extra query and more accurately describes what you are trying to achieve.
WARNING - test it carefully first!

php mysqli to call stored proc, get get results

I have a stored proc that does a geospatial query. The proc issues two sql statements but only the 2nd one does a query but unfortunately both statements produce a result set. I need the second result set which contains the results of the actual query.
The first statement sets a bounding box:
SET #bbox = 'POLYGON(($polygon))'; \n
SELECT * , AsText( location )
FROM users
WHERE Intersects( location, GeomFromText( #bbox ) ) [snipped for brevity]
If I run the above in phpMyAdmin, it works but I get the following message AFTER the SET command is issued and I want to throw this away:
# MySQL returned an empty result set (i.e. zero rows).
On the php side, I build the query string, calling the stored proc and on return the first thing I do is throw away the empty result set.
$query = "CALL usp_queryByPolygon('$polygon', $msg_id, $user_type)";
$result = mysqli_query($cxn, $query) or die("GEOCODE: queryPolygon - " .sql_error());
sql_free_result($result);
After throwing away the result set I now need the results of the query and this is what I have done:
$result = sql_next_result();
The problem is when I try to use this second result set as in:
if(mysqli_num_rows($result) > 0)
I get errors:
Warning: mysqli_num_rows() expects parameter 1 to be mysqli_result, boolean given
in /blah/blah/module.php on line 96
To complicate things, all of the above is in a loop and there could be dozens or 100's of polygons to search.
So the question is this: what is the proper way to get that 2nd result set?
You'd better be accurate of what functions you execute. sql_next_result() is no standard PHP function, nor is it in MySQLi which you seem to use. If it's some kind of database class, please just show the methods that class uses. Nobody here can but quess what sql_next_result() does.
Assuming you're talking about mysqli_next_result(), that indeed returns a boolean, you need to call mysqli_use_result() after that in order to retreive the next result set.
Found out the two statements: SET #bbox and SELECT can be executed sequentially so mysqli and the two results are just fodder that don't need to be dealt with.

Categories