In my sql set condition for table? - mysql

In mysql can I set a condition that a combination of two fields can never be the same???
Example:
id-1
name-abc
grade-A
Now, another entry with name='abc' and grade='A' can not be added into that table ????

You can create a composite primary key from those two columns, but that makes little sense as the table already has an ID field, and surely two people of the same name can have the same grade? e.g.:
CREATE TABLE student_grades (
id int unsigned not null,
name varchar not null,
grade varchar not null,
PRIMARY KEY(name, grade));

You can also add a secondary UNIQUE constraint:
CREATE TABLE student_grades (
id int unsigned not null,
name varchar(10) not null,
grade varchar(10) not null,
PRIMARY KEY(id),
UNIQUE KEY(name, grade)
);

Related

EAV model - How to restrict product properties?

I have the following structure of my database, implementing a simple EAV model (see pic):
My product has a type, which through the junction table restricts prop_names, available for this product. And here everything is clear.
BUT:
Then I've added a prop_values table to keep the properties values for each product. It has reference to products through prod_sku and to prop_names through prop_id. And here the problem comes: One can add to any product any properties - even those, which are not allowed for this product type. Also, there can be duplications - two or more same properties for a single product.
Is there any way to restrict this on the database level?
After the #BillKarvin's answer, I've tried the below CREATE code, but failed with the 'Foreign key constraint is incorrectly formed' error when creating the last table (property_values).
I have found my error - I forgot to add a KEY to the products table. Below is the corrected (working) version of my code:
CREATE TABLE product_types (
id INT PRIMARY KEY,
product_type varchar(50) NOT NULL,
block_css_id varchar(50) NOT NULL,
block_description varchar(50) NOT NULL
);
CREATE TABLE products (
sku varchar(50) PRIMARY KEY,
name varchar(50) NOT NULL,
price decimal(20,2) unsigned NOT NULL,
id_product_type INT NOT NULL,
FOREIGN KEY (id_product_type) REFERENCES product_types (id),
KEY (sku, id_product_type)
);
CREATE TABLE property_names (
id INT PRIMARY KEY,
property_name varchar(50) NOT NULL,
property_css_id varchar(50) NOT NULL,
property_input_name varchar(50) NOT NULL
);
CREATE TABLE junction_ptype_propname (
id_productt_type INT NOT NULL,
id_property_name INT NOT NULL,
PRIMARY KEY (id_productt_type, id_property_name),
FOREIGN KEY (id_productt_type) REFERENCES product_types (id),
FOREIGN KEY (id_property_name) REFERENCES property_names (id)
);
CREATE TABLE property_values (
id INT NOT NULL PRIMARY KEY,
product_sku varchar(50) NOT NULL,
property_id INT NOT NULL,
property_value decimal(20,2) NOT NULL DEFAULT 0.00,
id_prod_type INT NOT NULL,
UNIQUE KEY (product_sku, property_id),
FOREIGN KEY (product_sku, id_prod_type) REFERENCES products (sku, id_product_type),
FOREIGN KEY (property_id, id_prod_type) REFERENCES junction_ptype_propname (id_property_name, id_productt_type)
);
I would design this in the following way:
There are few important differences from your model:
prop_values has a unique key on (prod_sku, prop_id) so you can only have one instance of a given property per product sku.
prop_values has a prod_type column, and this references products, using both columns (sku, prod_type).
prop_values has a compound foreign key to junction_ptype_propname instead of prop_name.
Now the prod_type in prop_values can have a single value per row, and it must reference the correct product type in both the products table and the junction_ptype_propname table. So it is constrained to be a valid property for the given product, and a valid property for the product type. You therefore cannot add a property to a product that isn't legitimate for that product's type.
Here's the DDL:
create table prod_types (
id int primary key,
type_name varchar(30) not null
);
create table products (
sku varchar(30) primary key,
name varchar(30) not null,
type int not null,
foreign key (type) references prod_types(id),
key(sku, type)
);
create table prop_names (
id int primary key,
prop_name varchar(30) not null
);
create table junction_ptype_propname (
id_prop_name int not null,
id_prod_type int not null,
primary key (id_prop_name, id_prod_type),
foreign key (id_prod_type) references prod_types(id),
foreign key (id_prop_name) references prop_names(id)
);
create table prop_values (
id int primary key,
prod_sku varchar(30) not null,
prod_type int not null,
prop_id int not null,
prop_value decimal not null,
unique key (prod_sku, prop_id),
foreign key (prod_sku, prod_type) references products(sku, type),
foreign key (prop_id, prod_type) references junction_ptype_propname(id_prop_name, id_prod_type)
);
This question is fun because it's a case of using Fifth Normal Form. Many articles on database design claim that normal forms past the Third Normal Form aren't used. But your model disproves that.
Also, there can be duplications - two or more same properties for a
single product.
Use UNIQUE to prevent from duplications
w3schools.com - UNIQUE

