Duplicate data is inserted with unique index - mysql

I have a table called users with 4 unique columns and when I insert data in email it doesn't give me any error and inserts the data even when when the same value already exists in that column.
Here is my database structure:
$user = "CREATE TABLE IF NOT EXISTS users(
id INT UNSIGNED AUTO_INCREMENT,
fb_id BIGINT UNSIGNED NULL,
google_id BIGINT UNSIGNED NULL,
fname VARCHAR(255) NOT NULL,
lname VARCHAR(255) NULL,
email VARCHAR(320) NOT NULL,
username VARCHAR(20) NULL,
password VARCHAR(255) NULL,
access_token TEXT NULL,
type ENUM('facebook','google','site') NOT NULL,
gender ENUM('m','f','o') NULL,
reg_date DATE NOT NULL,
token_expire DATETIME NULL,
PRIMARY KEY(id),
UNIQUE(email,username,fb_id,google_id)
)";
But, when I create my table with following structure:
$user = "CREATE TABLE IF NOT EXISTS users(
id INT UNSIGNED AUTO_INCREMENT,
fb_id BIGINT UNSIGNED NULL UNIQUE,
google_id BIGINT UNSIGNED NULL UNIQUE,
fname VARCHAR(255) NOT NULL,
lname VARCHAR(255) NULL,
email VARCHAR(320) NOT NULL UNIQUE,
username VARCHAR(20) NULL UNIQUE,
password VARCHAR(255) NULL,
access_token TEXT NULL,
type ENUM('facebook','google','site') NOT NULL,
gender ENUM('m','f','o') NULL,
reg_date DATE NOT NULL,
token_expire DATETIME NULL,
PRIMARY KEY(id)
)";
It gives me an error when there is a duplicate entry.
Creating table with any of those methods doesn't give any error. After creating the tables I have verified with phpmyadmin that all those columns have unique index in both methods.

Akash, in the 1st create table, the composite (combination) is unique. If you want them individually to be unique, separate them into ... separate UNIQUE key statements, like in the 2nd.
Let's say the bottom of your first table read this
PRIMARY KEY(id),
UNIQUE KEY(email,username,fb_id,google_id)
Then there is nothing wrong with these two rows existing in the composite index:
'akash#gmail.com','Akash',101,102
and
'akash#gmail.com','Akash2',101,102

Related

How to get users by last message in Laravel Eloquent

I'm currently developing a simple chat application with Laravel 8 and VueJS. I need to order users by their latest message and get the last message along with the user. Below are the tables I am using if anyone has an idea for this operation. If it's an Eloquent method, it would be better.
Users Table
create table users
(
id bigint unsigned auto_increment
primary key,
name varchar(255) not null,
email varchar(255) not null,
email_verified_at timestamp null,
password varchar(255) not null,
two_factor_secret text null,
two_factor_recovery_codes text null,
remember_token varchar(100) null,
status varchar(255) default 'online' not null,
last_seen timestamp null,
current_team_id bigint unsigned null,
profile_photo_path varchar(2048) null,
created_at timestamp null,
updated_at timestamp null,
constraint users_email_unique
unique (email)
)
collate = utf8mb4_unicode_ci;
Private Messages Table
create table private_messages
(
id bigint unsigned auto_increment
primary key,
sender_id bigint unsigned not null,
receiver_id bigint unsigned not null,
message varchar(1000) not null,
delete_type varchar(15) null,
created_at timestamp null,
updated_at timestamp null,
deleted_at timestamp null,
constraint private_messages_receiver_id_foreign
foreign key (receiver_id) references users (id)
on delete cascade,
constraint private_messages_sender_id_foreign
foreign key (sender_id) references users (id)
on delete cascade
)
collate = utf8mb4_unicode_ci;
in user model create relation function
public function privateMessages()
{
return $this->hasMany(PrivateMessage::class)->orderBy('id','DESC');
}
then use
$users = User::with('privateMessages')->all();
in this result , messages sort by id desc.

MySQL database schema: 3 columns of same type with different purpose

