PHP Prepared Statement Fails - php

I'm passing a prepared sql insert statement (using placeholders ?, ?) into a mysql database. I'm then using ->execute($array) and passing a single array of the values in. It's working great (ie inserts) when there is data entered into every field of the form (the array is complete), however fails completly if just one single element is not completed.
With the older mysql_query, if a value was missing it would simply not insert that value into the database.
How do we deal with this in prepared statements?
Thanks!

They way you deal with it is to properly ensure you have entered all relevant values for your query. mysql_query() can be as lax as it wants because at the end of the day, it only has to support MySQL, but PDO is a generic interface for relational data storage and it does not take the job of making sure you've entered all your data.

I don't see the comparison because mysql_query doesn't take parameters?
The PDO object requires you to bind your elements to the parameters. This is the long-way:
$stmt->bindParam(":namedParam", 1, PDO::PARAM_INT);
This is short-hand, so internally PDO still should do the above with some extra work for itself:
$stmt->execute(array($value1, $value2, $etc));
If your query looks like this:
INSET INTO mytbl VALUES (?, ?, ?, ?, ?)
and your $data array looks like this:
$data = array($val1, $val2, $val3);
Where do you think the two NULL values should be inserted?
1st & 3rd ?'s ? How should PDO know that?
Furthermore, if you do know the answer to that question, you can still handle it in PHP:
function queryMyTable($val1, $val2, $val3, $val4 = null, $val5 = null) {
...
$stmt->execute(array($val1, $val2, $val3, $val4, $val5));
}

Related

PHP mysqli multiple queries bind_param crash [duplicate]

I would like to know if i can prepare one mysqli statement that executes multiple queries:
mysqli->prepare(query1 ...1,2,3 param...; query2...4,5 param...);
or
mysqli->prepare(insert into ...1,2,3 param...; insert into...4,5 param...);
and after all
mysqli->bind_param("sssss", 1, 2, 3, 4, 5);
In that way it make error: Call to a member function bind_param() on a non-object in...
$stmt = $sql->getQueryPrepare("INSERT INTO user (id_user, username, pw, email) VALUES (?,?,?,?); INSERT INTO process (id_user, idp) VALUES (?,?);");
$stmt->bind_param("ssssss",$id, $username, $pw, $email, $id, $idp);
$stmt->execute();
$stmt->close();
A prepared statement can only execute one MySQL query. You can prepare as many statements as you want in different variables:
$stmtUser = $sql->prepare("INSERT INTO user (id_user, username, pw, email) VALUES (?,?,?,?)");
$stmtProc = $sql->prepare("INSERT INTO process (id_user, idp) VALUES (?,?);");
And then execute them later. If you want to ensure that neither one is ever run unless both are able to run, then you need to look into transactions, like Thomas said.
Also, a general tip: "call to member function on a non-object" is the standard error you get when prepare() fails and so $stmt isn't actually a prepared statement object. It usually means you need to look for an error in your prepare() statement rather than anything later.
No, a single call to the mysqli prepare() function cannot prepare multiple queries at once. You can, however, prepare more than one query for execution by using different variables. The documentation for this function is available here.
It also looks like you are trying to setup a transaction, which is a different question than you asked. If that's what you really want to know, then you'll need to provide more information about your database setup and probably more specifics about the use case you are trying to solve.

PHP: Statement fails to prepare but SQL is correct [duplicate]

I would like to know if i can prepare one mysqli statement that executes multiple queries:
mysqli->prepare(query1 ...1,2,3 param...; query2...4,5 param...);
or
mysqli->prepare(insert into ...1,2,3 param...; insert into...4,5 param...);
and after all
mysqli->bind_param("sssss", 1, 2, 3, 4, 5);
In that way it make error: Call to a member function bind_param() on a non-object in...
$stmt = $sql->getQueryPrepare("INSERT INTO user (id_user, username, pw, email) VALUES (?,?,?,?); INSERT INTO process (id_user, idp) VALUES (?,?);");
$stmt->bind_param("ssssss",$id, $username, $pw, $email, $id, $idp);
$stmt->execute();
$stmt->close();
A prepared statement can only execute one MySQL query. You can prepare as many statements as you want in different variables:
$stmtUser = $sql->prepare("INSERT INTO user (id_user, username, pw, email) VALUES (?,?,?,?)");
$stmtProc = $sql->prepare("INSERT INTO process (id_user, idp) VALUES (?,?);");
And then execute them later. If you want to ensure that neither one is ever run unless both are able to run, then you need to look into transactions, like Thomas said.
Also, a general tip: "call to member function on a non-object" is the standard error you get when prepare() fails and so $stmt isn't actually a prepared statement object. It usually means you need to look for an error in your prepare() statement rather than anything later.
No, a single call to the mysqli prepare() function cannot prepare multiple queries at once. You can, however, prepare more than one query for execution by using different variables. The documentation for this function is available here.
It also looks like you are trying to setup a transaction, which is a different question than you asked. If that's what you really want to know, then you'll need to provide more information about your database setup and probably more specifics about the use case you are trying to solve.

SQL Error #1054 caused by single quotes?

