Custom PHP script PDO is throwing exception 23000,1062 duplicate entry - php

I am working on a PHP script where I am using PDO to insert data in mySQL. I am getting an error "23000",1062,"Duplicate entry 'email#email.com-username' for key 'email' but its inserting the data in database.
So here is my PHP codes:
if(isset($_POST['email'])){
$this->db = new connect();
$this->db = $this->db->dbConnect();
$this->encryption = new Encryption();
isset($_POST['timezone']) AND $_POST['timezone'] != 'null' ? date_default_timezone_set($_POST['timezone']): date_default_timezone_set('America/Chicago');
$this->email = $_POST['email'];
$this->username = $_POST['username'];
$this->password = $this->encryption->encode($_POST['password']);
$this->dTime = date("Y-m-d H:i:s");;
$this->sessionKey = $_POST['key'];
$this->country = $_POST['country'];
$this->region = $_POST['uregion'];
$this->browser = $_POST['browser'];
$this->ip = $_POST['accessFrom'];
$regMessage = array('error'=>false);
try{
$query = "INSERT INTO `users` (
id, email, uname, password, regtime, sessionkey, country, region, browser, ip
) VALUES (
(SELECT MAX(id) + 1 FROM `users` AS `maxId`), :email, :uname, :password, :regtime, :sessionkey, :country, :region, :browser, :ip
)";
$register = $this->db->prepare($query, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
if($this->sessionKey === $_SESSION['token']){
$register->bindParam(':uname', $this->username);
$register->bindParam(':email', $this->email);
$register->bindParam(':password', $this->password);
$register->bindParam(':regtime', $this->dTime);
$register->bindParam(':sessionkey', $this->sessionKey);
$register->bindParam(':country', $this->country);
$register->bindParam(':region', $this->region);
$register->bindParam(':browser', $this->browser);
$register->bindParam(':ip', $this->ip);
$register->execute();
if($register->rowCount() > 0){
$regMessage = array('error'=>false);
}else{
$regMessage = array('error'=>true);
}
}else{
throw new PDOException ('Error');
}
}
catch(PDOException $e){
//this is where I am getting error so I am echoing pdo exception error
$regMessage = array('error'=>$e);
}
header('Content-Type: application/json');
echo json_encode($regMessage);
}else{
header('Location: /');
}
At the error, it is showing me duplicate entry of emailid + username for key email which looks like email#email.com-username
But in data base, I am getting email id only in email column and username only in username column.
So can any one tell me whats wrong in my codes?
My users table structure is
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(250) CHARACTER SET utf8 NOT NULL,
`uname` varchar(20) CHARACTER SET utf8 NOT NULL,
`password` varchar(100) CHARACTER SET utf8 NOT NULL,
`regtime` datetime NOT NULL,
`sessionkey` varchar(10) CHARACTER SET utf8 NOT NULL,
`country` varchar(25) CHARACTER SET utf8 NOT NULL,
`region` varchar(25) CHARACTER SET utf8 NOT NULL,
`browser` varchar(25) CHARACTER SET utf8 NOT NULL,
`ip` varchar(16) CHARACTER SET utf8 NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`,`uname`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
So can anyone tell me where and what is wrong?
Thank you for helping me.

The phrasing in the error message: 'email#email.com-username' for key 'email' directly corresponds to your unique key UNIQUE KEY 'email' ('email','uname'). With that line, you are creating a compound key, which you can think of as an invisible column in the index that is comprised of email-uname. There will not be a column added to your table with this format, and you are seeing the expected behavior that email and uname are treated separately in the table and together for the key.
If you want to test over and over again with the same email and username combo, you'll need to delete that row every time. Without doing this, the error you are seeing is exactly what I would expect to see if you are POST-ing the same data over and over again.
I want to also mention that you have (appropriately) specified that your id column is AUTO_INCREMENT, but then you are calculating the value manually. I would like to discourage you from doing this, and instead use NULL as the insert value. MySQL will use the correct key value in this column, and you will avoid the potential for key collision if you ever had two of these things executing at the same exact moment.

CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(250) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`uname` varchar(20) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
`password` varchar(100) CHARACTER SET utf8 NOT NULL,
`regtime` datetime NOT NULL,
`sessionkey` varchar(10) CHARACTER SET utf8 NOT NULL,
`country` varchar(25) CHARACTER SET utf8 NOT NULL,
`region` varchar(25) CHARACTER SET utf8 NOT NULL,
`browser` varchar(25) CHARACTER SET utf8 NOT NULL,
`ip` varchar(16) CHARACTER SET utf8 NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
this is the solution.

Related

Why won't this binded MySQL query run?

My code for updating user info:
if($update_stmt = $link_reg->prepare("UPDATE email_pass SET password=?, salt=?, customer_id=?, subscription_id=?, subscription_datetime=? WHERE email=?")){
$update_stmt->bind_param('ssssss', $new_password, $random_salt, $new_customer_id, $new_sub_id, $new_sub_datetime, $new_email);
if($update_stmt->errno){
echo($update_stmt->error);
}
// Execute prepared query
if($update_stmt->execute()){
// MORE CODE HERE
} else {
echo("ERROR?");
}
}
When I run it, I get no feedback. My data table doesn't update, but there's no echo message either.
Is there an error somewhere? Why won't the code execute properly?
EDIT
Here's some sample UPDATE data and the table's columns
$new_password = '532a69d8124604e33e9f45a8c9xbea92c342cbd5a3f847f770816dbd97975b2769f52a25806ead6100c1ac1a9a1a4de6b1641279a26854fba7c162caffca8e9f';
$random_salt = 'b6a1062d2c07c3aa900cbe9777d4670192f77241ad0b5ceb5f7968e3107f6d719b450d2ac37165e7827f53c2005797c985deddb9bec71724948bcd833ea72e87';
$new_customer_id = '19582601';
$new_sub_id = 'crj94x';
$new_sub_datetime = '2014-02-25 19:41:56';
$new_email = 'myemail#someemailplace.com';
The CREATE TABLE syntax:
CREATE TABLE `email_pass` (
`row_id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`password` char(128) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`salt` char(128) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`customer_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`subscription_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`subscription_datetime` datetime NOT NULL,
PRIMARY KEY (`row_id`)
) ENGINE=MyISAM AUTO_INCREMENT=239 DEFAULT CHARSET=latin1
I have tried your code and it works. You have a WHERE email=? in your code, which is populated with $new_email. May it be that you are trying to find the record to update by searching for the new email to be set rather than by the current email address (or where row_id = ...)?
I.e. you do not get any errors and nothing is updated because you do not get a match on your email = <new email> where clause.
Welp, turns out I forgot to give the MySQL user permission to UPDATE. It could only SELECT and INSERT.

