Mysqli dynamic query bind_results - php

I wrote one databasse class which I use often and I used mysqli.I wanted to write it with PDO but it was slow (It is not about ip connection :) ),and my website is really huge and this pdo little slowness will be really big problem,that's why I choosed difficult way --Mysqli--.I wrote some dynamic class which bind params dynamicly and easily usage like this:
DB::getInstance()->query(sql,'ss',array($a,$b));
This was really useful untill today.I wanted to get result and also count values but I discover reaally big problem that when I use num_rows mysqli get_result will not work,When I use get_result num rows will never work,also when I use get_result and if I want to use it again for same query second one will not work
.Also get_result is not good function because it support only mysqlid.Then I have tried bind result which is useless because every select query I should write bind_result(params) which is not good for other developers on company also.What Should I do?Pdo is slow and for my website it is really slow,mysqli is not for developers it increase development time.How can I bind results dinamicly for query?I want something like I will write sql statement and bind result should get column names dinamicly bind them aoutomaticly and then I will write fetch() and I will write column names and I will get result.How can I do that?

When I use get_result num rows will never work
this is not true
besides, you never need num rows anyway
when I use get_result and if I want to use it again for same query
you don't want it
get_result is not good function because it support only mysqlid
this is true
however, if your site is so big and distinct, there is no problem to install a required module or two.
How can I bind results dinamicly for query?
use get_result.
To reuse a result get all the rows into array using fetch_all() and then use this array anywhere you wish
Instead of num_rows just fetch the data and see whether anything was fetched or not.

Related

which mysqli functions do a client server round trip

