PDO - getting column count on a prepared statement, is it possible? - php

I'm trying to refine my database access classes to help at the time of processing form data. What I'm trying to accomplish is this:
add an SQL query to my connection object.
classify the SQL query by its commands and arguments.
use the classification data to automatically add the required attribute to a given form input tag (and, optionally, insert a given or corresponding RegEx for advanced matching).
add a session-driven temporary object holding the form members to check for both completeness and compliancy with a given set of rules or matches.
execute the SQL query once all the given requirements are satisfied.
Then, the way to proceed (in my actual code) is like this:
if (!empty($data = \Helpers\Forms\getData($_POST))) {
if (!empty($rules = \Helpers\Forms\getRules($_POST))) {
if ($data->isCompliant($rules)) {
// rest continues here...
}
}
}
So far, I've got steps 1, 3 and 5 fully completed. I got steps 2 and 4 just partially implemented because I need a way to do a metadata scan on a given prepared SQL query and that's where I'm a bit lost.
According to the PDO manual, the columnCount() method doesn't provide an accurate result until the execute() method is called.
However, the execute method actually executes the query and I don't want to do it because if it's a SELECT query, it would actually be ok but not for a INSERT, DELETE, UPDATE or any other kind of query.
So my question is... is there any way to get the column count for a given SQL query without executing it? Or maybe... is there a way to perform a dummy execution of a given SQL query to obtain this column count value?

Related

Should you use prepared statments on LIMIT

One day I was googling to understand when a prepared statment should be used. As I searched online many claimed that you should use always prepared statments. Now the question I have is... does this also count for LIMIT? I mean it is possible (I tried) but is it really that rational? Same question on ORDER BY too.
When the database does not allow you to use a parameter on a specific location of the SQL statement you need to assemble the query on the fly, by the use of Dynamic SQL. That is... concatenating strings to get a full functioning SQL query.
Now, the trick is to make it safe against SQL Injection. To do this:
Make sure the value for LIMIT is an integer, and not something unsafe coming right from the UI like 3; DROP TABLE EMPLOYEE.
For the ORDER BY clause make sure the columns are not coming from the UI "as is"; use some kind of projection. For example, if there are 50 columns to order by, the UI can display them all, but then just send a number (from 1 to 50) to the backend; the backend receives this number and reconstitutes the ordering column(s) from it.
Normally the LIMIT parameters must be literals, not values that can be substituted for placeholders, so you would have to validate that they're integers before substituting into the string.
However, if you use PDO rather than mysqli, it allows you to perform parameter substitution in the LIMIT clause, by using the PDO::ATTR_EMULATE_PREPARES option. This is automatically enabled for a specific prepared statement if it contains parameters in this clause. See How to apply bindValue method in LIMIT clause? for the specific details.

php vs MySQLi, Which one is faster [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I want to execute a query to fetch data from 1000 rows in my database. I have found two methods to do that.
Method 1:
SELECT * FROM user WHERE id=879
and second one which I used to protect myself from SQL Injection was:
Method 2:
<?php
$q="SELECT * FROM user";
$get_res=$dbconn->query($q);
while($set=$get_res->fetch_assoc()) {
if($set['id']==879)
{
//Some task here
}
}
So Which one is faster. I know about SQL prepared Statement.. But I just want to compare these two method.. And if there will be any security flaw in Method2 then Please explain that one also..
If this is just static id=879 you can simply just execute the query. It's fast, performant, and lets MySQL do the filtering for you.
Method 1:
SELECT * FROM user WHERE id=879
Most performant, and is your choice if 879 is not a variable. Just execute the query, return 1 result.
Method 2:
$pdo = new PDO($dsn, $user, $pass, $opt);
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');
$stmt->execute([ $_POST['user_id'] ]);
$user = $stmt->fetch();
This method uses PDO (alternatively you can use bind_param that's available in the MySQLi package). Return 1 result from the database, and safely bind the variable to the query string for execution. This is likely your best solution, as it lets MySQL do the filtering (Using indexes and the most efficient means to find your result).
Method 3 (DO NOT USE):
<?php
$q="SELECT * FROM user";
$get_res=$dbconn->query($q);
while($set=$get_res->fetch_assoc()) {
if($set['id']==879)
{
//Some task here
}
}
HORRIBLE! You are returning EVERY result from the database, and causing many many needless loops to grab the data you want. Let the database do the filtering, it's what it was designed for!
The first (SQL) method is faster.
Reason: SQL is designed for filtering the rows (using the id) very fast. Thus it first searches through all the indexes and returns a single, matching result.
Despite this, with PHP this does the logically the same, but PHP has to fetch the complete row first, validate the id, and proceed to the next row if it does not match.
Both are sql querys, only that in the second one you're using php to make the query instead of doing directly as in the first one.
If it's a webpage what you're building, you need to do it rather with php or jsp, because you can't do it directly in this scenario.
However if you're asking which one is faster, it's the first one with no doubts. However it's use is limited to SQL platform rather than globally with php.
I assume in the first method you're still using PHP to execute the query.
If you're taking in user input, then in no way is the second method protecting you from SQL injection. You'll need parameterized queries for that.
Also, method 1 is definitely the way to go - the more closely you can get to the desired result without PHP, the better.

MySQL MULTIPLE INSERT get rows that fail?

I'm a beginner with PDO and MySQL, so here's my question :
How can I be sure that when performing an INSERT .. SELECT (or MULTIPLE INSERT)
all data will be inserted in database?
I know there is a rowCount() function but the number of rows inserted is dynamic.
The only way I see would be to make a SELECT count(*), and then compare it with the rowCount(), but I'm not sure I'm doing it the right way.
And if not all data were inserted, is it possible to get rows which didn't work?
Also, is it possible that a SELECT query fails and retrieves only a few part of the data? (ex : It must retrieve 1000 rows but due to some failure, it retrieves 700) Or it's all or nothing?
Thanks for the help.
How can I be sure that when performing an INSERT .. SELECT (or MULTIPLE INSERT) all data will be inserted in database?
You should tell PDO to throw an exception in case of error and thus there will be a PHP error in case of a failed query.
I know there is a rowCount() function
Row count has nothing to do in your case.
And if not all data were inserted, is it possible to get rows which didn't work?
It is advised to redo all the successful yet queries instead. To do so you have to wrap your inserts in a transaction.
However, if you want to keep alll the previous inserts in place, you may wrap execute call in a try and catch operator and do whatever workaround inside.
Also, is it possible that a SELECT query fails and retrieves only a few part of the data?
No.

Updating parameters in MySQLI

I am trying to update a row in mySql database. However I only want to update specific parameters, which are not null:
db->prepare("UPDATE table SET userFirstName = $userFirstName, userLastName = $userLastName WHERE xx = $xx");
this is what I do for now, but it may be that userFirstName does not need updating, or userLastName,... Since I have may values I need a way to say something like:
if userLastName is not "null" then update even that...
MySQL is smart enough to determine whether to update the row or not. If it sees that the value to be updated with matches the value currently in the column it will skip rewriting it, and even if it didn't it's not really something you should care about anyway. I've had quite a bunch of these optimization obsessions myself and I can tell you from experience, they don't bring you anything good.
There is a greater problem with your code. Your use of prepare is senseless. Your SQL is still vulnerable. Search for prepared statements and mysql injection.
However to answer the question as is - you should use an object as a database mapper. They make your life a whole lot easier. Basically the idea is that you have an object that represents a row of your table, then it keeps track of which properties have been modified and when you call $object->save() it knows exactly which fields to update.

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.

Categories