mysqli delete query not working

I'm writing a PHP script to delete a row from a MySQL database by id.
The value of the id is passed as a query string and stored in a variable.
The query runs normally, with no errors, but no rows are affected.
Here is my code, can somebody please point out what's wrong with it?
Thanks.
PHP Code:
$delete = $_GET['killthisguy'];
$sqlDel = "DELETE FROM `pba_files` WHERE id=".$delete;
$res = mysqli_query($cxn, $sqlDel);
$affRows = mysqli_affected_rows($cxn);
Database Schema:
CREATE TABLE IF NOT EXISTS `pba_files` (
`id` int(3) NOT NULL auto_increment,
`chap_id` int(2) default NULL,
`cat_id` varchar(2) character set utf8 collate utf8_unicode_ci default NULL,
`is_video` tinyint(1) default NULL,
`file_location` varchar(220) character set utf8 collate utf8_unicode_ci default NULL,
`clean_filename` varchar(116) character set utf8 collate utf8_unicode_ci default NULL,
`description` varchar(1026) character set utf8 collate utf8_unicode_ci default NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=611 ;
You could try removing the ' from the "id" because it is not a string, it is an int (from the database point of view)
$delete = $_GET['killthisguy'];
$sqlDel = "DELETE FROM `pba_files` WHERE id=".$delete;
$res = mysqli_query($cxn, $sqlDel);
$affRows = mysqli_affected_rows($cxn);
Also are you sure that the "id" exists in the table?
The issue was just a careless mistake I made when setting up my access rights. DELETE was not allowed for my user on the database.
Thanks for all your help guys.

MySQL delete troubleshooting

I restarted the MySQL service and I attempted to use my PHP programs delete function to delete an existing row but I'm finding although the delete queries were counted the row was not deleted. I tried applying on delete cascade to the foreign key of the child table but that did not seem to have an effect. I'm wondering why the delete would be doing nothing.
CREATE TABLE `customers` (
`idcustomers` int(11) NOT NULL AUTO_INCREMENT,
`firstname` varchar(45) DEFAULT NULL,
`lastname` varchar(45) DEFAULT NULL,
`address1` varchar(45) DEFAULT NULL,
`address2` varchar(45) DEFAULT NULL,
`city` varchar(45) DEFAULT NULL,
`state` varchar(45) DEFAULT NULL,
`zip` varchar(45) DEFAULT NULL,
`phone` varchar(45) DEFAULT NULL,
`email` varchar(45) DEFAULT NULL,
`cell` varchar(45) DEFAULT NULL,
PRIMARY KEY (`idcustomers`),
UNIQUE KEY `idcustomers_UNIQUE` (`idcustomers`)
) ENGINE=InnoDB AUTO_INCREMENT=54 DEFAULT CHARSET=latin1
CREATE TABLE `events` (
`idevents` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(250) DEFAULT NULL,
`start` datetime DEFAULT NULL,
`end` datetime DEFAULT NULL,
`allday` varchar(50) DEFAULT NULL,
`url` varchar(1000) DEFAULT NULL,
`customerid` int(11) NOT NULL,
`memo` longtext,
`dispatchstatus` varchar(45) DEFAULT NULL,
PRIMARY KEY (`idevents`),
KEY `FK_events` (`customerid`),
CONSTRAINT `FK_events` FOREIGN KEY (`customerid`) REFERENCES `customers` (`idcustomers`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=latin1
Com_delete 2
The PHP looks like this:
<?php
session_start();
date_default_timezone_set("America/Los_Angeles");
if($_SESSION['loggedin'] != TRUE)
{
header("Location: index.php");
}
require_once('../php.securelogin/include.securelogin.php');
$mysqli = new mysqli($ad_host, $ad_user, $ad_password, "samedaycrm");
if ($mysqli->connect_errno) {
printf("Connect failed: %s\n", $mysqli->connect_error);
exit();
}
$customerid = $_SESSION['customer_id'];
$tSQL = "delete from events where customerid = \"$customerid\"";
$result = $mysqli->query($tSQL);
$tSQL = "delete from customers where idcustomers = \"$customerid\"";
$result = $mysqli->query($tSQL);
echo $mysqli->error;
?>
Assuming that the customerid and idcustomers columns are both numeric it should be fine. You should not need to quote the variables in those queries btw, then you wouldnt need to escape them. You may try:
$tSQL = "delete from events where customerid = $customerid";
but it should not be any different than what you used already. Of course if you are not sure of the type of the column you can use:
$tSQL = "delete from events where customerid = '".$customerid."'";
or you can get away with:
$tSQL = "delete from events where customerid = '$customerid'";
but I have always hated that for some reason.
if all of that fails troubleshoot by spitting out the $customerid (or even the whole $tSQL) variable and then trying the query manually in phpmyadmin or toad or whatever db client you use, and see what it tells you. If it just says 0 rows affected, then run it like a select instead. Tailor to fit.

PDO not inserting more than one row in table

I'm having trouble inserting image data into my database. I have a table called images. When dumped with PHPMyAdmin it looks like this:
CREATE TABLE IF NOT EXISTS `images` (
`id` int(11) NOT NULL,
`orig_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`hash` varchar(6) COLLATE utf8_unicode_ci NOT NULL,
`filename` varchar(12) COLLATE utf8_unicode_ci NOT NULL,
`uploaded` datetime NOT NULL,
`views` int(11) NOT NULL DEFAULT '0',
`album_id` int(11) DEFAULT NULL,
`user_id` int(11) DEFAULT NULL,
`server_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
KEY `server_id` (`server_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
This is the code I'm using to insert rows:
// Database connection
$db = new PDO('mysql:host=localhost;dbname=testdb', 'root', '');
// some code...
$st = $db->prepare('INSERT INTO `images` (orig_name, hash, filename, uploaded, server_id)
VALUES (?, ?, ?, ?, (SELECT `id` FROM `servers` WHERE `name` = ?))');
$st->execute(array($origName, $fileHash, $filename, date('c'), $server));
// more code...
// Database cleanup
$st = null;
$db = null;
The script returns no errors, and works flawlessly for the first row inserted. If the script runs again, it fails to insert any more rows in the images table. I see no reason why it'd behave like this, the data going into each field is unique each time (except for the server_id field).
Your id field isn't set to auto_increment.
The first record that you post will be added, with a NULL as id; the second record won't be added because there's already a record with NULL as the primary key, so it'll fail - you don't have any error checking in the code, so it won't be printing out the errors it's getting back.

Why mysql_insert_id returns 0 in my case?

This is my table:
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL auto_increment,
`name` varchar(20) NOT NULL default '',
`pass` varchar(32) NOT NULL default '',
`lang` varchar(2) default NULL,
`locale` varchar(2) default NULL,
`pic` varchar(255) default NULL,
`sex` char(1) default NULL,
`birthday` date default NULL,
`mail` varchar(64) default NULL,
`created` timestamp NOT NULL default CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `mail` (`mail`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=27 ;
And this is my query:
$query = "INSERT IGNORE INTO `users` (`name`, `mail`, `birthday`, `lang`, `locale`, `sex`, `pic`) VALUES ('".$name."', '".$email."', '".date_format($birthdaynew, 'Y-m-d H:i:s')."', '".substr($locale, 0, 2)."', '".substr($locale, -2, 2)."', '".$sex."', 'pic/".$uid.".jpg')";
$rows = mysql_query($query) or die("Failed: " . mysql_error());
$_SESSION['id'] = mysql_insert_id(); // I have tryed also mysql_insert_id($db_con) where $db_con is the link to db.
$_SESSION['name'] = $name;
$_SESSION['name'] contains correctly the name but $_SESSION['id'] contains 0.
Why ?
I'm going crazy!
Is there a particular reason why you are using INSERT IGNORE?
If you use INSERT IGNORE, then the row won't actually get inserted if there is a duplicate key (PRIMARY or UNIQUE), or inserting a NULL into a column with a NOT NULL constraint.
Referring to the pass column, as you have not defined anything to insert into it, and it has NOT NULL constraint.
EDIT:
Referring also to the mail column, as you have a UNIQUE constraint on it.

Categories