Issue in mysql table creation

I need to create a table called benificiaries where I have three columns
customerid
accountno
bank
The condition should be one customerid can have only one unique accountno. But another customerid can have the same accountno and same unique (only once). So I cant give primary key to accountno. Even for customerid I can't give primary key, since one customerid can have multiple records with unique accountno.
How can we create table in this case? Any ideas?
You can use multiple-column unique index.
CREATE TABLE YOUR_TABLE (
id INT NOT NULL AUTO_INCREMENT,
customerid INT NOT NULL,
accountno INT NOT NULL,
bank INT NOT NULL,
PRIMARY KEY (id),
UNIQUE INDEX name (customerid,accountno)
);
Documentation here.
https://dev.mysql.com/doc/refman/5.7/en/multiple-column-indexes.html
If one customerid can have only 1 unique account number then how can you expect duplicates in terms of customer id in that table?
You can simply set a primary key to another column and make the customerid unique. I think this is what you want to have. Now every customerid is unique, but many costomerids can have the same accountno.
CREATE TABLE benificiaries(
id INT PRIMARY KEY,
customerid INT NOT NULL UNIQUE,
accountno INT NOT NULL,
bank INT NOT NULL
);
database can't manage all the business constraints within the data model. For the case, you might address elementary constraints with indexes (multiple column index for customerid, accountno and simple column index for accountno to perform search on the other way), add an auto-increment id and deal the business constraints in your code.
Just set your customer_id as a primary key then regarding the concept that a only two customer_id can have same account number once, will depend on the process of your App or System.
CREATE TABLE `tmpr_map`.`tbl_example`
(`customer_id` INT(11) NOT NULL AUTO_INCREMENT,
`account_number` VARCHAR NOT NULL , `bank_amount` DECIMAL(11,2) NOT NULL ,
PRIMARY KEY (`customer_id`)) ENGINE = InnoDB;

Can't add foreign key to mysql

I have multiple tables and they all seem to be fine but there is this one table which I'm trying to create but it wont work because I am keep on getting Error1005 "Foreign key constraint is incorrectly formed".
These are the two tables. I don't know what seems to be the problem.
CREATE TABLE Patient(
ID INT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,
Name VARCHAR(255) NOT NULL,
Age TINYINT UNSIGNED,
Sex VARCHAR(10),
Contact INT(11),
Email TEXT(2083),
PRIMARY KEY(ID)
);
CREATE TABLE Appointments (
Appointment_No INT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,
Name VARCHAR(255) NOT NULL,
Contact INT(11),
Date DATE NOT NULL,
Time TIME NOT NULL,
Reason TEXT(2083),
PRIMARY KEY(Appointment_No),
FOREIGN KEY (Name, Contact) REFERENCES Patient (Name, Contact)
);
As per me, table structure should be like below:
CREATE TABLE Patient(
ID INT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,
Name VARCHAR(255) NOT NULL,
Age TINYINT UNSIGNED,
Sex VARCHAR(10),
Contact INT(11),
Email TEXT(2083),
PRIMARY KEY(ID)
);
CREATE TABLE Appointments (
Appointment_No INT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE,
Patient_ID INT UNSIGNED NOT NULL,
Date DATE NOT NULL,
Time TIME NOT NULL,
Reason TEXT(2083),
PRIMARY KEY(Appointment_No),
FOREIGN KEY (Patient_ID) REFERENCES Patient (ID)
);
FOREIGN KEY (Name, Contact) REFERENCES Patient (Name, Contact)
The referenced columns in the Patient table must be part of a key. Ideally you would want Patient (Name, Contact) to be a unique key, because then the foreign key is guaranteed to reference exactly one row in the Patient table.
But in your table definition, the Name and Contact columns are not part of a key. That explains why you got the error given your table design.
But your table design is not good. Name and Contact are not good choices as a unique key, because two people can share a name, and in theory you could even have two people with the same name with the same contact details (for example, the former boxer George Foreman named his five sons George).
#Shadow is correct that it's a better idea is to reference Patient(id) instead, because it's guaranteed to be unique already.
Define Engine so sql statement would end with
ENGINE = MyISAM;
It should fix the issue.
Try to split the two foreign keys in two lines like this:
FOREIGN KEY (Contact) REFERENCES Patient (Contact)
FOREIGN KEY (Name) REFERENCES Patient (Name)

database using foreign keys

