How to update multiple rows in one table (mysql, php, pdo) - php

the thing is when i left text area blank, i want it to delete that entry
I have a table in which i want to update primary key (RegNo) and (Name)
Table students
(Primary Key) (Foreign Key)
RegNo Name Passwd ProjectID
f12345 Ali 345 1
f12346 Chris 346 1
f12347 Ameer 347 1
I am tried few ways,
$names = [
['reg'=> $_POST['s1_id'], 'name'=> $_POST['s1_name']],
['reg'=> $_POST['s2_id'], 'name'=> $_POST['s2_name']],
['reg'=> $_POST['s3_id'], 'name'=> $_POST['s3_name']]
];
$query="update students SET Name=:Name WHERE RegNo=:reg And
ProjectID='$id'";
foreach ( $names as $name)
{
try
{
$stmt = $conn->prepare( $query );
$stmt->bindParam(':Name', $name['name']);
$stmt->bindParam(':reg', $name['reg']);
$result = $stmt->execute();
$msg = "Record updated";
//header("location:adminhome.php");
}
catch(PDOException $ex)
{
$msg = $ex -> getMessage();
}
}
Through this way i was able to update Name column only. How i can update both RegNo and Name. I am new to back-end Programming. Don't know how to achieve this.

Something like this? I only added , RegNo=:reg this inside the SET because reg is already bound I think this is all you need to add.
I updated my answer because it will never match when you send an updated RegNo with your data structure. So you should send two RegNo, the old one, and the new one.
For deleting, I define two queries, one for delete and one for the update. Before we update the results I check inside the foreach if the new Students ID ($name['reg_set']) is empty, if it is we run the $query_delete otherwise we will run $query_update
$names = [
['reg'=> $_POST['s1_id'], 'reg_set'=> $_POST['s1_id_set'], 'name'=> $_POST['s1_name']],
['reg'=> $_POST['s2_id'], 'reg_set'=> $_POST['s2_id_set'], 'name'=> $_POST['s2_name']],
['reg'=> $_POST['s3_id'], 'reg_set'=> $_POST['s3_id_set'], 'name'=> $_POST['s3_name']]
];
$query_delete="DELETE FROM students WHERE RegNo=:reg And ProjectID='$id'";
$query_update="UPDATE students SET Name=:Name, RegNo=:reg_set WHERE RegNo=:reg And
ProjectID='$id'";
foreach ( $names as $name)
{
try
{
if(empty($name['reg_set'])){
$stmt = $conn->prepare( $query_delete );
$stmt->bindParam(':Name', $name['name']);
$stmt->bindParam(':reg', $name['reg']);
$result = $stmt->execute();
$msg = "Record deleted";
}else{
$stmt = $conn->prepare( $query_update );
$stmt->bindParam(':Name', $name['name']);
$stmt->bindParam(':reg', $name['reg']);
$stmt->bindParam(':reg_set', $name['reg_set']);
$result = $stmt->execute();
$msg = "Record updated";
}
//header("location:adminhome.php");
}
catch(PDOException $ex)
{
$msg = $ex -> getMessage();
}
}

Related

Unable to insert into MySQL database with php

