Why deos PDO SELECT Work but BASIC INSERT fails? - php

I have connected to the db and able to update a record.
I have a variable named "action" that is either "update" or "add".
I use it in a switch statement to set my query to either "SELECT" or "INSERT".
SELECT statement works.
INSERT statement does not.
I get this error on $pdo->execute($data).
PHP Fatal error: Uncaught PDOException: SQLSTATE[HY093]: Invalid parameter number: parameter was not defined in ...
PDOStatement->execute(Array)
The error is thrown by the PDOStatement
Here is what I have tried, seems pretty straight-forward, but i'm struggling with it.
$data = [
'firstName'=> $firstName,
'lastName'=> $lastName,
'badge'=> $badge,
'department'=> $department,
'image'=> $image,
'active'=> $active,
'stars'=> $stars,
'email'=> $email,
'primary_key'=> $primaryKey,
];
$sql = "INSERT INTO `team`
(`primary_key`,`firstName`, `lastName`, `badge`, `department`, `image`, `active`, `stars`, `email`)
VALUES
(NULL, :firstName, :lastName, :badge, :department, :image, :active, :stars, :email)";
$pdo->prepare($sql);
$pdo->execute($data); <- error is here
When I simply echo my $data array to see if there is something odd. I don't see anything based off all the sites, I've read.
//$data array DATA
primary_key =
firstName = test
lastName = test
badge = 9000
department = marketing
image = 9000.jpg
active = 1
stars = 0
email = tester#test.com
primary_key in db is auto-increment
primary_key is $_post[] on update query and NULL insert query (auto increment db column)
Any errors that would prevent this INSERT query from working that you can see? I'm stuck. I know it the array has 9 variables, there are 9 fields to insert, and 9 values listed.

I know it the array has 9 variables, there are 9 fields to insert, and 9 values listed.
Count the parameters. There are 8 of them. The array includes a value called primary_key for which there is no parameter in the query.
primary_key in db is auto-increment
Then don't insert a value for it:
$sql = "INSERT INTO `team`
(`firstName`, `lastName`, `badge`, `department`, `image`, `active`, `stars`, `email`)
VALUES
(:firstName, :lastName, :badge, :department, :image, :active, :stars, :email)";
And remove primary_key from the $data array.

Related

How to use PHP prepare with zillions of fields of different types

I am inserting data that has VARCHAR, TIMESTAMP and DECIMAL kinds using prepare.
The data is already in the format needed by mySQL.
My problem is this. Suppose I had only 2 items to insert. I would do like this:
$stmt = $mysqli->prepare("INSERT INTO myTable (name, age) VALUES (?, ?)");
$stmt->bind_param("si", $_POST['name'], $_POST['age']);
My problem is the bind part. How do I do the bind when I have to insert 40 columns at once?
I can deal with the prepare part by doing this:
$sql = "INSERT INTO customers ($columns) VALUES ($values)";
$stmt = $mysqli->prepare($sql);
But the next line will result in a ridiculous long line, impossible to understand and very easy to go wrong.
$stmt->bind_param("ssssiidisisssiidiisssidiisidi", ....);
I don't see how I could build that in a loop for example.
How do I do that?
You can pass an array to the mysqli_stmt::bind_param() function as variable arguments with the ... syntax, introduced in PHP 5.6.
$params = ['name', 42];
$stmt = $mysqli->prepare("INSERT INTO myTable (name, age) VALUES (?, ?)");
$stmt->bind_param(str_repeat('s', count($params)), ...$params);
$stmt->execute();
You don't really need to set the data type individually for each column. You can treat them all as 's'.
I know you're asking about mysqli, but I'll just point out that this is easier with PDO:
$params = ['name', 42];
$stmt = $pdo->prepare("INSERT INTO myTable (name, age) VALUES (?, ?)");
$stmt->execute($params);

PHP: PDO MySQL error