please excuse me if i'm doing things wrong, as I am new to this forum.. I am trying to figure out what columns to have for foreign keys... My teacher redid my database and i can't understand what to do. Here is my ERD: http://s1.postimg.org/3l2j6rh4v/Picture.png
I have looked up tutorials but I can't seem to find out how to use them..
Here is my MySQL code:
DROP TABLE PaymentType;
DROP TABLE ProjectType;
DROP TABLE Projects;
DROP TABLE Payment;
DROP TABLE Customer;
CREATE TABLE Customer
(
Customer_ID varchar(100) NOT NULL,
FName varchar(15) NOT NULL,
LName varchar(20) NOT NULL,
CustAddress varchar(20) NOT NULL,
CustCity varchar(30) NOT NULL,
CustState varchar(20),
CustZip char(5),
CustBal numeric(7,2) NOT NULL,
PRIMARY KEY (Customer_ID)
);
CREATE TABLE Payment
(
Payment_ID varchar(100) NOT NULL,
PaymentType varchar(15),
Date date NOT NULL,
AmntPaid numeric(7,2) NOT NULL,
PRIMARY KEY (Payment_ID)
);
CREATE TABLE Projects
(
Project_ID varchar(100) NOT NULL,
ProjectType varchar(30) NOT NULL,
LaborHrs char(3) NOT NULL,
Date date NOT NULL,
PRIMARY KEY (Project_ID)
);
CREATE TABLE ProjectType
(
Project_ID varchar(100) NOT NULL,
ProjectDesc varchar(100) NOT NULL,
PRIMARY KEY (Project_ID)
);
CREATE TABLE PaymentType
(
Payment_ID varchar(100) NOT NULL,
PaymentDesc varchar(100) NOT NULL,
PRIMARY KEY (Payment_ID)
);
Hopefully I didn't do anything wrong, thanks!
1) You should change your types for the id columns. Using varchar as id column should be avoided, as this will just blow off the performance (+ some other problems which might occur). Using any type of int (int, tinyint,..) would be much better.
2) The table "ProjectType" should have a column "ProjectType_ID" instead of "Project_ID" - same goes for the PaymentType ("PaymentType_ID").
3) Rename the fields in "Project" and "Payment" table as well.
4) The code for foreign-keys will look like:
ALTER TABLE Project
ADD CONSTRAINT Project_ProjectType
FOREIGN KEY (ProjectType_ID)
REFERENCES ProjectType(ProjectType_ID);
Do the same with Payment table.
Important: add "alter table"-command to the end of your sql file, so all tables are created
Important: your database schema should be innodb, or any other schema which supports foreign-keys (MyIsam does NOT support foreign-keys)
5) For the relation between Customer and Projects you will need an extra table (so one project can have multiple users | might be a change to your erd). A cross-relation table (called something Like CustomerProject) with fields "Project_ID" and "Customer_ID". Then add a foreign-key to the project table and add a foreign-key to customer table. (extra points for adding a unique key to "Project_ID" + "Customer_ID")
For the payment and user, just add a "Customer_ID" field in "Payment" table and add a foreign-key as explained in #4.
(offtopic): your naming convention is a bit wierd. Mixing underscore and camelcase should be avoided. You can just stick to camelcase - even for your id fields - but this is just a personal opinion

MySQL issue.. creating and referencing tables at once

I was trying to create multiple tables (some of them referncing the other tables) at once.
I think I matched data types and set primary/foreign keys correctly. But I can only see an error
of 'You cannot add foreign key constraint'. I thought the referenced tables might be created on the first before other tables refernce it, so I reversed the order and the result was the same.
Lastly I tried creating and executing only the referenced tables first(item_type), then referencing tables(item) later.. and... it worked!
However, I wonder if those codes can be executed at once.
Here is code below..
(just two tables are shown to make it simple..)
CREATE TABLE item (
i_id SMALLINT unsigned NOT NULL AUTO_INCREMENT,
i_name VARCHAR(30) NOT NULL,
t_id SMALLINT unsigned NOT NULL,
PRIMARY KEY (i_id),
FOREIGN KEY (t_id) REFERENCES item_type(t_id)
) ENGINE=INNODB;
CREATE TABLE item_type (
t_id SMALLINT unsigned NOT NULL AUTO_INCREMENT,
t_name VARCHAR(20) NOT NULL,
PRIMARY KEY(t_id)
);
You can't define a foreign key to a table that doesn't exist, so doing the CREATE TABLE operations in the order above is not going to work. If you create the item_type table first, then the item table with the foreign key to item_type, it should work.
Database engines execute sql code in batches, so one statement that crate table is one batch, but in you example, first batch references second batch which is not executed yet, so change order of batches and it will be working.
CREATE TABLE item_type (
t_id SMALLINT unsigned NOT NULL AUTO_INCREMENT,
t_name VARCHAR(20) NOT NULL,
PRIMARY KEY(t_id)
);
CREATE TABLE item (
i_id SMALLINT unsigned NOT NULL AUTO_INCREMENT,
i_name VARCHAR(30) NOT NULL,
t_id SMALLINT unsigned NOT NULL,
PRIMARY KEY (i_id),
FOREIGN KEY (t_id) REFERENCES item_type(t_id)
) ENGINE=INNODB;