MySQL: UNIQUE keys - php

I have a weird issue, well, weird in my eyes anyway.
I've got a database with ID, username, email, password etc...
The ID is the Primary key, and both the username and email have the UNIQUE key assigned.
Now the strange thing is, when I submit, lets say the following values;
username: ActionHank
email: ah#ah.com
it is added.
Now when I try adding the same values again, I get an error that it is not allowed since it would be a duplicate entry. This works great.
But, when I put in the following next;
username: ActionHank2
email: ah#ah.com
It just adds it again, so 2 users have the same e-mail address while I've given the email row the UNIQUE key. I could also just change the e-mail address instead of the username and it will be added. So somehow the MySQL only registers one of the UNIQUE keys or something, I'm confused.
Could someone help me on this matter? Thanks
Edit: I've used phpMyAdmin to create the table and exported it to SQL, here's how the create table looks:
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(25) NOT NULL,
`email` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
`date_registered` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`ip_address` varchar(50) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`,`email`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=54 ;
So I think it has a composite as Michael and Kingkero suggested. How can I solve this within phpMyAdmin?

You have defined the combination of username and email to be unique. If you want each to be unique, you need to define separate unique constraints:
create table . . .
unique username,
unique email
)
Or, because these are single columns, you can just do:
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
`username` varchar(25) NOT NULL UNIQUE,
`email` varchar(255) NOT NULL UNIQUE,
`password` varchar(255) NOT NULL,
`date_registered` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`ip_address` varchar(50) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=54 ;

Try this:
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`),
UNIQUE KEY `email` (`email`)

Related

how to avoid duplicate entries

I created a form on my website where the user can create an account. I save everything into a database connected to a website.
This is how I created a table:
CREATE TABLE Customer(
CID int(9) not null PRIMARY KEY AUTO_INCREMENT,
Email VARCHAR(100) not null,
CustomerName VARCHAR(42) not null,
Password VARCHAR(42) not null,
Phone VARCHAR(42)
);
Since users would use the email and password to later login to the website, I don't want duplicated email entries.
Now my question is should I make column email unique inside my table or should I check if the inputted email already exists in the database (with PHP)? Is there even any difference?
Making the email and username as unique for example
CREATE TABLE `Customer` (
`CID` INT(9) NOT NULL AUTO_INCREMENT,
`Email` VARCHAR(100) NOT NULL,
`CustomerName` VARCHAR(42) NOT NULL,
`Password` VARCHAR(42) NOT NULL,
`Phone` VARCHAR(42) NULL DEFAULT NULL,
PRIMARY KEY (`CID`),
UNIQUE INDEX `Email` (`Email`),
UNIQUE INDEX `CustomerName` (`CustomerName`)
);
of course you must also check it in your application, but this will prevent it.

ERROR 1005 (HY000): Can't create table 'db.POSTS' (errno: 150)

