PDO lastInsertId in the same query - php

Hello so I have a table named tblcontactlist and have 5 columns (contactID, contactName, contactEmail, contactNumber, hashed_id) and this is my working query
$query = "INSERT INTO tblcontactlist (contactName, contactEmail, contactNumber) VALUES (:cname, :cea, :cnum)";
$stmt = $dbc->prepare($query);
$stmt->bindParam(':cname', $contactName);
$stmt->bindParam(':cea', $emailAdd);
$stmt->bindParam(':cnum', $contactNumber);
$stmt->execute();
$last_id = $dbc->lastInsertId('contactID');
$hashed_id = sha1($last_id);
$query2 = "UPDATE tblcontactlist SET hashed_id=:hid WHERE contactID=:cid";
$stmt2 = $dbc->prepare($query2);
$stmt2->bindParam(':hid', $hashed_id);
$stmt2->bindParam(':cid', $last_id);
$stmt2->execute();
What this basically does is insert a new record then updates the latest inserted record with a hashed id on the hashed_id column. Is there a proper way of doing this? I mean shorter code or better code. Thanks!

lastInsertId presupposes that you have a previous INSERT beforehand, that you don't have. In this case, lastInsertId is the max contactID. So I would perform a query to get and hash the max contactID and then perform one insert query (and no update).
//fetch Max contactID
$res=$dbc->prepare("SELECT MAX(contactID) FROM tblcontactlist");
$res->execute();
$fetchMax=$res->fetch(PDO::FETCH_NUM);
$last_id=$fetchMax[0];
//hash the max contactID
$hashed_id = sha1($last_id);
//for reusability you can create a function with the above code.
And now perform the insert query:
$query = "INSERT INTO tblcontactlist (contactName, contactEmail, contactNumber, hashed_id) VALUES (:cname, :cea, :cnum, :hid)";
$stmt = $dbc->prepare($query);
$stmt->bindParam(':cname', $contactName);
$stmt->bindParam(':cea', $emailAdd);
$stmt->bindParam(':cnum', $contactNumber);
$stmt->bindParam(':hid', $hashed_id);
$stmt->execute();
Is that better for you?

Related

MySQL INSERT with a field coming from another table fails

I Need to insert data in a table but 1 of the fields will come from another table but not working...
Code as below:
//Save payment to table paylog
$sql = "INSERT INTO `paylog`(`payment_id`, `date_approved`, `newcredit`, `before`) VALUES (?,?,?,?)";
$stmt = $conn->prepare($sql);
$stmt->bind_param('ssss',$payment->id,$dateApproved,
$payment->transaction_amount,(SELECT credit from tokens WHERE token=$payment->external_reference LIMIT 1));
$stmt->execute();
$stmt->close();
Assistance welcome
Paulo
Just move that SELECT subquery up inside of $sql, keep $payment->external_reference as a binded parameter.
See https://stackoverflow.com/a/42132551/7977859

PHP returning output from a Stored Procedure

