Check if row exists in the database before inserting - php

$DBH = new PDO($dsn, $username, $password, $opt);
$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$DBH->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$STH = $DBH->prepare("INSERT INTO requests (id,imdbid,msg) VALUES ('',:imdbid,:msg)");
$STH->bindParam(':imdbid', $_POST['imdbid']);
$STH->bindParam(':msg', $_POST['msg']);
$STH->execute();
echo "<p>Successfully Requested ".$_POST['imdbid']."! Thanks!</p>";
Is there either some SQL Query that will check and insert or what?
I need it to check if whatever the user typed is already in the db so if the user typed in a imdbid that is already there then it wont continue inserting anything. How would I do this? I know I can do a fetch_all and make a foreach for it but doesnt that only work after you execute?

It's better to set a constraint on your columns to prevent duplicate data instead of checking and inserting.
Just set a UNIQUE constraint on imdbid:
ALTER TABLE `requests` ADD UNIQUE `imdbid_unique`(`imdbid`);
The reason for doing this is so that you don't run into a race condition.
There's a small window between finishing the check, and actually inserting the data, and in that small window, data could be inserted that will conflict with the to-be-inserted data.
Solution? Use constraints and check $DBH->error() for insertion errors. If there are any errors, you know that there's a duplicate and you can notify your user then.
I noticed that you are using this, $DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);. In this case, you don't need to check ->error() because PDO will throw an exception. Just wrap your execute with try and catch like this:
$duplicate = false;
try {
$STH->execute();
} catch (Exception $e) {
echo "<p>Failed to Request ".$_POST['imdbid']."!</p>";
$duplicate = true;
}
if (!$duplicate)
echo "<p>Successfully Requested ".$_POST['imdbid']."! Thanks!</p>";