Hi I'm having issues creating my post database. I'm trying to make a forenge key to link to my users database. Can someone please help?
Here's the code for my tables :
CREATE TABLE USERS(
UserID int NOT NULL AUTO_INCREMENT,
UserName varchar(255),
UserPassword varchar(255) NOT NULL,
UserEmailAddress varchar(255) NOT NULL,
Admin int DEFAULT 0,
PRIMARY KEY (userID,UserName)
)ENGINE=InnoDB;
CREATE TABLE POSTS(
postID int NOT NULL AUTO_INCREMENT,
postTitle varchar(255) NOT NULL,
postContent varchar(255) NOT NULL,
category varchar(255) NOT NULL,
postDate Date NOT NULL,
postAuthor varchar(255),
tag varchar(255),
PRIMARY KEY(postID),
FOREIGN KEY(postAuthor) REFERENCES USERS(UserName)
)ENGINE=InnoDB;
Here's the last InnoDB error message:
Error in foreign key constraint of table db/POSTS:
FOREIGN KEY(postAuthor) REFERENCES USERS(UserName)
)ENGINE=InnoDB:
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.
Note that the internal storage type of ENUM and SET changed in
tables created with >= InnoDB-4.1.12, and such columns in old tables
cannot be referenced by such columns in new tables.
See http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html
for correct foreign key definition.
There really should not be a good reason to have a compound primary key on the first table. So, I think you intend:
CREATE TABLE USERS (
UserID int NOT NULL AUTO_INCREMENT,
UserName varchar(255),
UserPassword varchar(255) NOT NULL,
UserEmailAddress varchar(255) NOT NULL,
Admin int DEFAULT 0,
PRIMARY KEY (userID),
UNIQUE (UserName)
);
CREATE TABLE POSTS (
postID int NOT NULL AUTO_INCREMENT,
postTitle varchar(255) NOT NULL,
postContent varchar(255) NOT NULL,
category varchar(255) NOT NULL,
postDate Date NOT NULL,
postAuthor int,
tag varchar(255),
PRIMARY KEY(postID),
FOREIGN KEY(postAuthor) REFERENCES USERS(UserId)
);
Some notes:
An auto-incremented id is unique on every row. It makes a good primary key.
A primary key can consist of multiple columns (called a composite primary key). However, an auto-incremented id doesn't make much sense as one of the columns. Just use such an id itself.
If you use a composite primary key, then the foreign key references need to include all columns.
I chose UserId for the foreign key reference. You could also use UserName (because it is unique).
UserName is a bad choice for foreign keys, because -- conceivably -- a user could change his or her name.
The error is caused by incorrect foreign key definition. In the concrete case you are missing a complete column in your foreign key definition.
In the USERS table you have defined primary key as composite key of UserID and UserName columns.
CREATE TABLE USERS (
UserID int NOT NULL AUTO_INCREMENT,
UserName varchar(255),
UserPassword varchar(255) NOT NULL,
UserEmailAddress varchar(255) NOT NULL,
Admin int DEFAULT 0,
PRIMARY KEY (UserID,UserName)
) ENGINE=InnoDB;
note that it is good practice to respect case of the identifiers (column names)
In the POSTS table you declared your foreign key to reference only one column in the USERS table, the UserName column. This is incorrect as you need to reference entire primary key of the USERS table which is (UserID, UserName). So to fix the error you need to add one additional column to the POSTS table and change your foreign key definition like this:
CREATE TABLE POSTS(
postID int NOT NULL AUTO_INCREMENT,
postTitle varchar(255) NOT NULL,
postContent varchar(255) NOT NULL,
category varchar(255) NOT NULL,
postDate Date NOT NULL,
authorId int,
postAuthor varchar(255),
tag varchar(255),
PRIMARY KEY(postID),
FOREIGN KEY(authorId, postAuthor) REFERENCES USERS(UserID, UserName)
) ENGINE=InnoDB;
Please look at following fiddle: http://sqlfiddle.com/#!9/92ff1/1
NOTE: If you can you should re-architect this to not use the composite primary key in the USERS table as it does not make sense from what I can see in the displayed code. You can change the tables like this:
CREATE TABLE USERS (
UserID int NOT NULL AUTO_INCREMENT,
UserName varchar(255),
UserPassword varchar(255) NOT NULL,
UserEmailAddress varchar(255) NOT NULL,
Admin int DEFAULT 0,
PRIMARY KEY (UserID)
) ENGINE=InnoDB;
CREATE TABLE POSTS (
postID int NOT NULL AUTO_INCREMENT,
postTitle varchar(255) NOT NULL,
postContent varchar(255) NOT NULL,
category varchar(255) NOT NULL,
postDate Date NOT NULL,
postAuthorID int,
tag varchar(255),
PRIMARY KEY(postID),
FOREIGN KEY(postAuthorID) REFERENCES USERS(UserID)
) ENGINE=InnoDB;;

$wpdb->insert is not respacting unique fields

I have been creating Wordpress plugin for a while. This is example of mysql table:
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id INT(11) NOT NULL AUTO_INCREMENT,
email VARCHAR(100) DEFAULT NULL,
telephone VARCHAR(15) DEFAULT NULL,
PRIMARY KEY(id),
UNIQUE (email, telephone)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='WP plugin sesa_players db' AUTO_INCREMENT=1 ;
";
Email should be unique, right? phpMyAdmin says it it.
This is wordpress code that inserts data into that table:
$err = $wpdb->insert($wpdb->prefix.$table_name, $data, $format);
var_dump($err);
It works, even more than it should. Assume email is m#m.com. First insert goes well. Second try fails because of duplicate entry as it should. var_dump is false.
BUT if I refresh wp page, third try with same email passes flawlessly, var_dump 1. Any repeated wp refresh opens db for duplicate entry.
Why? What am I doing wrong?
No, email is not UNIQUE here. Pair of email and telephone is UNIQUE in your table definition.
$sql = "CREATE TABLE IF NOT EXISTS $table_name (
id INT(11) NOT NULL AUTO_INCREMENT,
email VARCHAR(100) DEFAULT NULL,
telephone VARCHAR(15) DEFAULT NULL,
PRIMARY KEY(id),
UNIQUE (email),
UNIQUE (telephone)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='WP plugin sesa_players db' AUTO_INCREMENT=1 ;
";
Probably this is what you want.

PHP MySQL (PDO) CREATE TABLE does not create tables (and in fact, does nothing)