I have seen and read a few questions about this but I can't figure out what's going on. I have a SP that inserts into a table and then returns just a single column with the last inserted id(Since I'm executing multiple statments lastInsertID() doesn't work.
CREATE DEFINER=`graffixnyc`#`%` PROCEDURE `createUser`(
IN userName VARCHAR(50),
IN firstName VARCHAR(25),
IN lastName VARCHAR(25),
IN pass text)
BEGIN
SELECT FLOOR(RAND() * 0xFFFFFFFF) into #salt;
INSERT INTO `users` (`username`, `first_name`,`last_name`,`salt`,`password`)
VALUES (userName, firstName,lastName, (select
#salt),sha2(concat(md5(pass(select #salt)),256));
SELECT LAST_INSERT_ID() as lastinsert;
END
Now when I execute this is MySql is returns the value of the last inserted record. When I try to access it with PHP I get Null.
$paramUsername = $req->params('username'); // Getting parameter with names
$paramFirstName = $req->params('firstname');
$paramLastName = $req->params('lastname');
$paramPassword = $req->params('password');
$sql = "CALL createUser(:username, :firstname,:lastname,:password)";
try {
$dbCon = getConnection();
$stmt = $dbCon->prepare($sql);
$stmt->bindParam("username", $paramUsername);
$stmt->bindParam("firstname", $paramFirstName);
$stmt->bindParam("lastname", $paramLastName);
$stmt->bindParam("password", $paramPassword);
$stmt->execute();
$row= $stmt->fetch();
$last_id=$row["lastinsert"];
$user->id =$last_id;
I have also tried using an output Paramater like so:
CREATE DEFINER=`graffixnyc`#`%` PROCEDURE `createUser`(
IN userName VARCHAR(50),
IN firstName VARCHAR(25),
IN lastName VARCHAR(25),
IN pass text,
OUT lastinsert INT)
BEGIN
SELECT FLOOR(RAND() * 0xFFFFFFFF) into #salt;
INSERT INTO `users` (`username`, `first_name`,`last_name`,`salt`,`password`)
VALUES (userName, firstName,lastName, (select
#salt),sha2(concat(md5(pass(select #salt)),256));
SET lastinsert=(SELECT LAST_INSERT_ID());
SELECT lastinsert;
END
$paramUsername = $req->params('username');
$paramFirstName = $req->params('firstname');
$paramLastName = $req->params('lastname');
$paramPassword = $req->params('password');
$sql = "CALL createUser(:username, :firstname,:lastname,:password,
#lastinsert)";
try {
$dbCon = getConnection();
$stmt = $dbCon->prepare($sql);
$stmt->bindParam("username", $paramUsername);
$stmt->bindParam("firstname", $paramFirstName);
$stmt->bindParam("lastname", $paramLastName);
$stmt->bindParam("password", $paramPassword);
$stmt->execute();
$row = $dbCon->query("select #lastinsert;")>fetch();
$last_id=$row["#lastinsert"];
$user->id =$last_id;
When I try it like this I get this error:
{"error":{"text":SQLSTATE[HY000]: General error: 2014 Cannot execute queries
while other unbuffered queries are active. Consider using
PDOStatement::fetchAll(). Alternatively, if your code is only ever going to
run against mysql, you may enable query buffering by setting the
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.}}
So I tried FetchAll and got the same error.. I then tried this which I found here which works but since it's only returning 1 row with 1 feild it doesn't seem like I should really need to loop through anything:
$stmt->execute();
$stmt = $dbCon->prepare("select #lastinsert;");
$outputArray = $dbCon->query("select #lastinsert;")->fetchAll();
foreach($outputArray as $row)
{
$last_id=$row["#lastinsert"];
}
So if there a better way to do this? I'm sure there is. I'm pretty new to PHP and mySQL but have a lot of experience with SQLServer so any insight would be appreciated.
I figured it out.. This works well and I don't need the input paramater or the loop:
SP:
CREATE DEFINER=`graffixnyc`#`%` PROCEDURE `createUser`(
IN userName VARCHAR(50),
IN firstName VARCHAR(25),
IN lastName VARCHAR(25),
IN pass text)
BEGIN
SELECT FLOOR(RAND() * 0xFFFFFFFF) into #salt;
INSERT INTO `users` (`username`, `first_name`,
`last_name`,`salt`,`password`)
VALUES (userName, firstName,lastName, (select #salt),sha2(concat(md5(pass
),(select #salt)),256));
SELECT LAST_INSERT_ID()as lastinsert;
END
PHP:
$paramUsername = $req->params('username');
$paramFirstName = $req->params('firstname');
$paramLastName = $req->params('lastname');
$paramPassword = $req->params('password');
$sql = "CALL createUser(:username, :firstname,:lastname,:password)";
try {
$dbCon = getConnection();
$stmt = $dbCon->prepare($sql);
$stmt->bindParam("username", $paramUsername);
$stmt->bindParam("firstname", $paramFirstName);
$stmt->bindParam("lastname", $paramLastName);
$stmt->bindParam("password", $paramPassword);
$stmt->execute();
$user->id =$stmt->fetchColumn(0);
$dbCon = null;

SQL insert into select issue

So i think i'm close to figuring this out but my query won't add the item from the "pending" table to the "items" table. can you guys help me out with this please. Also if i want it to delete after it gets added should i add the code below the INSERT INTO SELECT query? thanks
action.php:
$sql = "INSERT INTO items (photo,title,description, name) SELECT (photo,title,description, name) FROM pending";
$stmt = $conn->prepare($sql);
$stmt->execute();
Example for delete query after it takes the item from the "pending" into items:
$idToDelete = filter_var($_POST["recordToDelete"],FILTER_SANITIZE_NUMBER_INT);
//try deleting record using the record ID we received from POST
$sql = "DELETE FROM pending WHERE id = :id";
$stmt = $conn->prepare($sql);
$stmt->bindParam(':id', $idToDelete, PDO::PARAM_INT);
$stmt->execute();
I think you are leaving yourself open to mistakes doing it this way.
Consider what would happen if a new row is added to the pending queue after you have issued the INSERT SELECT but before you have started your delete.
I think you need to do this in a more controlled way inside a single loop to make sure you are only deleting what you have copied from pending into items.
$sql = "SELECT photo,title,description, name FROM pending";
$select_pending = $conn->prepare($sql);
$select_pending->execute();
$sql = "INSERT INTO items (photo,title,description, name)
VALUES (:photo,:title,:description, :name)";
$insert_items = $conn->prepare($sql);
$sql = "DELETE FROM pending WHERE id = :id";
$delete_pending = $conn->prepare($sql);
// only if you are using INNODB databases.
//$conn->beginTransaction();
while( $row = $select_pending->fetch_object() ) {
$insert_items->bindParam(':photo', $row->photo, PDO::PARAM_STR);
$insert_items->bindParam(':title', $row->title, PDO::PARAM_STR);
$insert_items->bindParam(':description', $row->description, PDO::PARAM_STR);
$insert_items->bindParam(':name', $row->name, PDO::PARAM_STR);
$insert_items->execute();
$delete_pending->bind_param(':id', $row->id, PDO::PARAM_INT);
$delete_pending->execute();
}
// only if you are using INNODB databases.
//$conn->commit();
$sql = "INSERT INTO items (photo,title,description, name)
SELECT photo,title,description, name FROM pending";
remove the () in the SELECT statement.

looping a php script to insert data for multiple users

I have two tables: phpbb_sn_fms_groups and phpbb_fms_user_groups, which I would like to INSERT into using the two queries below, however the first problem is I can't possibly manually run the two queries ~1000 times for each user_id (56 through 1060). The second problem is I need to INSERT the auto incremented fms_gid from the first query (table: phpbb_sn_fms_groups) into fms_id from the second query (table: phpbb_sn_fms_users_group) when the php script INSERTs each user_id.
// user_id: 56 through 1060
// fms_gid in the table phpbb_sn_fms_users_group needs the unique fms_gid for each row from the table phpbb_sn_fms_groups because it doesn't autoincrement.
$result = mysql_query("INSERT INTO phpbb_sn_fms_groups (fms_gid, user_id, fms_name, fms_clean, fms_collapse) VALUES ('autoincrementednumberthatdoesntneedtobeinserted', '56', 'Staff', 'staff', '0')")
or die(mysql_error());
$result = mysql_query("INSERT INTO phpbb_sn_fms_users_group (fms_gid, user_id, owner_id) VALUES ('inserttheautoincrementednumberfromfms_gidinphpbb_sn_fms_groups', '2', '56')")
or die(mysql_error());
Any help would be appreciated. Thanks!
This is a great time for PDO.
See http://php.net/manual/en/book.pdo.php for connection info but something like
$pdo = new PDO("mysql:host=$host;dbname=$dbname", $user, $pass);
$pdo->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
// First select the users you need query.
$stmt = $pdo->prepare("SELECT id, name FROM users WHERE id BETWEEN 56 AND 1060");
$stmt->execute();
$result = $stmt->fetchAll();
OR if literally 56 through 1060 you can use a for loop.
Then loop through those results to execute
foreach($result as $row) {
$stmt1 = $pdo->prepare("INSERT INTO phpbb_sn_fms_groups (fms_gid, user_id, fms_name, fms_clean, fms_collapse) VALUES ('autoincrementednumberthatdoesntneedtobeinserted', :user_id , 'Staff', 'staff', '0')");
$stmt1->bindParam(":user_id", $row['id']);
$stmt1->execute();
//get last inserted id.
$inserted_id = $pdo->lastInsertId();
$stmt2 = $pdo->prepare("INSERT INTO phpbb_sn_fms_users_group (fms_gid, user_id, owner_id) VALUES (:last_id, '2', :user_id)");
$stmt2->bindParam(":last_id", $inserted_id);
$stmt2->bindParam(":user_id", $row['id']);
$stmt2->execute();
}
Hope this gets you started. Can also be done in mysqli. Don't want to jump into that debate. I just like naming the parameters for binding.

PHP insert into database query

I am trying to insert values into a database table, a row is inserted but blank no values are inserted. Only the order_id which is the primary key with auto increment increase.
php code:
<?php
$user_get = mysql_query("SELECT * FROM users");
while($row_user = mysql_fetch_assoc($user_get)){
if($row_user['username'] == $_SESSION['username']){
$row_user['first_name'] = $res1;
$row_user['last_name'] = $res2;
$store_order ="INSERT INTO oko (user, product) VALUES ('$res1', '$res2')";
mysql_query($store_order);
}
}
?>
Your assignments are backwards. I think you meant to:
$res1 = $row_user['first_name'];
$res2 = $row_user['last_name'];
Don't you mean:
$res1 = $row_user['first_name'];
$res2 = $row_user['last_name'];
You could also update the SELECT to have a WHERE clause that checks $_SESSION['username'].
You could also just do an INSERT/SELECT:
INSERT INTO oko (user, product)
SELECT
first_name, last_name
FROM
users
WHERE
username = '$_SESSION["username"]'
Your code is vulnerable to injection. You should use properly parameterized queries with PDO/mysqli

Categories