I have built one PHP page which sends virtually identical information to two different tables (one is accessible by all users of the site, the other is a user's individual table).
$post = "INSERT INTO `Alpha` (`number`, `field1`, `field2`,
`field3`, `field4`, `field5`, `field6`, `field7`, `field8`, `field9`,
`field10`) VALUES (NULL, ?, ?, ?, ?, ?, ?, ?, ?, '0', '0')";
$dbh = new PDO( "mysql:dbname=essay;host=localhost", "root", "password" );
$selectStatement = $dbh->prepare( $post );
$selectStatement->bindValue(1, $name, PDO::PARAM_STR);
$selectStatement->bindValue(2, $id, PDO::PARAM_INT);
$selectStatement->bindValue(3, $head, PDO::PARAM_STR);
$selectStatement->bindValue(4, $text, PDO::PARAM_STR);
$selectStatement->bindValue(5, $topic1, PDO::PARAM_STR);
$selectStatement->bindValue(6, $topic2, PDO::PARAM_STR);
$selectStatement->bindValue(7, $topic3, PDO::PARAM_STR);
$selectStatement->bindValue(8, $date, PDO::PARAM_INT);
$selectStatement->execute();
This is the code for the first table, and it works. The code for the second table is literally copied and pasted from this - the only difference being that the table name is changed (since it is unique to the user it is also now in the prepared statement) and one of the field names is changed (and I've created a new PDO object), but for some reason it won't work.
I put together a string which represents what the SQL query ought to look like, having it echo out each time I make a query, and when I input it manually I'm getting error #1054.
The strange thing is that the error goes away if I alter the query such that all of my string values are wrapped in single quotes. This, of course, is quite confusing because the first query didn't demand single quotes - why then would the second, since they are almost identical? Do I have some kind of weird setting on my SQL table of which I am unaware? If I could make the database accept the query without single quotes that would be ideal.
Regardless, when I append single quotes to both ends of the variables in my prepared statement, the prepared statement seems to be stripping them out, so I'm not sure how to get the single quotes on, but if I could I suppose that solution would suffice.
Table (and column) names can't be provided as parameters in prepared statements, which your description leads me to believe you've done.
See this old SO question
Have you tried PDO::quote? Looks like it handles escaping strings and might help solve those issues that you're facing.

ON DUPLICATE KEY UPDATE not working in PDO

INSERT INTO b (id, website...)
VALUES (:id, :website...)
ON DUPLICATE KEY UPDATE
website=:website ...
I have a MYSQL QUERY, I have SET id unique, why
website=:website ...
is not working, when I change to website="whatever" it works. anyone know why?
$job_B->bindValue(':website', $website, PDO::PARAM_STR);
As a general tip, you shouldn't be "duplicating" inserted values when doing an ON DUPLICATE KEY. Mysql provides the VALUES() function for this purpose, e.g.
INSERT INTO foo (bar) VALUES (:baz)
ON DUPLICATE KEY UPDATE bar := :baz
can be better rewritten as
INSERT INTO foo (bar) VALUES (:baz)
ON DUPLICATE KEY UPDATE bar = VALUES(bar)
^^^^^^^^^^^
VALUES() will re-use the value assigned to the specified field in the VALUES (...) section automatically, without requiring binding another variable into the query.
You have run into an unfortunate and misleading behavior of PDO's named parameters in a prepared statement. Despite assigning names, you cannot actually use a parameter more than once, as mentioned in the prepare() documentation:
You must include a unique parameter marker for each value you wish to pass in to the statement when you call PDOStatement::execute(). You cannot use a named parameter marker of the same name twice in a prepared statement. You cannot bind multiple values to a single named parameter in, for example, the IN() clause of an SQL statement.
This means you'll need to bind the parameter twice, with two different names, and consequently two different bindValue() calls:
$stmt = $pdo->prepare("
INSERT INTO b (id, website...)
VALUES (:id, :website_insert...)
ON DUPLICATE KEY UPDATE
website=:website_update ...
");
// Later, bind for each
$job_B->bindValue(':id', ...);
// Same value twice...
$job_B->bindValue(':website_insert', $website, PDO::PARAM_STR);
$job_B->bindValue(':website_update', $website, PDO::PARAM_STR);
The use of VALUES() to refer to the new row and columns is deprecated beginning with MySQL 8.0.20, and is subject to removal in a future version of MySQL.

PDO Prepared Statements: having trouble binding multiple values to query

I am new to PDO and prepared statements and I am having trouble binding multiple values to my query. I have no problem if it is just one while making a SELECT, for example:
SELECT foo FROM table WHERE id=:something // no problem
But multiple, and trying to INSERT I am getting stuck:
Insert INTO mytable (field1, field2) VALUES (:value1, :value2) // No bueno
Have tried a few different ways and read other posts on here but no luck. Below is an example of what I am having trouble with:
$insertSQL = $db->prepare("INSERT INTO voting_poll (ipaddress, choice)
VALUES (':ipaddress', :value)");
$insertSQL->bindParam(':ipaddress', getenv('REMOTE_ADDR'), PDO::PARAM_STR);
$insertSQL->bindParam(':value', $_POST['radio'], PDO::PARAM_STR);
$insertSQL->execute();
I am getting the following error: Invalid parameter number: number of bound variables does not match number of tokens
You don't put quotes around params. Remove the quotes around :ipaddress in your query.
bindParam() must be used with a variable as it binds the parameter to the variable reference. If you want to use a value (for example, the return value from a function like getenv()), use bindValue() instead.

Categories