I have been struggling since this morning, trying to write an install.php file that will insert three empty tables (users, sessions, posts) into a database. The SQL code I'm using is valid when I inject it with PHPMyAdmin, but apparently the way I'm handling it in PHP is wrong, because when I run my install.php file my database remains empty. Here's my code:
<?php
try {
$con = new PDO('mysql:host=omitted;dbname=omitted','omitted','');
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$con->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$q="CREATE TABLE posts (
title varchar(150) NOT NULL,
body text NOT NULL,
created varchar(100) NOT NULL,
user varchar(40) NOT NULL,
id int(20) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id),
UNIQUE KEY id (id)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
CREATE TABLE sessions (
session_id varchar(40) NOT NULL,
data text NOT NULL,
last_activity int(11) NOT NULL,
PRIMARY KEY (session_id)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
CREATE TABLE users (
id int(11) NOT NULL AUTO_INCREMENT,
username varchar(40) NOT NULL,
password varbinary(250) NOT NULL,
email varchar(40) NOT NULL,
salt varchar(20) NOT NULL,
name varchar(50) NOT NULL DEFAULT '',
PRIMARY KEY (id),
UNIQUE KEY email (email),
UNIQUE KEY username (username),
UNIQUE KEY id (id)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ";
$stmt = $con->prepare($q);
$stmt->execute();
echo "success";
} catch (PDOException $e) {
$e->getMessage();
}
?>
I am assuming that it's some idiotic mistake on my part (since my last 3 headaches were also quite silly) but at this moment I really can't figure it out. Any ideas?
You can prepare only one statement per prepare call. To execute multiple statements you have to use PDO::exec method.
For example:
$con = new PDO('mysql:host=localhost;dbname=db','user','pass');
$con->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$con->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$q="CREATE TABLE posts (
title varchar(150) NOT NULL,
body text NOT NULL,
created varchar(100) NOT NULL,
user varchar(40) NOT NULL,
id int(20) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id),
UNIQUE KEY id (id)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=5 ;
CREATE TABLE sessions (
session_id varchar(40) NOT NULL,
data text NOT NULL,
last_activity int(11) NOT NULL,
PRIMARY KEY (session_id)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
CREATE TABLE users (
id int(11) NOT NULL AUTO_INCREMENT,
username varchar(40) NOT NULL,
password varbinary(250) NOT NULL,
email varchar(40) NOT NULL,
salt varchar(20) NOT NULL,
name varchar(50) NOT NULL DEFAULT '',
PRIMARY KEY (id),
UNIQUE KEY email (email),
UNIQUE KEY username (username),
UNIQUE KEY id (id)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ";
try {
$con->exec($q) or die(print_r($db->errorInfo(), true));;
echo "Success";
} catch (PDOException $e) {
$e->getMessage();
}
This is not a query but rather set of queries.
Just run them one by one with separate calls.

mysql compare takes too much time

I'm Using 3 tables here listed below:
CREATE TABLE `user` (
`uid` int(10) NOT NULL AUTO_INCREMENT,
`kid` int(3) NOT NULL,
`Email` varchar(255) DEFAULT NULL,
`del` tinyint(1) DEFAULT '0',
PRIMARY KEY (`uid`),
KEY `kid` (`kid`),
KEY `email` (`Email`)
) ENGINE=MyISA
and
CREATE TABLE `blacklist_global` (
`bgid` int(10) NOT NULL AUTO_INCREMENT,
`email` varchar(255) NOT NULL,
`kid` int(3) DEFAULT NULL,
`stmp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`bgid`),
UNIQUE KEY `email` (`email`),
KEY `kid` (`kid`)
) ENGINE=MyISAM
and
CREATE TABLE `verteiler_user` (
`vuid` int(10) NOT NULL AUTO_INCREMENT,
`uid` int(3) NOT NULL,
`vid` int(3) NOT NULL,
`del` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`vuid`),
KEY `uid` (`uid`)
) ENGINE=MyISAM
every entry in table user is also in table verteiler_user. now i want to delete every entry from user where user.uid = verteiler_user.uid and verteiler_user.vid=XX and user.uid = XXX
so atm im doing it from php fetch all entrys from table user, all from blacklist_global.
the problem is, in the blacklist i could enter *#heloooo.de so i want to delete every email from the domain helooo.de but its very very slow.
is it possible to do it only in mysql? without php ? or any tip, of doing this faster ?
This might get what you need. Test it first before using it on production data.
DELETE FROM user WHERE uid = ? AND uid in (SELECT uid from verteiler_user WHERE vid = ?)
Edited based on comment:
DELETE FROM user WHERE uid IN (SELECT uid FROM blacklist_global WHERE email LIKE '%#somedomain.com')

Categories