Using mysql_fetch_assoc twice in a single PHP script - php

I usually try to minimize calls to MySQL where possible, but I've finally encountered the case where I have to do multiple calls to MySQL in a single script.
It looks like you can't use mysql_fetch_assoc twice in a single script(!).
It seems that mysql_data_seek is the solution, but I cannot seem to get it to work.
To be clear, I have two queries I need to make. The second query depends on results from the first... Here's the structure:
$result = mysql_query($query1);
while($row = mysql_fetch_assoc($result)){
$pos = $row['position'];
}
mysql_free_result($result); // result freed per comment below.
$query2 = ' '; //... dependent on $pos - in mysql shell this returns results!
$result2 = mysql_query($query2)
while($row = mysql_fetch_assoc($result2)){
echo $row['id'];
}
What happens above is that the second while loop returns no results even though the query should have nontrivial rows.
Just to be sure:
Is this how you clear the pointer from the previous result to be able to use mysql_fetch_assoc again?
mysql_data_seek($result,mysql_num_rows($result) - 1);
I'm not sure what to use as the second argument. Admittedly, I am not that clear on pointers, but it seems I should clear the pointer to 0. But I get this error:
Offset 0 is invalid for MySQL result index 8 (or the query data is unbuffered

Check your connection with mysql_error() and see if you're getting the "commands out of sync" error. If so, you need to call mysql_free_result() after completing the first query and before starting the second. You could also just call mysql_close() to close your database connection and then reopen a new one.
For more details, see this question.

OP changed the question, so see the edit
*Deleted the posted codes here**
EDIT
After your edited your question and made clear you have actually 2 resources it looks like there is something else wrong. You don't have to worry about pointer when you use two different resources to supply mysql_fetch_assoc(). The thing with mysql_fetch_assoc() is that it takes your param ($result) by reference.
Now to answer your question:
I usually try to minimize calls to MySQL where possible, but I've finally encountered the case where I have to do multiple calls to MySQL in a single script.
Nothing wrong with multiple SQL calls in one script. Although in general you should try to minimize the SQL calls (because they may hurt performance).
It looks like you can't use mysql_fetch_assoc twice in a single script(!).
Plain wrong. Ofc you can do it. As long as you note the above. However when you have two result sets this wouldn't be your problem.
It seems that mysql_data_seek is the solution, but I cannot seem to get it to work.
Again: this has nothing to do with it when you use two (different) result sets.
To be clear, I have two queries I need to make. The second query depends on results from the first.
This shouldn't be any problem at all. It looks like is something else wrong. Have you verified that the second query really is what you think it is? Are you sure there are records? Are you sure there aren't any (MySQL) errors. Do you have error reporting enabled? Have you tried printing out mysql_error()? To better be able to help you can you please provide your real code and not etc etc stuff? Maybe something else is going on.
Or maybe you are simply trying to run the second query inside the first loop. Which would be bad in so many ways.

Related

PHP pg_fetch_object function returning false

Before post this question, i searched a lot in internet but did not find anything that could solve my problem.
<?php
$result=pg_query($this->conn_link,$strSqlQuery) or die(pg_last_error());
if($result)
$data=pg_fetch_object($result);
?>
So, after execute the code above, the value of $data is false, using var_dump() function. The strange thing is that if i copy the sql string and execute directly on SGBD (Sql Manager 2007) it returning data correctly!!!
I tried use functions that return last error, but no error was shown. So, i don't have any idea why is this happening. This never happened to me.
So guys, what could be or what i could to do for try to discover this issue. Thanks!
Solved.
Be careful when use pg_query without conection parameter, it will pick up the default conection, which maybe can cause wrong conection(other database conection for example) and your query will fail.
For me, i forced a re-conection with bd before execute the query and it worked beautifully.
<?php
$bd->conect();
$result=pg_query($this->conn_link,$strSqlQuery) or die(pg_last_error());
if($result)
$data=pg_fetch_object($result);
?>

Problems with converting mysql over to mysqli errors with mysqli_query & mysqli_fetch_row

Here is the edited script without errors. And the 2 fixes applied to it. To those who helped in part, thank you. To mentions that the code is unclear or messy is inconsequential. Given that most of the following is common structure in mysql queries. Even the example documentation for mysql followed this similar flow. Members who reply should negate from pointless internet banter. Its more worth your time, and my own to do so. Those who stayed on topic and assisted, I thank you.
For example:
$row = mysqli_fetch_row(mysqli_query($con, "SELECT test_table.points FROM test_table WHERE test_table.key = '" . $key . "'"));
if ($row[0] > 0){ // exists
Where $row will return a non-zero result if true. Otherwise 0 on false. There is little need to check mysqli_fetch_row and/or mysqli_query. Since checking $row in simplicity works fine. It is unneeded to check mysqli_fetch_row and/or mysqli_query individually in a general exists condition. It does accurately provide exist / does not exist results. There is no $result $row $query just $row.
The noted deviation to that normal flow was my desire to use call_user_func. And to poll in func and params through $_GET. Will be looking more at PDO. However, the clean code before exec should do alright job for now. Which is to clean before exec.
All in all, the code works just as it should. And have since written more to manage a mysql database. From write, write chunk, read, read chunk, delete, delete chunk.
Also to collect numbered records on request. For example say you have 6 records for the same John Smith. You can now collate and scan for differences in those records. Either for what you want, dont want, etc. Or if say you just want to blindly call the first 3 of those records for John Smith.
mysqli_fetch_row & mysqli_fetch_row fix :
FROM Calling $con outside function then into as per mysql. Which in mysqli does not work as expected. There was no error with the functions, over how $con was being handled.
TO Calling $con inside function with just the added global $con. May end up using $GLOBALS even for this.
Result : Calling $con outside function then in works fine in mysql. In mysqli it requires global be set within the function. ie global $con. Or it fails.
call_user_func non-critical error fix :
FROM call_user_func($func($_GET['user'],$_GET['key'],$_GET['points'],$_GET['type']));
TO call_user_func($func,$_GET['user'],$_GET['key'],$_GET['points'],$_GET['type']);
Result : Both lines execute correctly. From executed with a non-critical error. TO does the same thing, but with no following non-critical error.
Sample Output for both : user=MY_Name;key=34342$ee56i1;points=1234;type=
-- code removed as fixes solved the issues --
You are using call_user_func wrong read the manutal
call_user_func first parameter is the callback - in your case it's a function inside your class so it should be something like this:
If you have a non-static function in an object:
class Test{
public function doit($a){
echo($a);
}
}
$t = new Test();
call_user_func(array($t,'doit'),'asfaasfs');
and in static functions inside object:
class Test{
public static function doit($a){
echo($a);
}
}
call_user_func('Test::doit','asfaasfs');
You have a few problems.
$con is declared outside the class, and is thus not available inside the class. You need to pass it into the class (the better option), or specify it as a global (the quick+dirty option).
mysqli_fetch_row(mysqli_query($con,'...'))
This code is obviously converted directly from your old mysql_xx() code, but it's not great.
You're ignoring any possible error condition that is returned by mysqli_query(). This means that if it fails, it'll pass false into the mysqli_fetch_row() function, which will then fail with a meaningless error expects parameter 1 to be mysqli_result, rather than actually telling you what the error was in the query.
The thing is, because of my first point above, with $con not being set, mysqli_query() is failing, and this is why you're getting the error in mysqli_fetch_row().
Ideally, you should split this code out into multiple lines. Call mysqli_query() on its own, then do some error checking, then call mysqli_fetch_row() only once you know that the query actually worked.
Hope that helps explain what the problems are here. Solve those two points, and you should be well on the way to sorting the whole thing out.
Once you've got rid of those fatal errors, you should also take time to work on the problem that your code is vulnerable to SQL injection attacks. You're currently passing your $_GET variables directly into the query strings without any sanitisation. This will make your system very fragile and easy to hack. You should consider using Parameterised Queries, which is a feature of the mysqli library designed to make it easier to deal with variables in SQL queries in a safe and secure way.
Your class is pointless at the moment, perhaps stick to writing imperative style code as it will at least be cleaner.
At the moment, you should pass $con to your MYsql class to use itself as a resource, not try to access it as a global variable.
Your are not filtering your user's input either, this is dangerous and could lead to SQL injection attacks on your site.
I'd encourage you to read through these two articles, and once you grok them, I'd also encourage you to simply switch to using PDO with prepared statements. This will stop SQL injection attacks that your code currently allows.
http://net.tutsplus.com/tutorials/php/pdo-vs-mysqli-which-should-you-use/
http://net.tutsplus.com/tutorials/php/why-you-should-be-using-phps-pdo-for-database-access/

Simple DELETE query not working

This is something I should be able to do but I have been trying for the last hour to see the issue here but I can't. It is a simple delete function to delete an entry through the use of a ID tag. It is getting passed through the delete_category.php. If it helps my sql table is called blog_categories.
Its not throwing a error. Tried using echo mysql_error() on it but nothing. It simply acts like a dead link and refreshes the page.
Any help will be appreciated.
Blog.php:
function delete($table, $id) {
$table = mysql_real_escape_string($table);
$id = (int) $id;
mysql_query("DELETE FROM {$table} WHERE id = {$id}");
}
Linking delete function by:
Delete
Delete_category.php
<?php
include("../script/dbconnect.php");
include("../script/blog.php");
if ( ! isset($_GET['id']) ) {
header('location: cms.php');
die();
}
delete('blog_categories', $_GET['id']);
header('location:category_list.php');
die();
?>
So, this isn't a complete answer, but the comment fields are way, way too short to point you in the right troubleshooting direction.
Your code is broken, but not in the way you might expect.
GET requests have to be be idempotent. That is, they can't have side effects other than serving content. By having your delete functionality tied to a GET request, you are causing a side effect. This has some pretty severe consequences. Some browsers and caching mechanisms can pre-fetch links, for example. Also think about what a search spider would end up doing if it crawled that page.
Turn that GET into a POST. Perhaps use a form and a button instead?
It's awesome that you're using mysql_real_escape_string, but your use of it here is incorrect. mres is designed to encode character data as part of a string. You are using it on an identifier -- a table name. Identifiers do not share the same escaping semantics as strings, especially when used outside of quotes.
As long as the first argument to the delete function never comes through users, you can skip mres here.
You aren't checking the result from mysql_query. Sayeth the manual:
For other type of SQL statements, INSERT, UPDATE, DELETE, DROP, etc, mysql_query() returns TRUE on success or FALSE on error.
You're throwing away the result. You should check that it isn't false and then call mysql_affected_rows to make sure that one and only one row was removed. If mysql_query was false, then you can check mysql_error.
After making these changes, you then need to alter your delete_category.php script to assist in troubleshooting:
Add the following two lines to the very top:
error_reporting(-1);
ini_set('display_errors', true);
Change all of the headers to echos. An immediate redirect is going to mask any errors.
Use exit instead of die. While they do the same thing, the use of die is frequently used exclusively in the context of "something went so wrong that I have to exit now," vs exit, which is just, well, uh... exit.
Anything that's actually going wrong should then be pretty darn obvious.
If you still aren't seeing anything incorrect happen, and the rows still aren't being deleted, try adding a SELECT COUNT(*) FROM ... before and after the delete, using the same table name and WHERE clause. That will help us troubleshoot further.
Long term, you really want to begin switching from mysql_ PDO or mysqli. The next major release of PHP, version 5.5, is deprecating the mysql_ family of functions.

PHP, Using PDO with nested queries, results corrupted

I'm using PDO against MSSQL, and need to run nested queries. They are all prepared statements. If I try to use the fetch() method, it inner queries fail immediately, so I used fetchAll(). So, I get something like this, with Programs, Products and Budgets:
$pgm_stmt->execute();
$pgm_res = $pgm_stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($pgm_res as $pgmrow) {
$prod_stmt->execute(array($pgmrow['ID']));
$prod_res = $prod_stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($prod_res as $prodrow) {
$bdgt_stmt->execute(array($pgmrow['ID'], $prodrow['ID']));
$bdgt_res = $bdgt_stmt->fetchAll(PDO::FETCH_NUM);
foreach ($bdgt_res as $bdgtrow) {
... work here
}
}
}
OK, everything works the first time through, but when it loops back for the 2nd program, the product result set gets corrupted somehow. When I dump the $prod_res variable right after the fetchAll(), the values are randomly assigned from other parts of memory, bits of other arrays, etc. Of course it fails because the $prodrow['ID'] value is undefined, because that whole result set is mangled.
Can someone help me troubleshoot this? I'm stumped.
Thanks.
Not a bug, but a feature, see: https://bugs.php.net/bug.php?id=65945
This is the behavior of MSSQL (TDS), DBLIB and FreeTDS. One statement per connection rule. If you initiate another statement, the previous statement is cancelled.
The previous versions buffered the entire result set in memory leading to OOM errors on large results sets.
The previous behavior can be replicated using fetchAll() and a loop if desired. Another workaround is to open 2 connection objects, one per statement.

php mysql 2 different ways

I recently ran across some code which the person did the first one. Would like some thoughts on if the top one is better or why a person would write it that way? Any positive reasons over the bottom way.
$result = mysql_query($query)or die("Obtaining location data failed!");
for ($i = mysql_num_rows($result) - 1; $i >=0; $i--)
{
if (!mysql_data_seek($result, $i))
{
echo "Cannot seek to row $i\n";
continue;
}
if(!($row = mysql_fetch_object($result)))
continue;
echo $row->locationname;
}
mysql_free_result($result);
vs
$result = mysql_query($query) or die("Obtaining location data failed!");
while($row = mysql_fetch_object($result)){
echo $row->locationname;
unset($row);
}
mysql_free_result($result);
It looks like the top code is iterating through the mysql result backwards, where the first one is going through it forwards.
The second code example looks cleaner, and there is probably a way to adjust the query to get the results in reverse order in the first place, instead of the somewhat convoluted way the top loop was performed.
Those two are not equivalent since only the first processes the result set in reverse order.
I'd do that with an ORDER BY x DESC clause if only to keep the code simple. When using mysql_query() the complete result set is transferred from the MySQL server to the php process before the function returns and mysql_data_seek() is only moving some pointer within the process' memory, so performace-wise it shouldn't matter much. But if you at some point decide to use an unbuffered query instead it might very well affect the performance.
Definitely the second one :
less code = less code to maintain =~ maybe less bugs !!
The top one has definite advantages when it comes to job security and 'lines of code' performance metrics. Apart from that there is no good reason to do what they did.

Categories