I want to understand how many client sever calls are made for a typical mysqli query?
Step(1) $result = mysqli_query($link, $query);
Depending on the type of query, we use other mysqli function after this like
mysqli_fetch_fields, mysqli_affected_rows, mysqli_insert_id, mysqli_fetch_row
etc. then we close the result object.
Now, is all data retrieved and stored in php memory after step (1)?
Or mysqli_fetch_fields, mysqli_insert_id etc makes another call to mysql server?
Reason for asking: Trying to understand how mysqli calls work. But can not find such explanation anywhere for beginners like me.
PHP MySQLi API is built on MySQL C API. So it would be better if you have knowlegdes of it.
Basically, SELECT query could generate large ResultSet and this ResultSet is transfered from Server to Client when you call PHP's mysqli_store_result() (In C API, mysql_store_result()).
C API mysql_fetch_row() just returns a pointer to MYSQL_RES* (which is already stored in PHP right after mysql_store_result(). But 'mysqli_fetch_row()` would require some memories to make PHP's array.
mysqli_insert_id() (which is last_insert_id() of C API) just returns insert id of MYSQL connection data stucture which means there is no extra memory for insert id.
If you want to know how MySQLi works, I would recommand to learn MySQL C API and see PHP source codes.
mysqli_query runs the query on the server and returns false is the query failed, true is the query was successful but did not return anything (UPDATE query for example) or a mysqli_result otherwise. That mysqli_result is a class that extends Traversable interface, so yes, it's in memory. All other functions mysqli_fetch_fields, mysqli_affected_rows etc. are just methods in that class so those just read what's already in memory.
For more details, read this: php documentation
The documentation tells you everything you need to know about mysqli.
mysqli_query execute the query and returns a query object, this object has some methods and amongst them there are:
mysqli_fetch_fields:
Returns an array of objects representing the fields in a result set
mysqli_affected_rows:
Returns the number of rows affected by the last INSERT, UPDATE, REPLACE or DELETE query.
mysqli_insert_id:
Returns the auto generated id used in the last query
mysqli_fetch_row:
Get a result row as an enumerated array
Being all method of an object they don't execute sql requests, they simply access object values and gives you back different results depending on the method.

Add element to array in the conditional statement of a loop in PHP

I have this piece of code:
while ($i = $res->fetchArray(SQLITE3_ASSOC))
{
$items[] = $i;
}
I tried neatening it to this:
while ($items[] = $res->fetchArray(SQLITE3_ASSOC));
It looks very satisfying but I now get an extra element at the end of the array (when the call to fetchArray() returns false. Is there a way of writing this statement without getting the extra element at the end?
If you're using PDO as your database library, you should use the fetchAll() method (documentation)
$items = $stmt->fetchAll(PDO::FETCH_ASSOC)
This will provide you a bidimensional associative array. Its index goes from 0 to n-1 where n is the fetched rows count and every row contains an array with column names as indexes. For example:
$items[3]['id']
will contain the value stored in the id column of the 4th fetched row.
if you're using mysqli_* instead, there is mysqli_fetch_all() but it's discouraged because it's more expensive rather a loop of mysqli_fetch_array(), or so the documentation says.
If you're using a third party library, consult the provided documentation. If there is none provided or there is no fetchAll equivalent it's a sign of poor quality. Drop it and use the native PDO instead.
Since you're using SQLITE3 driver, i suggest you to look at this page: SQLITE (PDO) which explains how to use PDO with SQLITE3. Believe me, it's worth it. Most probably you won't stick to SQLITE for long and when you'll migrate to MySQL or PostgreSQL you'll thank me for this read.
PDO's main advantage is that's (usually) transparent to the user regarding which DB is below. Therefore, it shouldn't break your application if you change database, just change the PDO connection string and it'll be enough.
Try
while(($item=$res->fetchArray(SQLITE3_ASSOC))&&$items[]=$item);

Method "moveFirst()" ADODB, PDO equivalence

Currently I use in my projects ADODB library for integration with the database.
I want to migrate to PDO, but I have a question about the consultations.
Currently, with the ADODB I do a query and use the row with the set numerous times using the method MoveFirst().
Example:
//I consultation
$rs = $conn->execute('select * from mytable');
//Loop through the results
while(!$rs->EOF) {
echo $rs->fields('name');
$rs->MoveNext();
}
//I move the "pointer" to the beginning of the list
$rs->MoveFirst();
//I can go over the results without needing to re-select
while(!$rs->EOF) {
echo $rs->fields('name');
$rs->MoveNext();
}
I wonder if there is any way similar in PDO, so I do not need to run the query again.
The goal is to avoid unnecessary queries on the bench more often since they use the same query.
I'm not sure why you want to loop through the result set more than once over the database connection. Why pull the data over the network again when you can just retrieve and save it the first time? But what you are looking for is a scrollable cursor, which isn't supported by mysql. At least not through any PHP/MySQL driver. You may also want to look into buffered/unbuffered queries, which is supported by PDO.
PDO::CURSOR_SCROLL
http://www.php.net/manual/en/pdo.prepare.php

Get Number of Rows from a Select Statement Efficiently

Until recently I've been using mysql_real_escape_string() to fix most of my variables before making SQL queries to my database. A friend said that I should be using PDO's prepared statements instead, so after reading a bit about them I'm now switching over to them.
I've only encountered one problem so far in switching over, and that's counting the rows to returned by a SELECT statement. On occasion in my code, I'd run an SQL query and then count the number of rows returned from the SELECT statement. Depending on whether a result set returned, I would take different actions. Sometimes I do need to use the result set from it. MySQL let me go straight to mysql_fetch_assoc() after mysql_num_rows() with no problem. However, PDO doesn't seem to have anything like mysql_num_rows().
I've been reading some responses on SO that gave me a solution, to either use COUNT() in the SQL statement or to use the PHP function count() on the result set. COUNT() would work fine in the SQL statement if I didn't need the result set in some places, however, several people have mentioned that using count() on the result set is fairly inefficient.
So my question is, how should I be doing this if I need to count the number of rows selected (if any), then run a script with the result set? Is using count() on the result set the only way in this case, or is there a more efficient way to do things?
Below is a short example of something similar to my previous SQL code:
$query=mysql_query('SELECT ID FROM Table WHERE Name='Paul' LIMIT 1);
if(mysql_num_rows($query)>0)
{
print_r(mysql_fetch_assoc($query));
}
else
{
//Other code.
}
Thanks.
EDIT
I do know that you use fetchAll() on the statement before counting the result set (which gives me what I need), but I'm just trying to figure out the most efficient way to do things.
$stmt->rowCount();
http://php.net/manual/en/pdostatement.rowcount.php
the rows must be fetched(buffered into memory, or iterated) for it to work. It's not uncommon for your pdo driver to be configured to do this automatically.
You will have to use Count(). You can run two queries like
SELECT COUNT(ID) FROM Table WHERE Name='Paul'
one you have get the count, then run the query with select clause
SELECT ID FROM Table WHERE Name='Paul' LIMIT 1
Count() function is not inefficient at all if you are using it like COUNT(ID), because most probably id is primary key and have an index. MYSQL wont even have to access the table.

Work-around for PHP5's PDO rowCount MySQL issue

I've recently started work on a new project using PHP5 and want to use their PDO classes for it. The problem is that the MySQL PDO Driver doesn't support rowCount() so there's no way to run a query and then get the number of affected rows, or rows returned, which is a pretty big issue as far as I'm concerned. I was wondering if anyone else has dealt with this before and what you've done to work around it. Having to do a fetch() or fetchAll() to check if any rows were affected or returned seems like a hack to me, I'd rather just do $stmt->numRows() or something similar.
You can issue a SELECT FOUND_ROWS() query right after the original SELECT query to get row count.
$pdo->query("SELECT * FROM users");
$foundRows = $pdo->query("SELECT FOUND_ROWS()")->fetchColumn();
See also: MySQL Docs on FOUND_ROWS()
For those of you who are using MySQL stored procedures, this solution isn't really feasible. What I would suggest that you do is have your stored procedure create two rowsets. The first one will contain one row and one column, containing the number of records. The second will be the recordset you will use for fetching that number of rows.
The number of unlimited rows can be a SELECT COUNT(*) with the exact same WHERE clause as the second rowset without the LIMIT/OFFSET clauses.
Another idea could be to create a temporary table. Use your SELECT statement to populate the temporary table. Then you can use SELECT COUNT(*) FROM tmpTable for your first rowset and SELECT * FROM tmpTable for your second.
This question is based on several false assumptions and one outdated statement.
First of all, do not confuse number of affected and selected rows. PDO supported the former even back in '09.
Speaking of number of rows returned by SELECT statement - you just don't need that number. The data you have is enough.
And yeah, nowadays rowCount() supports number of rows selected from mysql as well. But again - you don't need that number in an average web-application anyway.

Categories