In this Insert function where I have to insert a book into the database. The author is already existed in the database and I am trying insert a book that is written by the same author. What I am trying to achieve is to prevent user from entering the already existing author that would make duplicate data. When I get to the record the changelog with BookID but I get the a MySQL error where it says
"PDOException: SQLSTATE[HY000]: General error: 1366 Incorrect integer value: 'SELECT BookID from book WHERE BookID = 102' for column 'BookID' at row 1 in C:\wamp64\www\bookprojectdb\Model\bookInsertFunction.php on line 97".
function addBook2($existauthor, $bt, $ot, $yop, $genre, $sold, $lan, $cip, $bp, $ps, $userID){
global $conn;
try {
$conn->beginTransaction();
//Author Data already exist
//Book Data
$stmt = $conn->prepare("INSERT INTO book(BookTitle, OriginalTitle, YearofPublication, Genre,
MillionsSold, LanguageWritten, CoverImagePath, AuthorID)
VALUES(:bt, :ot, :yop, :genre, :sold, :lan, :cip, :authorid);");
$stmt->bindValue(':bt', $bt);
$stmt->bindValue(':ot', $ot);
$stmt->bindValue(':yop', $yop);
$stmt->bindValue(':genre', $genre);
$stmt->bindValue(':sold', $sold);
$stmt->bindValue(':lan', $lan);
$stmt->bindValue(':cip', $cip);
$stmt->bindValue(':authorid',$existauthor);
$stmt->execute();
//BookPlot Data
$lastbookID = $conn->lastInsertID();
$stmt = $conn->prepare("INSERT INTO bookplot(Plot, PlotSource, BookID)
VALUES(:bp, :ps, :bookid);");
$stmt->bindValue(':bp', $bp);
$stmt->bindValue(':ps', $ps);
$stmt->bindValue(':bookid', $lastbookID);
$stmt->execute();
//Changelog Date Create Insert. This inserts date created, bookid and userid.
$datecreated = (date('y-m-d h:m:s'));
$bookID = "SELECT BookID from book WHERE BookID = $lastbookID";
$stmt = $conn->prepare("INSERT INTO changelog(DateCreated, BookID, UserID)
VALUES(:datecreated, :bookid, :userid);");
$stmt->bindValue(':datecreated', $datecreated);
$stmt->bindValue(':bookid', $bookID);
$stmt->bindValue(':userid', $userID);
$stmt->execute();
//commit
$conn->commit();
}
catch(PDOException $ex) {
$conn->rollBack();
throw $ex;
}
}
$existauthor
$query = $conn->prepare("SELECT Name, Surname, AuthorID FROM author WHERE Name = :name AND Surname = :surname");
$query->bindValue(':name', $name);
$query->bindValue(':surname', $surname);
$query->execute();
$row = $query->fetch();
if($query->rowCount() < 1){ //if author doesn't exists
addBook($name, $surname, $nationality, $yob, $yod,
$bt, $ot, $yop, $genre, $sold, $lan, $cip, $bp, $ps, $userID);
header('location:../View/Pages/adminView.php');
}else {
//if author exists
$existauthor = $row['AuthorID'];
addBook2($existauthor,$bt, $ot, $yop, $genre, $sold, $lan, $cip, $bp, $ps, $userID);
header('location:../View/Pages/adminView.php');
}
I thought that by using "lastinsertID();", it would have recorded ID of recently created book. Please Help !
'SELECT BookID from book WHERE BookID = 102' - that is an incorrect integer value indeed.
You have this value assigned to a variable:
$bookID = "SELECT BookID from book WHERE BookID = $lastbookID";
and then you're trying to bind it in place of an integer:
$stmt->bindValue(':bookid', $bookID);
Here's the help you need:
if(!$stmt->execute()) echo $stmt->error;
You ALWAYS should expect errors, and have a workaround, but first you need to check for errors

Insert rows for an m:m relationship (pupil-evening_activity) consistently

I have three tables in my database (MySQL/InnoDB): pupil, evening_activity and pupil_evening_activity. As you can guess there is an m:m relationship between pupil and evening_activity.
I have a HTML form to insert new pupils and associate to them evening activities. After submitting the form, I would like to insert pupils and their associated activities in the database. So I have written this code:
$db = new PDO('mysql:host=localhost;dbname=school;charset=utf8','root', '****');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
try {
$sql = "INSERT INTO pupil
(name, surname)
VALUES
('test_name', 'test_surname')";
$st = $db->prepare($sql);
$st->execute();
foreach ($eveningActivityIds as $eveningActivityId) {
$sql = "INSERT INTO pupil_evening_activity
(pupil_id, evening_activity_id)
VALUES
(?, ?)
";
$st = $db->prepare($sql);
$st->execute(array($db->lastInsertId(), $eveningActivityId));
}
} catch (PDOException $e) {
echo $e->getMessage();
return false;
}
I have written that code expecting PDO::lastInsertId() always returns the last inserted pupil's id, but I've found out that what it really returns is the last inserted id on the whole database. So if another row is inserted in a hypothetical teacher table just before calling to $db->lastInsertId() on the code above, $db->lastInsertId() would return the id of the inserted teacher instead of the id of the last pupil.
So how I can get 100% safety the last inserted id of pupil table after submitting the form?
I have thought about using a transaction and MAX() function to get last id inserted in the pupil table, but I'm not sure about it.
It's a mistake to have $db->lastInsertId() within the foreach loop, as it may return unpredictable values. Please consider the code below:
try {
$sql = "INSERT INTO pupil
(name, surname)
VALUES
('test_name', 'test_surname')";
$st = $db->prepare($sql);
$st->execute();
// save pupil id into variable here:
$pupil_id = $db->lastInsertId();
// also there's no need to prepare the statement on each iteration:
$sql = "INSERT INTO pupil_evening_activity
(pupil_id, evening_activity_id)
VALUES
(?, ?)";
$st = $db->prepare($sql);
foreach ($eveningActivityIds as $eveningActivityId) {
$st->execute(array($pupil_id, $eveningActivityId));
}
} catch (PDOException $e) {
echo $e->getMessage();
return false;
}
Optimization: you can insert all acivities in one statement. It saves you few requests
try {
$sql = "INSERT INTO pupil
(name, surname)
VALUES
('test_name', 'test_surname')";
$st = $db->prepare($sql);
$st->execute();
// save pupil id into variable here:
$pupil_id = $db->lastInsertId();
$sql = 'INSERT INTO pupil_evening_activity
(pupil_id, evening_activity_id)
VALUES ';
$values = array();
foreach ($eveningActivityIds as $eveningActivityId) {
$sql .= '(?, ?),';
array_push($values, $pupil_id, $eveningActivityId);
}
$st = $db->prepare(chop($sql, ','));
$st->execute($values);
} catch (PDOException $e) {
echo $e->getMessage();
return false;
}

Insert record if user_id is unique in table, if not update column

I need to INSERT record if user_id is unique in table map, but if not then UPDATE that row where user_id=:user_id with data...
What I try:
try {
$result = $db->prepare('SELECT user_id FROM map WHERE user_id=:user_id');
$result->bindParam(':user_id', $user_id);
$result->execute();
//echo $jsonTable;
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
try {
if ($result==null) {
$STH = $db->prepare("INSERT INTO map (json, user_id) VALUES (:json, :user_id)");
$STH->bindParam(':json', $_POST['mapData']);
$STH->bindParam(':user_id', $user_id);
$STH->execute();
} else {
$STH = $db->prepare("UPDATE map SET json = :json WHERE user_id= :user_id");
$STH->bindParam(':json', $_POST['mapData']);
$STH->bindParam(':user_id', $user_id);
$STH->execute();
}
} catch (PDOException $e) {
echo $e->getMessage();
}
echo "<p>Data submitted successfully</p>";
}
So here I try to check is user_id I need to add exist into table, and if there is no user_id, so if prepared user_id is new then I try to insert data, but if user_id alredy excist into table then to UPDATE that record...
But this dont work for me, also dont give me any error?
I'beginer to php, so sorry about trivial question... Thanks!
UPDATE:
I also try to insert but if user_id is duplicate then to UPDATE:
try {
$STH = $db->prepare("INSERT INTO map (user_id, json) VALUES (:user_id,:json)
on duplicate key update json=values(json)");
$STH->bindParam(':json', $_POST['mapData']);
$STH->bindParam(':user_id', $user_id);
$STH->execute();
} catch (PDOException $e) {
echo $e->getMessage();
}
echo "<p>Data submitted successfully</p>";
}
To check uniqueness you can use an unique key to have uniqueness checked by the db: http://dev.mysql.com/doc/refman/5.6/en/mysql-indexes.html
Or better, ususally ids are primary keys of the table, this means you don't need to worry about uniqueness, primary key is always unique and the db checks it for you

Add data into two table connected with id

Hi here I have this code to insert data to mysql database into table radnici :
try {
$STH = $db->prepare("INSERT INTO radnici (ime_prezime, jmbg, grad, ulica, posta, telefon, uloga, email, user_id) VALUES (:1,:2,:3,:4,:5,:6,:7,:8,:9)");
$STH->bindParam(':1', $_POST['ime']);
$STH->bindParam(':2', $_POST['jmbg']);
$STH->bindParam(':3', $_POST['grad']);
$STH->bindParam(':4', $_POST['ulica']);
$STH->bindParam(':5', $_POST['posta']);
$STH->bindParam(':6', $_POST['telefon']);
$STH->bindParam(':7', $_POST['pozicija']);
$STH->bindParam(':8', $_POST['email']);
$STH->bindParam(':9', $user_id);
//HERE I NEED TO INSERT DATA TO TABLE WORKHOURS BUT CONNECTED WITH JUST ADDEDED ID
//SO here I NEED query something like this // INSERT INTO radnici (ID, ID_radnici, ime_prezime, jmbg,... here ID_radnici is =with ID from table radnici of added data
$STH->execute();
} catch (PDOException $e) {
echo $e->getMessage();
}
echo "<p>Data submitted successfully</p>";
So now when I add this I need to add into this table workhours data but connected with ID with just added data...
so in second table I have: ID, ID_radnici (here I must add ID_radnici same value as ID on table radnici), value, user_id
I write this but DONT work:
UPDATE:
try {
$STH = $db->prepare("INSERT INTO radnici (ime_prezime, jmbg, grad, ulica, posta, telefon, uloga, email, user_id) VALUES (:1,:2,:3,:4,:5,:6,:7,:8,:9)");
$STH->bindParam(':1', $_POST['ime']);
$STH->bindParam(':2', $_POST['jmbg']);
$STH->bindParam(':3', $_POST['grad']);
$STH->bindParam(':4', $_POST['ulica']);
$STH->bindParam(':5', $_POST['posta']);
$STH->bindParam(':6', $_POST['telefon']);
$STH->bindParam(':7', $_POST['pozicija']);
$STH->bindParam(':8', $_POST['email']);
$STH->bindParam(':9', $user_id);
$orderID = $db -> lastInsertId();
$STH1 = $db->prepare("INSERT INTO workhours (ID_radnika) values($orderID)"); // where $value is the value you want to insert...
$STH->execute();
$STH1->execute();
} catch (PDOException $e) {
echo $e->getMessage();
}
echo "<p>Data submitted successfully</p>";
Using lastInsertId will do what you want:
$orderID = $db -> lastInsertId();
Use lastInsertId() and insert your data into the other table using the value returned from it.
Something like this:
int $lastID = $db->lastInsertId();
if ( $lastID ) {
$STH = $db->prepare("INSERT INTO workhours (ID_radnici, value, userid) values($lastID, $value, $user_id)"); // where $value is the value you want to insert...
$STH->execute();
}

Better solution for sequential statement executions with PDO and PHP

I have 3 tables which I have to add a record to them after registration of a new user:
List of Tables:
I. users
... ... ... id (auto_increment, primary)
... ... ... email (email address of new user)
II. blogs
... ... ... id (auto_increment, primary)
... ... ... owner_id (= 'id' in 'users')
III. events
... ... ... id (auto_increment, primary)
... ... ... owner_id (= 'id' in 'users')
... ... ... blog_id (= 'id' in 'blogs')
In this situation I found 2 solutions for adding sequential records:
Solution 1: Using lastInsertId
<?php
try {
// Step 1: add a record to 'users' table and get lastInsertId
$query = $conn->prepare("INSERT INTO users (email) VALUES (:email)");
$query->bindParam(':email', $email);
$query->execute();
$user_id = $conn->lastInsertId();
// Step 2: add a record to 'blogs' table and get lastInsertId
$query = $conn->prepare("INSERT INTO blogs (owner_id) VALUES (:owner)");
$query->bindParam(':owner', $user_id);
$query->execute();
$blog_id = $conn->lastInsertId();
// Step 3: add a record to 'events' table
$query = $conn->prepare("INSERT INTO events (owner_id, blog_id) VALUES (:owner, :blog)");
$query->bindParam(':owner', $user_id);
$query->bindParam(':blog', $blog_id);
$query->execute();
} catch (PDOException $e) {
echo $e->getMessage();
}
?>
Solution 2: Using single execute()
<?php
try {
// Step 1
$query = $conn->prepare("INSERT INTO users (email) VALUES (:email);" .
"INSERT INTO blogs (owner_id) VALUES ((SELECT id FROM users WHERE email = :email));" .
"INSERT INTO events (owner_id, blog_id) VALUES ((SELECT id FROM users WHERE email = :email), (SELECT id FROM blogs WHERE owner_id = (SELECT id FROM users WHERE email = :email)));");
$query->bindParam(':email', $email);
$query->execute();
} catch (PDOException $e) {
echo $e->getMessage();
}
?>
Which solution should I choose for a better performance and security? Is there a better solution for my purpose?
Note: the connection created using PDO:
<?php
$options = array(
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
);
try {
$conn = new PDO("mysql:host=" . App::DB_HOST . ";dbname=" . App::DB_NAME . ";charset=utf8", App::DB_USERNAME, App::DB_PASSWORD, $options);
} catch (PDOException $e) {
echo $e->getMessage();
}
?>
I would use transactions as a modification of 1st option.
$conn->beginTransaction();
try {
// Step 1: add a record to 'users' table and get lastInsertId
$query = $conn->prepare("INSERT INTO users (email) VALUES (:email)");
$query->bindParam(':email', $email);
$query->execute();
$user_id = $conn->lastInsertId();
// Step 2: add a record to 'blogs' table and get lastInsertId
$query = $conn->prepare("INSERT INTO blogs (owner_id) VALUES (:owner)");
$query->bindParam(':owner', $user_id);
$query->execute();
$blog_id = $conn->lastInsertId();
// Step 3: add a record to 'events' table
$query = $conn->prepare("INSERT INTO events (owner_id, blog_id) VALUES (:owner, :blog)");
$query->bindParam(':owner', $user_id);
$query->bindParam(':blog', $blog_id);
$query->execute();
$conn->commit();
}
catch (PDOException $e) {
// roll back transaction
$conn->rollback();
echo $e->getMessage();
die();
}
If you do some benchmarks you will see most time will be lost making the request.
From personal benchmarks on simple queries like this the execution time is very low.
The only thing that realy took time is the initialisation/prepare function.
There for making 3 requests will be slower then creating one large one.
EDIT:
Option 1 is the correct one because you do need to use id's, never link using a string or somethign else allways use id's.
Appart from that 1 (prepared) big query is better then 3x a prepare.
Edit. I misread the question at first, thought you are using exec(), not execute().
So, in fact you can combine both, as lastInsertId is just a PHP wrapper for Mysql's LAST_INSERT_ID()
But, as you need two ids, it will require additional mess with setting a variable. So, I doubt second option would worth, although feasible.
Just note that second would work only if PDO emulation mode is turned off
And surely there is no such question like "performance". Both will go perfectly.

Categories