Simply run a query prior to inserting.
If found die the script:
$DBH = new PDO($dsn, $username, $password, $opt);
$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$DBH->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$sql = 'SELECT COUNT(*) from requests WHERE imdbid = :imdbid';
$stmt = $DBH->prepare($sql);
$stmt->execute(array(':imdbid' => $_POST['imdbid']));
if($stmt->fetchColumn()){ die('Already exist');}
$STH = $DBH->prepare("INSERT INTO requests (id,imdbid,msg) VALUES ('',:imdbid,:msg)");
$STH->bindParam(':imdbid', $_POST['imdbid']);
$STH->bindParam(':msg', $_POST['msg']);
$STH->execute();
echo "<p>Successfully Requested ".$_POST['imdbid']."! Thanks!</p>";
or alternatively make the msg field unique.
Using a stored Procedure:
DELIMITER //
CREATE PROCEDURE insert_request_msg(IN `p_imbd`, IN `p_msg`)
IF NOT EXISTS (SELECT COUNT(*) from requests WHERE imdbid = p_imbd)
BEGIN
INSERT INTO requests (id,imdbid,msg) VALUES ('',p_imbd,p_msg)
END
END IF; //
DELIMITER ;
You call it in one query like this:
$STH = $DBH->prepare('
call insert_request_msg(:imdbid,:msg)
');
$STH->bindParam(':imdbid', $_POST['imdbid']);
$STH->bindParam(':msg', $_POST['msg']);

Try this
$DBH = new PDO($dsn, $username, $password, $opt);
$DBH->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$DBH->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$STH = $DBH->prepare("INSERT INTO requests (id,imdbid,msg) VALUES ('',:imdbid,:msg) WHERE NOT EXISTS(SELECT imdbid FROM requests WHERE imdbid =:imdbid)");
$STH->bindParam(':imdbid', $_POST['imdbid']);
$STH->bindParam(':msg', $_POST['msg']);
$STH->execute();
echo "<p>Successfully Requested ".$_POST['imdbid']."! Thanks!</p>";
Source

Related

How to get the value of expression from LAST_INSERT_ID(`my_column`+1)?

DB Type: MariaDB
Table Engine: InnoDB
I have a table where inside it has a column with a value which is being incremented (not auto, no inserting happens in this table)
When I run the following SQL query in phpMyAdmin it works just fine as it should:
UPDATE `my_table`
SET `my_column` = LAST_INSERT_ID(`my_column` + 1)
WHERE `my_column2` = 'abc';
SELECT LAST_INSERT_ID();
The above returns me the last value for the my_column table when the query happened. This query was taken directly from the mysql docs on locking: https://dev.mysql.com/doc/refman/8.0/en/innodb-locking-reads.html (to the bottom) and this seems to be the recommended way of working with counters when you don't want it to be affected by other connections.
My PDO:
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "UPDATE `my_table`
SET `my_column` = LAST_INSERT_ID(`my_column` + 1)
WHERE `my_column2` = 'abc';
SELECT LAST_INSERT_ID();";
// Prepare statement
$stmt = $conn->prepare($sql);
// execute the query
$stmt->execute();
$result = $stmt->fetchColumn(); // causes general error
$result = $stmt->fetch(PDO::FETCH_ASSOC);// causes general error
// echo a message to say the UPDATE succeeded
echo $stmt->rowCount() . " records UPDATED successfully";
} catch(PDOException $e) {
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
Exact error SQLSTATE[HY000]: General error, If I remove the lines where I try to get the result, it updates the column, but I still do not have a return result... how do I perform that update query and get the select result all in one go like I do when I run it in phpMyAdmin? This all needs to happen in one go as specified by the MySQL docs so I don't have issues where two connections might get the same counter.
There is no need to perform SELECT LAST_INSERT_ID();. PDO will save that value automatically for you and you can get it out of PDO.
Simply do this:
$conn = new PDO("mysql:host=$servername;dbname=$dbname;charset=utf8mb4", $username, $password, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
$sql = "UPDATE `my_table`
SET `my_column` = LAST_INSERT_ID(`my_column` + 1)
WHERE `my_column2` = 'abc'";
// Prepare statement
$stmt = $conn->prepare($sql);
// execute the query
$stmt->execute();
$newID = $conn->lastInsertId();
lastInsertId() will give you the value of the argument evaluated by LAST_INSERT_ID().

How can I prevent SQL from being executed until POST values are not empty?

I have the following PHP script that executes an sql update query, how can I prevent it from being executed until the two POST values are not empty?
try {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$delivery_time = addslashes($_POST['delivery_time']);
$customer = addslashes($_POST['customer']);
$sql = "UPDATE Equipment SET time = '$time', customer = '$customer' WHERE status ='Broken' ";
// Prepare statement
$stmt = $conn->prepare($sql);
// execute the query
$stmt->execute();
// echo a message to say the UPDATE succeeded
echo $stmt->rowCount() . " records UPDATED successfully";
}
catch(PDOException $e)
{
echo $sql . "<br>" . $e->getMessage();
}
$conn = null;
Warning: You are wide open to SQL Injections and should really use parameterized prepared statements instead of manually building your queries. They are provided by PDO or by MySQLi. Never trust any kind of input, especially that which comes from the client side. Even when your queries are executed only by trusted users, you are still in risk of corrupting your data.
To avoid sending the query until $_POST variables are supplied check for their existence with if statement and isset.
if (isset($_POST['delivery_time'], $_POST['customer'])) {
$conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
// set the PDO error mode to exception
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); // switch off emulated prepares, but you should add charset=utf8mb4 in the contructor above too
$sql = "UPDATE Equipment SET `time` = ?, `customer` = ? WHERE `status` ='Broken' ";
// Prepare statement
$stmt = $conn->prepare($sql);
// execute the query
$stmt->execute([
$_POST['delivery_time'],
$_POST['customer']
]);
// echo a message to say the UPDATE succeeded
echo $stmt->rowCount() . " records UPDATED successfully";
}

run insert query once only when the database is created php pdo

from config.php
<?php
global $dbh;
$dbname = 'memberdb';
try {
$dbh = new PDO("mysql:host=localhost", "root", "");
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbname = "`".str_replace("`","``",$dbname)."`";
$dbh->query("CREATE DATABASE IF NOT EXISTS $dbname");
$dbh->query("use $dbname");
$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$sql ="CREATE TABLE IF NOT EXISTS $member (
mem_id int(40) NOT NULL AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(40) NOT NULL,
password VARCHAR(40) NOT NULL);" ;
$dbh->exec($sql);
$stmt = $dbh->prepare("INSERT INTO member (username, password) VALUES (?,?)")or die($db->errorInfo());
$stmt->bindValue(1,"admin1",PDO::PARAM_STR);
$stmt->bindValue(2,"password1",PDO::PARAM_STR);
$stmt->execute();
$stmt->bindValue(1,"admin2",PDO::PARAM_STR);
$stmt->bindValue(2,"password2",PDO::PARAM_STR);
$stmt->execute();
$stmt->bindValue(1,"admin3",PDO::PARAM_STR);
$stmt->bindValue(2,"password3",PDO::PARAM_STR);
$stmt->execute();
} catch(PDOException $e) {
}
?>
This is my function of new user when the user is registered using a registered button.
How to make this kind of function run only one, when the database is created and only.
I will need to put defined value for each input but i didnt not change it yet
UPDATE
The code i used is above my prob is still the same when i reload the index.php the query runs again making double entry..what i want is that when the database is create the query will run and when loaded the database is not created again so i want the query to not run again to avoid double entry.
$stmt = $dbh->prepare("SELECT * FROM member") ;
$stmt->execute();
$count = $stmt -> rowCount();
echo $count;
if( $count == 00 ){
$stmt = $dbh->prepare("INSERT INTO member (username, password) VALUES (?,?)")or die($db->errorInfo());
$stmt->bindValue(1,"admin1",PDO::PARAM_STR);
$stmt->bindValue(2,"password1",PDO::PARAM_STR);
$stmt->execute();
$stmt->bindValue(1,"admin2",PDO::PARAM_STR);
$stmt->bindValue(2,"password2",PDO::PARAM_STR);
$stmt->execute();
$stmt->bindValue(1,"admin3",PDO::PARAM_STR);
$stmt->bindValue(2,"password3",PDO::PARAM_STR);
$stmt->execute();
}
i only have one more question why is it sometimess the echo for count is 3 and sometimes its 33 its like the query is run twice please clear this out...this worked but maybe just maybe there are incorrect logic here please feel free to edit to make it perfect.

