I wonder if I still need question mark if I don't want to specify any row. Because bind_param needs it.
$zr="0";
$stmt=$mysqli->prepare("select * from products_db where not prd_id=?");
$stmt->bind_param("i",$zr);//can I skip this line or what?
I search everywhere but there's no such a thing. Once I tried without ? it errors without reason. I might be typo error, something?
If you don't need to bind any parameters, you can use mysqli::query()
$result = $mysqli->query('SELECT * FROM products_db');
This both prepares and executes the SQL provided but offers no way to safely bind parameters.
This is roughly equivalent to...
$stmt = $mysqli->prepare('SELECT * FROM products_db');
$result = $stmt->execute();
which you can also use.
Note there are no positional parameters (ie ?) and therefore, no need to use mysqli_stmt::bind_param().
Related
I'm getting this annoying error and although I have an idea of why I'm getting it, I can't for the life of me find a solution to it.
if ($limit) {
$sth->bindValue(':page', $page - 1, PDO::PARAM_INT);
$sth->bindValue(':entries_per_page', $page * $entries_per_page, PDO::PARAM_INT);
}
$sth->execute($criteria);
Query contains placeholders (:placeholder). But to add those LIMIT placeholders, I need to use the manual method (bindValue) because otherwise the engine will turn them into strings.
I'm not getting the Invalid number of parameters error, so all placeholders have been bound correctly (I assume).
Query:
SELECT `articles`.*, `regional_municipalities`.`name` AS `regional_municipality_name`,
`_atc_codes`.`code` AS `atc_code`, `_atc_codes`.`name` AS `substance`
FROM `articles`
LEFT JOIN `_atc_codes`
ON (`_atc_codes`.`id` = `articles`.`atc_code`)
JOIN `regional_municipalities`
ON (`regional_municipalities`.`id` = `articles`.`regional_municipality`)
WHERE TRUE AND `articles`.`strength` = :strength
GROUP BY `articles`.`id`
ORDER BY `articles`.`id`
LIMIT :page, :entries_per_page
All placeholder values reside in $criteria, except for the last two LIMIT, which I manually bind with bindValue().
This same error 2031 can be issued when one bind two values with the same parameter name, like in:
$sth->bindValue(':colour', 'blue');
$sth->bindValue(':colour', 'red');
..so, beware.
You cannot use ->bind* and ->execute($params). Use either or; if you pass parameters to execute(), those will make PDO forget the parameters already bound via ->bind*.
This exception also appears if you try to run a query with placeholders instead of preparing a statment such as
$stmt = $db->query('SELECT * FROM tbl WHERE ID > ?');
instead of
$stmt = $db->prepare('SELECT * FROM tbl WHERE ID > ?');
From the manual:
public bool PDOStatement::execute ([ array $input_parameters ] )
Execute the prepared statement. If the prepared statement included
parameter markers, you must either:
call PDOStatement::bindParam() to bind PHP variables to the parameter markers: bound variables pass their value as input and
receive the output value, if any, of their associated parameter
markers
or pass an array of input-only parameter values
You need to pick a method. You cannot mix both.
It's not exactly an answer, but this error also happens if you try to use a word with a hyphen as placeholders, for example:
$sth->bindValue(':page-1', $page1);
So better use
$sth->bindValue(':page_1', $page1);
This happens if you have mismatching parameters. For example:
$q = $db->prepare("select :a, :b");
$q->execute([":a"=>"a"]);
The exception also happens (at least in MySQL/PDO) when your SQL tries to UPDATE an AUTO_INCREMENT field.
Which of these two is the safe method to write a query?
$stmt = $pdo->prepare("UPDATE tableName SET fieldName = 0");
OR
$stmt = $pdo->prepare("UPDATE tableName SET fieldName = :parameter");
$stmt-> bindValue(':parameter', 0);
I know the 2nd method is way best and I use it whenever I use a $variable in bindValue. But here, I need to use a known integer 0. So, the first process seemed easier as I did not had to write another bindValue statement. But, is it safe?
Looking at your questions I'd say that you'll definitely benefit from reading the PDO tutorial I wrote, which says:
There are two ways to run a query in PDO. If no variables are going to be used in the query, you can use the PDO::query() method.
and
if at least one variable is going to be used in the query, you have to substitute it with a placeholder, then prepare your query, and then execute it, passing variables separately.
So now you can tell that for this particular query you can use the query() method instead of prepare/execute
$stmt = $pdo->query("UPDATE tableName SET fieldName = 0");
as there is no variables to be used and this no danger at all
From experience and also having been told constantly the benefits of using prepared statements and binding my parameters, I have constantly used those two techniques in my code, however I would like to understand exactly the purpose of each of those two techiques:
From my understanding of prepared statements:
$sql = "SELECT * FROM myTable WHERE id = ".$id;
$stmt = $conn->prepare($sql);
$stmt->execute();
The previous code should create a sort of a buffer in the database with the query I proposed. Now FROM MY UNDERSTANDING (and I could be very wrong), the previous code is insecure, because the string $sql could be anything depending on what $id actually is, and if $id = 1; DROP TABLE myTable;--, I would be inserting a malicious query even though I have a prepared statement.
FROM MY UNDERSTANDING this is where binding my parameters com in. If I do the following instead:
$sql = "SELECT * FROM myTable WHERE id = :id";
$stmt = $conn->prepare($sql);
$stmt->bindParam(':id', $id);
$stmt->execute();
The database should know exactly all the parts of the sql statement before hand:
SELECT these columns: * FROM myTable and WHERE id = "a variable that was input by the user", and if "a variable that was input by the user" != a variable, the query fails.
I have been told by some my understanding is correct, and by others that it is false, could someone please let me know if I am wrong, correct, or missing something? And elaborate as much as you want, all feedback is greatly appreciated!
You're correct that the first case is insecure. It's important to understand though, that preparing a statement only has value if you are using variable data, and/or executing the same query repeatedly. If you are executing plain statements with no variables, you could simply do this:
$sql = "SELECT * from myTable WHERE this_column IS NOT NULL";
$result = $conn->query($sql);
And end up with a PDOStatement object to work with, just like when you use PDO::exec().
For your second case, again, you're largely correct. What's happening is the variable passed to the database is escaped and quoted (unless you specify otherwise with the third argument to PDOStatement::bindParam(), it's sent as a string which is fine for most cases.) So, the query won't "fail" if bad data is sent. It behaves exactly as if you had passed a valid number that didn't exist as an ID in the database. There are, of course, some edge cases where you are still vulnerable even with a correctly prepared statement.
Also, to make life easier, you can use prepared statements like this, to do implicit binding:
$sql = "SELECT * FROM myTable WHERE id = :id";
$stmt = $conn->prepare($sql);
$stmt->execute([":id"=>$id]);
Or even like this, with un-named parameters:
$sql = "SELECT * FROM myTable WHERE id = ?";
$stmt = $conn->prepare($sql);
$stmt->execute([$id]);
Naturally, most of this has been explained in the comments while I was typing up the answer!
I have a conventional query that works just fine that looks like this:
$result = $mysqli->query("SELECT value FROM activities WHERE name = 'Drywall'");
This succeeds in returning a row. However, for the purposes of diagnosing the problem I'm having with a prepared statement, I tried an identical query as a prepared statement like so:
$stmt = $mysqli->prepare("SELECT value FROM activities WHERE name = 'Drywall'");
$stmt->execute();
Despite the fact these are identical query strings, $stmt->num_rows is always 0. Why would the conventional query work, but the prepared statement not when they are the same exact query? Also, I realize including 'Drywall' in the prepared query string runs counter to the purpose of prepared statements, but I was just trying to eliminate the possibility that bind_param() was the culprit. So I was using bind_param() to fill in placeholders and that wasn't working either, despite my double-checking at runtime that the variable I was binding contained the correct value.
I think you want to use
$stmt->store_result();
before the call
$stmt->num_rows();
see last line of the descripton in the manual for $stmt->num_rows() (http://www.php.net/manual/en/mysqli-stmt.num-rows.php).
Check for proper use of the mysqli->prepare. The function depends on a parameter to be passed. It is different from passing the values directly in the query but can use with another way.
Verify the manual:
http://www.php.net/manual/pt_BR/mysqli.prepare.php
Did you try something like this:
$stmt = $mysqli->prepare("SELECT value FROM activities WHERE name = 'Drywall'");
$stmt->execute();
$res = $stmt->get_result();
$row = $res->fetch_assoc();
PS:
Prepared statements are Good. I would urge you to ALWAYS consider using them.
But in this case, a simple query would be much more efficient (would incur fewer round trips) than a prepared statement.
Are all 3 options the same (Y/N) or is one better (A/B/C)?
Option A - (1) defining the SQL string in the variable $sql and (2) define the statement handle using the "method" prepare on the variable $sql to compose the statement and (3) activating composition of the statement in step 2 using the execute function.
$sql = "SELECT * FROM table1";
$sth = $dbh->prepare($sql);
$sth->execute();
Option B - Similar to Option C because the ->query method is used directly on the db object and similar to Option A in that the sql statement is kept separate.
$sql = "SELECT * FROM table1";
$sth = $dbh->query($sql);
Option C - The statement handle is the sql query itself (no reference to any another variables and just using one method.
$sth = $dbh->query("SELECT * FROM table1");
Questions:
Do both options yield the same result?
If they yield the same result, is one approach recommended (i.e. best practice)?
Did I get the vocabulary like "variable", "method", and "function" correct?
Does Option A still query the db despite not explicitly using the ->query() method?
What are the pros/cons of including the sql stmnt in a seperate variable vs in the PDO Statement?
I would say both methods are the same about using a string variable or direct text string.
Assuming you using PDO there is difference between prepare statement and invoke a query statement.
In case A, the prepare statement will make the database create a plan so that statement can be reexecuted without reparsing the query string.
In case B the query is executed at once.
In your given example case B would run a little bit faster.
But if your statement uses arguments case A would benefit you with additional security due to placeholders been replaced by the driver.
Do both options yield the same result?
Yes.
If they yield the same result, is one approach recommended (i.e. best practice)?
Both are fine. In your particular example Option B gets the same job done with less code.
However, if you need to use parameters and/or constraints in your query (e.g. ...WHERE id = :id) you need to opt for option A to bind params using the $dbh->bindParam(':id', $id, PDO::PARAM_INT) method after your prepare your statement, e.g:
$dbh->prepare('UPDATE table SET column = :value WHERE id = :id');
$dbh->bindParam(':value', $someNewValue, PDO::PARAM_STR);
$dbh->bindParam(':id', $targetId, PDO::PARAM_INT);
$dbh->execute();
Doing it this way will also protect you from nasty things like SQL injections.
Storing the query in a separate variable is only needed if you plan to re-use that query at a later time in your code. Otherwise you might as well just type it within your prepare/query method directly.
Did I get the vocabulary like "variable", "method", and "function" correct?
Looks about right! Except: "the execute function" is a method. Functions and methods are basically the same things except when they belong to an object they are referred to as methods. In your example execute belongs to the $sth object, so it's called a method.
Does Option A still query the db despite not explicitly using the ->query() method?
Yes. The execute method executes the query that was prepared in $dbh->prepare(...). If you want to use parameters you can call ->bindParam() between your prepare and execute methods. If you don't need parameters, invoking ->query() directly is really the more convenient way to do it.