I don't really know MySQL but I try.
I have this script in PHP
$sql = $DB->prepare("INSERT INTO `users`(`id`, `firstname`, `lastname`, `email`, `password`) VALUES ($this->firstname, $this->lastname, $this->email, $this->password))");
and when I use
print_r($sql->errorInfo());
It is giving me this error
Warning: PDOStatement::execute(): SQLSTATE[HY093]: Invalid parameter
number: no parameters were bound in
C:\Bitnami\wampstack-5.5.27-0\apache2\htdocs\OOPLogin\register.php on
line 115 Array ( [0] => HY093 [1] => [2] => )
If anyone could help me, I would appreciate it very much.
Thank you.
EDIT: I changed it to
$sql = $DB->prepare("INSERT INTO `users`(`firstname`, `lastname`, `email`, `password`) VALUES ($this->firstname, $this->lastname, $this->email, $this->password))");
And now it's giving me
Array ( [0] => 42000 [1] => 1064 [2] => You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '#gmail.com, ff0b80f26259f9c0178aeed5198bac48))' at line 1 )
Assuming your using PDO, you need to bind parameters with a prepared statement.
Here's an example, using the PDO::prepare documentation for reference:
$statement = $DB->prepare("INSERT INTO `table` (`id`) VALUES (?)");
$statement->execute(array($user_id));
Additional example using mysqli as an alternative...
$statement = $DB->prepare("INSERT INTO `table` (`id`) VALUES (?)");
$statement->bind_param("i", $user_id);
$statement->execute();
You need to bind each of your parameters instead of putting them inline your prepared statement.
You are misusing the prepare() function. When using prepared statements, you are supposed to use either ? or :name as placeholders for your values. This prevents you from constructing a malicious SQL query from user input.
Also, you are listing 5 fields, but only give 4 values. If id is an AUTO_INCREMENT field then it can just be omitted from the query.
Finally, you had too many ) in your query,
$sql = $DB->prepare("INSERT INTO `users`(`firstname`, `lastname`, `email`, `password`)
VALUES (:firstname, :lastname, :email, :password)");
Now you just pass an array of values to execute() to bind to the placeholders.
$sql->execute(array(
'firstname' => $this->firstname,
'lastname' => $this->lastname,
'email' => $this->email,
'password' => $this->password
));
P.S. Your original code didn't work because you forgot to put quotes around your strings.
INSERT INTO `users` (`email`) VALUE ('test#example.com');
Your ID-column does not have a corresponding value to insert, if that column is auto-incrementint you can skip it, like so:
$sql = $DB->prepare("INSERT INTO `users`(`firstname`, `lastname`, `email`, `password`) VALUES ($this->firstname, $this->lastname, $this->email, $this->password))");
you need as many values to insert, as you have columns
An Insert query need to have the same parameters in table fields and values in the same order.
So, if you have id, firstname, lastname, email, password
you need to have idValue, firstnameValue, lastnameValue, emailValue, passwordValue
A good way to try if query is well formed is do an echo $sql or a var_dump($sql) and paste the result on a sql ID query like Mysql Workbench or HeidiSql

php, pdo mysql can't insert with inner join

So I'm a little stuck with the following. I have two tables, projects and change.
Projects:
- id
- title
- description
- datecreated
Change:
- id
- title
- description
- projectid FOREIGN KEY
- datecreated
i can't figure out how to
insert into change (name, description, projectid) value (:name, :description, :projectid)
select id from project
where name = $name
important - the name and description in the insert are provided by php variables using a form.
important - must use PDO
Actual Code:
$sql = "INSERT INTO change (title, description, project_id) SELECT :title, :description, id FROM project WHERE title = :project_title";
$query = $db->prepare($sql);
$query->execute(array(":title" => $title, ":description" => $description, ":project_title" => $created));
This is what I did in the end but Barmar gets the point for help on this and another question.
$sql = "INSERT INTO `change` (`title`, `description`, `project_id`) SELECT :title, :description, id FROM project WHERE title = :project_title";
$query = $db->prepare($sql);
$query->execute(array(":title" => $title, ":description" => $description, ":project_title" => $created));
When you insert, you either use a values clause or you use select to specify the source of the data. You can't use both.
You want:
INSERT INTO `change` (`title`, `description`, `projectid`)
SELECT :title, :description, id
FROM project
WHERE title = :project_title

Prevent SQL Injection on Insert, php

Can someone just save my life been reading for a few hours,
I followed this exactly:
http://docs.php.net/manual/en/pdo.prepared-statements.php
I got this working with sqli but i was told by the group that this was prome to sql injection so i'm trying to improve my code
Alot of the topics here are on SELECT
When I try this i get a blank page, i still haven't gotten apache to render errors that is a separate issue....
this is php:
$dbh = new PDO('mysql:host=localhost;dbname=table', $DBuser, $DBpswd );
$stmt = $dbh->prepare("INSERT INTO `sonyCES2013`.`registration` (`id`, `firstName`, `lastName`, `eMail`, `telephone`, `outlet`, `comfirm`, `boothTour`) VALUES (
:id,
:firstName,
:lastName,
:eMail,
:telephone,
:outlet,
:comfirm,
:boothTour
)");
$stmt->bindParam(':id', NULL);
$stmt->bindParam(':firstName', $fName);
$stmt->bindParam(':lastName',$lName);
$stmt->bindParam(':eMail', $eMail);
$stmt->bindParam(':telephone', $telephone);
$stmt->bindParam(':outlet', $outlet);
$stmt->bindParam(':comfirm',$comfirmation);
$stmt->bindParam(':boothTour', $dateFormatted);
$stmt->execute();
Empty string is not the same as NULL. Also you must pass variables to bindParam() by reference.
If you want to pass a NULL as a query parameter, use
$stmt->bindValue(':id', NULL);
Or you can make a dummy variable and pass that, and give PDO a hint that it's a NULL:
$null = null;
$stmt->bindParam(':id', $null, PDO::PARAM_NULL);
Or else just omit id from the column in your INSERT:
$stmt = $dbh->prepare("INSERT INTO `sonyCES2013`.`registration`
(`firstName`, `lastName`, `eMail`, `telephone`, `outlet`, `comfirm`,
`boothTour`) VALUES ...
The problem was I had set some attributes to NULL. Comfirm was an optional value on the form and if no one selected it, i made the variable NULL. I instead set them to an empty string ''. that solved the problem.

Insert auto-incremented ID using prepared statements

When inserting a new record into a table with an auto-incrementing ID column, it is normally enough to give the ID field the value NULL or omit it from the INSERT query, as explained at How to insert new auto increment ID
INSERT INTO `database`.`table` (`id`, `user`, `result`) VALUES (NULL, 'Alice', 'green')");
or
INSERT INTO `database`.`table` (`user`, `result`) VALUES ('Alice', 'green')");
My question is - how do you do the same thing when using prepared statements. I have tried the following, using NULL:
$stmt = $db->prepare("INSERT INTO `db` (id, name, password, text) VALUES (NULL, ?, ?, ?)");
$stmt->bind_param('sss', $name, $password, $text);
$stmt->execute();
and the fowllowing, omitting the ID field:
$stmt = $db->prepare("INSERT INTO `test_db` (name, password, text) VALUES (?, ?, ?)");
$stmt->bind_param('sss', $name, $password, $text);
$stmt->execute();
When I run this I get nothing inserted and no error message in the browser. I think it is because it is trying to insert a duplicate value for the ID field (stackoverflow.com/questions/12179770/…) - but why it should do that when this seems equivalent to the non-prepared-statement way of inserting data, and then give no message, I'm not sure.
Any ideas most welcome!

Categories