Having this query
$query = 'INSERT INTO users(name) VALUES (:name)';
$stmt = $pdo->prepare($query);
$stmt->execute(['name' => $_POST['name']]);
INSERTing into The Table: Users where column name is UNIQUE.
Instead of doing two queries
$check = 'SELECT EXISTS (SELECT name FROM users WHERE name = :name);'
$stmt = $pdo->prepare($check);
$stmt->execute(['name' => $_POST['name']]);
if ($stmt->fetchColumn() == 0) {
$query = 'INSERT INTO users(name) VALUES (:name)';
$stmt = $pdo->prepare($query);
$stmt->execute(['name' => $_POST['name']]);
}
Is it possible using PDO to FETCH the Duplicated row id if $query failed to INSERT? Something like
$query = 'INSERT INTO users(name) VALUES (:name)';
$stmt = $pdo->prepare($query);
$stmt->execute(['name' => $_POST['name']]);
if ($stmt->duplicated() > 0) {
echo "Name already exists by the id number ".$stmt->duplicated()."";
}
In case it is impossible to return the Duplicated ID, Can I just tell if there is a Duplication without returning anything?
Example:
users
[id - name]
[1 - MARX]
[2 - MATH]
$query = 'INSERT INTO users(name) VALUES ('MARX')';
$stmt = $pdo->prepare($query);
$stmt->execute();
if ($stmt->duplicated() > 0) {
echo "Name already exists by the id number ".$stmt->duplicated()."";
} else {
echo "Name was Inserted";
}
Result: Name already exists by the id number 1
Create a unique index on users(name).
Then, catch the error when the unique index is violated.
This has nothing to do with on duplicate key update.
A unique index on name is highly, highly recommended for this purpose. Your code is not thread-safe. Two threads could have the same name. Each could check that it doesn't exist. And each could try to insert it. All that effort -- and you'll get duplicates anyway.
Let the database do what it is supposed to be doing -- protecting your data. Define the unique index/constraint.
Related
How can I fix this transaction so that the pdo query makes a new table in step #4?
The first three steps work, but I can't seem to get #4 to work.
STEPS
Finds a user with a chattingstatus of 0 in the database
Add a user into the database (with predetermined variables)
change the chattingstatus from 0 to 1 for both the user with a 0 status and the inserted user
4. Create a table with the id of both users as the title like this 2+13 (2 being the id and 13 being the id)
$userid = "123456";
$firstname = "Dae";
$oglang = "engs";
$status = 0;
$pdo->beginTransaction();
try{
// Find a user with a status of 0
$sql = "SELECT id FROM users WHERE chattingstatus = :status";
$stmt = $pdo->prepare($sql);
$stmt->execute(array(':status' => $status)
);
$freeuser = $stmt->fetchColumn();
//put the original user into the database with userid firstname and language
$sql = "INSERT INTO users (userid, firstname, oglang, chattingstatus) VALUES (:userid, :firstname, :oglang, :chattingstatus)";
$stmt = $pdo->prepare($sql);
$stmt->execute(array(':userid' => $userid, ':firstname' => $firstname, ':oglang' => $oglang, ':chattingstatus' => 0)
);
$ogID = $pdo->lastInsertId();
// change the chattingstatus of 0 of the free user to 1
$sql = "UPDATE users SET chattingstatus = 1 WHERE id = :freeuser";
$stmt = $pdo->prepare($sql);
$stmt->execute(array(':freeuser' => $freeuser)
);
//query 3 CHANGE STATUS OF ORIGINAL USER from 0 to 1
$sql = "UPDATE users SET chattingstatus = 1 WHERE userid = :oguser";
$stmt = $pdo->prepare($sql);
$stmt->execute(array(':oguser' => $userid)
);
//query 4: Make a table between the 2 users with their IDs
$table = $freeuser."+".$ogID;
$sql ="CREATE table $table(
ID INT( 11 ) AUTO_INCREMENT PRIMARY KEY,
Messages VARCHAR( 50 ) NOT NULL);";
$stmt = $pdo->exec($sql);
print("Created $table Table.\n");
$pdo->commit();
}
//Our catch block
catch(Exception $e){
//Print out the error message.
echo $e->getMessage();
//Rollback the transaction.
$pdo->rollBack();
}
Thanks in advance.
Since your table name includes the special character +, you need to put it in backticks to quote it.
$sql ="CREATE table `$table` (
ID INT( 11 ) AUTO_INCREMENT PRIMARY KEY,
Messages VARCHAR( 50 ) NOT NULL);";
You'll need to remember to put backticks around the table name whenever you use it in other queries. If you insist on having per-user tables like this, you might want to use a different character to connect them, like underscore.
Creating table in transation doesn't work in MySQL:
Some databases, including MySQL, automatically issue an implicit COMMIT when a database definition language (DDL) statement such as DROP TABLE or CREATE TABLE is issued within a transaction. The implicit COMMIT will prevent you from rolling back any other changes within the transaction boundary.
Source: https://www.php.net/manual/en/pdo.begintransaction.php
I would like to get the error message if a duplicate entry error happened with PDO.
this is the code I use where a duplicate entry is possible because id is a unique key:
$movetotable = $conn->prepare("INSERT INTO `$table` SELECT * FROM `$trashtable` WHERE id = :id");
$movetotable->bindParam(':id', $id, PDO::PARAM_STR);
$movetotable->execute();
I hope it is possible with PHP PDO, I know this: PDO::errorCode() but I simply don't know how to use it in an if statement.
Thanks in advance
$stmt = $conn->prepare("INSERT IGNORE INTO `$table` SELECT * FROM `$trashtable` WHERE id = ?");
$stmt->execute([$id]);
$id = $conn->lastInsertId();
if (!$id) {
echo "a dupe!";
}
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?
I'm trying to generate a unique username that is not already in my database and then add it as a primary key into my InnoDB database table plus some other field entries.
I get the error code:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'ft6888' for key 'PRIMARY'
Checking the database table manually I can see that it does not already contain the value I'm passing and by echoing the username values I'm binding I can see each is only bound once. The field is not set to auto_increment as in some of these questions but it used as a foreign key in some other tables (but the values I'm binding don't exist in those either).
If I echo out the variables I'm binding just before I bind them I get two sets of correct data. When I insert this same data (copy and pasted) into the table using phpmyadmin it works fine no errors. I can only assume my code itself is somehow trying to insert twice?
$query = "INSERT INTO user_login (username, usertype, hashedpassword) VALUES";
$qPart = array_fill(0, count($excelData), "(?, ?, ?)");
$query .= implode(",",$qPart);
$sth = $dbh->prepare($query);
$i = 1;
$sql = "SELECT username FROM user_login WHERE username = :username";
$sthUser = $dbh->prepare($sql);
Foreach($excelData As $Row){
Do{
//Create unique userID
$finitial = substr(addslashes(str_replace(" ","",$Row['0']['2'])),0,1);
$sinitial = substr(addslashes(str_replace(" ","",$Row['0']['3'])),0,1);
$username = strtolower($finitial).strtolower($sinitial).rand(999,9999);
try {
$sthUser->bindParam(':username', $username);
$sthUser->execute();
$Row = $sthUser->fetch(PDO::FETCH_ASSOC);
}catch (PDOException $e) {
print $e->getMessage();
}
}while(!empty($Row));
$hashedPassword = create_hash($Row['0']['1']);
$usertype = 'Student';
$sth->bindParam($i++, $username);
$sth->bindParam($i++, $usertype);
$sth->bindParam($i++, $hashedPassword);
}
try {
$sth->execute();
}catch (PDOException $e) {
print $e->getMessage();
}
Found the answer here - It seems that bindParam inside the loop binds by reference and is only evaluated at execute statement so it always contains the last bound value for each field.
Changing it to bindValue worked.
Hi guys am fighting with a syntax error of my sql, saying exactly:
"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax"
Even though the code is working and doing what I wanted I still get the syntax error info!
and here is the code:
$person_id =mysql_query("SELECT person_id FROM person WHERE firstname='$array[0]' AND lastname='$array[1]' AND city='$array[2]' ")
or die(mysql_error());
if (mysql_num_rows($person_id) )
{
print 'user is already in table';
}
else
{
mysql_query ("INSERT INTO person VALUES (NULL, '$array[0]' ,'$array[1]' , '$array[2]' ")
or die(mysql_error());
$person_id = mysql_insert_id();
}
$address_id =mysql_query("SELECT address_id FROM address WHERE street='$array[3]' AND city='$array[4]' AND region='$array[5]'")
or die(mysql_error());
if (mysql_num_rows($address_id) )
{
print ' already in table';
}
else
{
mysql_query ("INSERT INTO address VALUES (NULL, '$array[3]', '$array[4]', '$array[5]'")
or die(mysql_error());
$address_id = mysql_insert_id();
}
mysql_query ("INSERT INTO person_address VALUES($person_id, $address_id)")
or die(mysql_error());
Thanks for any suggestions
It's probably because you haven't escaped your values...
Try:
$query = "SELECT age FROM person WHERE name='".mysql_real_escape_string($array[0])."' AND lastname='".mysql_real_escape_string($array[1])."' AND city='".mysql_real_escape_string($array[2])."'";
And read up on SQL injection.
EDIT
I think your problem is that you are trying to pass mysql result resources directly into a string, without fetching the actual values first.
Try this:
// Create an array of escaped values to use with DB queries
$escapedArray = array();
foreach ($array as $k => $v) $escapedArray[$k] = mysql_real_escape_string($v);
// See if the person already exists in the database, INSERT if not
$query = "SELECT person_id FROM person WHERE firstname='$escapedArray[0]' AND lastname='$escapedArray[1]' AND city='$escapedArray[2]' LIMIT 1";
$person = mysql_query($query) or die(mysql_error());
if ( mysql_num_rows($person) ) {
print 'user is already in table';
$person = mysql_fetch_assoc($person);
$person_id = $person['person_id'];
} else {
$query = "INSERT INTO person VALUES (NULL, '$escapedArray[0]', '$escapedArray[1]', '$escapedArray[2]')";
mysql_query($query) or die(mysql_error());
$person_id = mysql_insert_id();
}
// See if the address already exists in the database, INSERT if not
$query = "SELECT address_id FROM address WHERE street='$escapedArray[3]' AND city='$escapedArray[4]' AND region='$escapedArray[5]'";
$address = mysql_query($query) or die(mysql_error());
if (mysql_num_rows($address) ) {
print 'address already in table';
$address = mysql_fetch_assoc($address);
$address_id = $person['address_id'];
} else {
$query = "INSERT INTO address VALUES (NULL, '$escapedArray[3]', '$escapedArray[4]', '$escapedArray[5]')";
mysql_query ($query) or die(mysql_error());
$address_id = mysql_insert_id();
}
// INSERT a record linking person and address
mysql_query ("INSERT INTO person_address VALUES($person_id, $address_id)") or die(mysql_error());
ANOTHER EDIT
Firstly, I have modified the code above - added a couple of comments, corrected a couple of small errors where the wrong variable was referenced and re-spaced it to make it more readable.
Secondly...
You are getting that additional error because you are trying to insert a new row into your person_address table, which doesn't seem to have a sensibly configured primary key. The easy work around to the problem you currently have is to run a SELECT against this table to see if you have already got a record for that user, then if you have you can do an UPDATE instead of the INSERT to alter the existing record.
However, if I understand what your doing here correctly, you don't actually need the person_address table, you just need to add another integer column to the person table to hold the ID of the corresponding row in the address table. Doing this would make many of your future queries potentially much simpler and more efficient as it will be much easier to SELECT data from both tables at once (you could do it with your current structure but it would be much more confusing and inefficient).
The following code example could be used if you add another integer column on the end of your person, and call that column address_id. You will notice it's very similar to the above, but there are two key differences:
We do the address stuff first, since we will keep track of the relation in the person record
We do an UPDATE only if we find a person, otherwise we just INSERT a new person as before
// Create an array of escaped values to use with DB queries
$escapedArray = array();
foreach ($array as $k => $v) $escapedArray[$k] = mysql_real_escape_string($v);
// See if the address already exists in the database, INSERT if not
$query = "SELECT address_id FROM address WHERE street='$escapedArray[3]' AND city='$escapedArray[4]' AND region='$escapedArray[5]'";
$address = mysql_query($query) or die(mysql_error());
if (mysql_num_rows($address) ) {
print 'address already in table';
$address = mysql_fetch_assoc($address);
$address_id = $person['address_id'];
} else {
$query = "INSERT INTO address VALUES (NULL, '$escapedArray[3]', '$escapedArray[4]', '$escapedArray[5]')";
mysql_query ($query) or die(mysql_error());
$address_id = mysql_insert_id();
}
// See if the person already exists in the database, UPDATE if he does, INSERT if not
$query = "SELECT person_id FROM person WHERE firstname='$escapedArray[0]' AND lastname='$escapedArray[1]' AND city='$escapedArray[2]' LIMIT 1";
$person = mysql_query($query) or die(mysql_error());
if ( mysql_num_rows($person) ) {
print 'user is already in table';
$person = mysql_fetch_assoc($person);
$person_id = $person['person_id'];
$query = "UPDATE person SET address_id = '$address_id' WHERE person_id = '$person_id'";
mysql_query($query) or die(mysql_error());
} else {
$query = "INSERT INTO person VALUES (NULL, '$escapedArray[0]', '$escapedArray[1]', '$escapedArray[2]', '$address_id')";
mysql_query($query) or die(mysql_error());
}
If we structure the database in this way, it allows us to do this:
SELECT person.*, address.* FROM person, address WHERE person.address_id = address.address_id AND [some other set of conditions]
Which will return the person record, and the address record, in the same result set, all nicely matched up for you by the database.
YET ANOTHER EDIT
You need to add an auto-increment primary key to the person_address table, and perform a SELECT on it to make sure you are not adding duplicate records.
You should replace the final INSERT statement with the following code segment. This code assumes that you have a primary key in the person_address table called relation_id. It also assumes that the id field names in this table are named in the same way as they are in the other two tables.
// See if a relation record already exists for this user
// If it does, UPDATE it if the address is different
// If it doesn't, INSERT an new relation record
$query = "SELECT relation_id, address_id FROM person_address WHERE person_id = '$person_id' LIMIT 1";
$relation = mysql_query($query);
if ( mysql_num_rows($relation) ) {
$relation = mysql_fetch_assoc($relation);
if ($relation['address_id'] == $address_id) {
print 'The record is identical to an existing record and was not changed';
} else {
$relation_id = $relation['relation_id'];
$query = "UPDATE person_address SET address_id = '$address_id' WHERE relation_id = '$relation_id'";
mysql_query($query) or die(mysql_error());
}
} else {
$query = "INSERT INTO person_address VALUES(NULL, '$person_id', '$address_id')";
mysql_query($query) or die(mysql_error());
}
EVEN MORE EDITING
Try this to replace the code from above:
// See if a relation record already exists for this user
// If it doesn't, INSERT an new relation record
$query = "SELECT person_id FROM person_address WHERE person_id = '$person_id' AND address_id = '$address_id' LIMIT 1";
$relation = mysql_query($query);
if ( !mysql_num_rows($relation) ) {
$query = "INSERT INTO person_address VALUES('$person_id', '$address_id')";
mysql_query($query) or die(mysql_error());
}
You cannot use array values like that inside of quotes - instead you could, for example, separate the values from the query using dots.
$query = "SELECT age FROM person WHERE name='".$array[0]."' AND lastname='".$array[1]."' AND city='".$array[2]."'";
the second and fourth query do not have an ending ')' at the end of the values