First run with PDO getting a Call to a member function bindParam() on a non-object error

This is my first run with PDO, not sure how much better it is than using mysqli but its part of a project I have to create.
Here is the code that is causing the message, all I am trying to do is update pieces of data within my db table.
<?php
//PHP Data Objects
try{
//Connect
$dbh = new PDO('mysql:host=localhost; dbname = company; charset=utf-8','root', 'bachi619');
} catch(PDOException $e){
echo $e->getMessage();
}
$id = 4;
$name = "logan";
$department = "Design";
$sth = $dbh->query("UPDATE employees SET department=:department,last_name=:lastname WHERE id=:id");
//bind
$sth->bindParam(':id',$id);
$sth->bindParam(':lastname',$name);
$sth->bindParam(':department',$department);
$sth->execute();
?>
you have to use
$dbh -> prepare("UPDATE employees SET department=:department,last_name=:lastname WHERE id=:id");
Use prepare for PDO, check this http://in3.php.net/manual/en/pdostatement.bindparam.php
$sth = $dbh->prepare('UPDATE employees SET department=:department,last_name=:lastname WHERE id=:id' );
The dsn should be non spaced
$dbh = new PDO('mysql:host=localhost;dbname=company','root', 'bachi619');
You need to prepare the SQL statement like this
$sth = $dbh->prepare( 'UPDATE employees SET department=:department,last_name=:lastname WHERE id=:id' );
Then bind the parameters
$sth->bindParam(':id',$id);
$sth->bindParam(':lastname',$name);
$sth->bindParam(':department',$department);
and finally execute the query
$sth->execute();

PHP PDO UPDATE not updating data

I am having a tough time updating data using PDO. These are the two options that i've tried. None has actually updated the database, however.
Query 1:
$dateLastLoggedIn = date("Y-m-d H:i:s");
$username = mysql_real_escape_string($_POST['User']);
$sth = $dbh->prepare("UPDATE users SET dateLastLoggedIn = ? WHERE username = ?");
$sth->execute(array($dateLastLoggedIn,$username));
print_r($sth->queryString); just prints out UPDATE users SET dateLastLoggedIn = ? WHERE username = ?
Query 2:
$dateLastLoggedIn = date("Y-m-d H:i:s");
$username = mysql_real_escape_string($_POST['User']);
$sql = "UPDATE users SET dateLastLoggedIn = '".$dateLastLoggedIn."' WHERE username = '".$username."'";
$sth = $dbh->prepare($sql);
$sth->execute();
print_r($sth->queryString); prints out UPDATE users SET dateLastLoggedIn = '2012-08-03 13:36:32' WHERE username = 'testuser'
The second option generates the correct query but it doesn't actually update the data. I can manually run the generated script and it works, but not through the execute(). Anything i'm doing wrong? I'm still new to PDO, so it may be a simple fix.
SOLVED: see my last comment under the accepted answer.
getting connection :
function getConnection(){
$dbhost="127.0.0.1";
$dbuser="application";
$dbpass="password";
$dbname="abc";
$dbh = new PDO("mysql:host=$dbhost;dbname=$dbname", $dbuser, $dbpass);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
try {
$dbh = getConnection();
$sth = $dbh->prepare("UPDATE users SET dateLastLoggedIn = :dateLastLoggedIn WHERE username = :username ");
$sth->bindParam('dateLastLoggedIn',$dateLastLoggedIn);
$sth->bindParam('username',$username );
$sth->execute();
$dbh = null; // after done
} catch(PDOException $e) {// simple exception handling
error_log($e->getMessage(), 3, '/var/tmp/php.log');
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
Also, try to wrap this in try catch to see the error
print_r($sth->queryString); just prints out UPDATE users SET dateLastLoggedIn = ? WHERE username = ?
That's what will happen with PDO prepared queries.
If you're using PDO, mysql_real_escape_string isn't going to work. At all. It requires an existing connection via mysql_connect. Your username value is effectively blank.

Categories