I am building a financial app, and it requires the following tables:
tax
item, which can have one tax
invoice, which can have many items
To the question:
An invoice must have the ability to contain 3 categories of emails:
Recipient emails
CC emails
BCC emails
So far I just have a recipients/cc/bcc column, but I don't think it's good because I'd basically have to concatenate the emails together and separate them by a comma or something.
I also thought about a generic email table, but then I'd have to create invoice_recipient_email, invoice_cc_email and invoice_bcc_email tables respectively, in order to link the emails back to the particular invoice ID as well as categorize them by the 3 types.
Can someone advice me on my second solution, or provide a better way to do this?
Here is my current schema:
CREATE TABLE tax (
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
rate INT(3) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE item (
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
description VARCHAR(1000) NOT NULL,
quantity INT(10) NOT NULL,
price INT(10) NOT NULL,
CONSTRAINT `f_tax_item_tax_id` FOREIGN KEY (`tax_id`) REFERENCES `tax` (`id`),
PRIMARY KEY (id)
);
CREATE TABLE invoice (
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
invoice_number VARCHAR(255) NOT NULL,
recipients VARCHAR(1000) NOT NULL,
cc VARCHAR(1000) NOT NULL,
bcc VARCHAR(1000) NOT NULL,
discount INT(10) NOT NULL,
note VARCHAR(500) NOT NULL,
terms VARCHAR(2000) NOT NULL,
due_date TIMESTAMP NOT NULL,
PRIMARY KEY (id)
);
I would add a single recipients table with id (pk), invoice_id (fk), email, recipient_type fields, where recipient type could have one of the following values: to, cc, or bcc. The recipient type field would tell you how to use the email address, therefore you would not need 3 separate tables to hold the 3 different recipient types.
1 record would hold only 1 email address.
You can normalize your emails into a single table and put a flag on it to categorize its type.
CREATE TABLE invoice (
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
invoice_number VARCHAR(255) NOT NULL,
discount INT(10) NOT NULL,
note VARCHAR(500) NOT NULL,
terms VARCHAR(2000) NOT NULL,
due_date TIMESTAMP NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE email(
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
invoice_id INT(10) not null references invoice(id),
email_type int not null,
addresses varchar(1000),
PRIMARY KEY (id)
);
You can define your email types in another table as well. You can look at this approach implemented in a production environment for phone numbers in MSSSQL but same concept. We however normalize the records to one phone number per record which I would also recommend you do.
CREATE TABLE [dbo].[ActorPhones](
[PKId] [int] IDENTITY(0,1) NOT NULL Primary Key,
[FKActorId] [int] NOT NULL References Actor(PKID),
[FKPhoneTypeId] [int] NOT NULL,
[Number] [varchar](20) NOT NULL
) ON [PRIMARY]
CREATE TABLE [dbo].[PhoneTypes](
[PKId] [int] IDENTITY(0,1) NOT NULL Primary Key,
[PhoneTypeName] [varchar](50) NOT NULL References ActorPhones(PKId),
[PhoneTypeDescription] [varchar](250) NULL,
[ModifiedDate] [datetime] NULL,
[ModifiedBy] [varchar](50) NULL
)

Why I obtain this FK error when I try to create this table? errno: 150 "Foreign key constraint is incorrectly formed

I have this USER table on a MySql DB:
id bigint(20) unsigned NO PRI NULL auto_increment
username varchar(30) NO NULL
pswd varchar(40) NO NULL
Then I am trying to create a new ACCOMODATION table having a user_Id field that is the foreign key of the previous USER table, I am doing in this way:
CREATE
TABLE testdb.ACCOMODATION
(
Id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
user_Id BIGINT(20) NOT NULL,
name VARCHAR(255) NOT NULL,
address VARCHAR(255) NOT NULL,
tel VARCHAR(20) NOT NULL,
mobile VARCHAR(20) NOT NULL,
fax VARCHAR(20) NOT NULL,
email VARCHAR(80) NOT NULL,
cap VARCHAR(20) NOT NULL,
nation VARCHAR(20) NOT NULL,
region VARCHAR(20) NOT NULL,
province VARCHAR(20) NOT NULL,
municipality VARCHAR(20) NOT NULL,
stars ENUM('ONE', 'TWO', 'THREE', 'FOUR', 'FIVE') NOT NULL,
lat BIGINT NOT NULL,
lon BIGINT NOT NULL,
CONSTRAINT fk_accomodation_user FOREIGN KEY (user_Id) REFERENCES testdb.user (Id),
PRIMARY KEY (Id)
)
ENGINE=InnoDB DEFAULT CHARSET=latin1
But I obtain the following error message:
#1005 - Can't create table testdb.accomodation (errno: 150 "Foreign key constraint is incorrectly formed")
How can I fix this issue?
Data type of user_id column in ACCOMODATION table must be exactly the same data type of id column in user table.
user_id bigint(20) unsigned NO NULL
These definitions are not the same:
id bigint(20) unsigned NO PRI NULL auto_increment
user_Id BIGINT(20) NOT NULL
An unsigned bigint is not the same as a signed bigint. The columns used in a foreign key reference need to have exactly the same types as the columns in the original table.

Creating tables with foreign keys

I am creating tables where I have foreign keys. This is part of the statements. For some reason I cannot get it to work.
What am i doing wrong?
CREATE TABLE Doctor (
NPI NUMBER PRIMARY KEY NOT NULL,
LNAME VARCHAR(20) NOT NULL,
FNAME VARCHAR(20) NOT NULL,
PHONE NUMBER NOT NULL,
ADDRESS VARCHAR(20) NOT NULL
CITY VARCHAR(20) NOT NULL );
CREATE TABLE Patient (
SSN NUMBER PRIMARY KEY NOT NULL,
INSURANCE_POLICY_ID NUMBER NOT NULL,
LNAME VARCHAR(20) NOT NULL,
FNAME VARCHAR(20) NOT NULL,
DOB DATE NOT NULL,
PHONE NUMBER NOT NULL,
ADDRESS VARCHAR(20) NOT NULL,
CITY VARCHAR(20) NOT NULL,
FOREIGN KEY (INSURANCE_POLICY_ID) REFERENCES INSURANCE (INSURANCE_POLICY_ID));
You have tagged your question with SQL Server and MySql both, in both of these RDBMS there is no data type called Number but there is a data type to store numbers it is called INT or INTEGER.
Therefore your table definitions should be as follow:
CREATE TABLE Doctor (
NPI INT NOT NULL PRIMARY KEY ,
LNAME VARCHAR(20) NOT NULL,
FNAME VARCHAR(20) NOT NULL,
PHONE INT NOT NULL, --<-- should be a varchar since most phone numbers have a leading zero
ADDRESS VARCHAR(20) NOT NULL,
CITY VARCHAR(20) NOT NULL );
CREATE TABLE Patient (
SSN INT NOT NULL PRIMARY KEY,
INSURANCE_POLICY_ID INT NOT NULL,
LNAME VARCHAR(20) NOT NULL,
FNAME VARCHAR(20) NOT NULL,
DOB DATE NOT NULL,
PHONE INT NOT NULL,
ADDRESS VARCHAR(20) NOT NULL,
CITY VARCHAR(20) NOT NULL,
FOREIGN KEY (INSURANCE_POLICY_ID)
REFERENCES INSURANCE (INSURANCE_POLICY_ID));

MySQL-error 150 solution

I have the following MySQL scripts:
CREATE TABLE user_roles (
id INT AUTO_INCREMENT,
PRIMARY KEY(id),
name TEXT NOT NULL,
access INT NOT NULL DEFAULT '0'
)
CREATE TABLE users (
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id),
name TEXT NOT NULL,
email TEXT NOT NULL,
password TEXT NOT NULL,
date_created DATETIME,
roles VARCHAR(50) NOT NULL,
active INT DEFAULT '1',
FOREIGN KEY(roles) REFERENCES user_roles(id)
)
It keeps giving me error 150. Maybe the database isn't well planned? Any help will be greatly appreciated.
The data types of your users.roles and user_roles.id columns must be the same for the FOREIGN KEY constraint to work correctly. Instead try making users.roles an INT:
CREATE TABLE users (
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id),
name TEXT NOT NULL,
email TEXT NOT NULL,
password TEXT NOT NULL,
date_created DATETIME,
-- Change this...
roles INT NOT NULL,
active INT DEFAULT '1',
FOREIGN KEY(roles) REFERENCES user_roles(id)
)
UPDATE According to comments, users.roles should be text like "admin, moderator, etc." For correct data normalization, user_roles.id should be keyed against and to get the text name of the role, JOIN them in queries.
You need to separate your statements with a semicolon and use INTS instead of strings:
CREATE TABLE user_roles (
id INT AUTO_INCREMENT,
PRIMARY KEY(id),
name TEXT NOT NULL,
access INT NOT NULL DEFAULT 0
);
CREATE TABLE users (
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id),
name TEXT NOT NULL,
email TEXT NOT NULL,
password TEXT NOT NULL,
date_created DATETIME,
roles VARCHAR(50) NOT NULL,
active INT DEFAULT 1,
FOREIGN KEY(roles) REFERENCES user_roles(id)
);