SQL - How to prevent duplicate in specific condition? - mysql

In general, we can use unique key or primary key to prevent this, but in my case. I am creating an MyFavorite table like this:
---------------------------------------------------------
| UserName | FavoriteLink |
---------------------------------------------------------
| Ryan | http://www.google.com |
---------------------------------------------------------
| Ryan | http://www.yahoo.com |
---------------------------------------------------------
| Joyce | http://www.google.com |
---------------------------------------------------------
| Joyce | http://www.cnn.com |
---------------------------------------------------------
So, each user can have a lot of favoritelinks, but they shouldn't have duplicate favoritelink, for example, Ryan shouldn't have two favoritelink for http://www.google.com. but for this table, FavoriteLink field may be duplicate, because both Ryan and Joyce, they all have favoritelink for http://www.google.com.
Here is the question: how can I insert data into this table without duplicate FavoriteLink for specific person?

Composite keys.
CREATE TABLE userlinks (
user VARCHAR(255),
link VARCHAR(255),
PRIMARY KEY (user, link)
)
or
CREATE TABLE userlinks (
id INTEGER AUTO_INCREMENT PRIMARY KEY,
user VARCHAR(255),
link VARCHAR(255),
UNIQUE KEY (user, link)
)
depending on what exactly it is you want.

You can add a composite unique index.
CREATE UNIQUE INDEX username_favorite_uniq ON yourTable (UserName, FavoriteLink)

Related

MySQL Adding Foreign Key Error 1215

I know such a question is asked before. I made sure that they have the same data type and also checked my syntax, but I am still getting the error:
ALTER TABLE meetings ADD FOREIGN KEY (ownerName) REFERENCES employees(name);
ERROR 1215 (HY000): Cannot add foreign key constraint
mysql> desc `meetings`;
+-----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| room | int(6) | NO | | NULL | |
| ownerName | varchar(30) | NO | | NULL | |
| ownerID | varchar(30) | NO | | NULL | |
+-----------+-------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
mysql> desc `employees`;
+----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| name | varchar(30) | NO | | NULL | |
| username | varchar(30) | NO | PRI | NULL | |
| pswd | varchar(255) | YES | | NULL | |
+----------+--------------+------+-----+---------+-------+
What am I doing wrong?
name is not primary key in employees table so .. try using username
ALTER TABLE meetings ADD FOREIGN KEY (ownerName) REFERENCES employees(username);
or as suggested by DanielE or you can use the column name but need an UNIQUE index for this column
Change the primary key of 'employees' from user name to name. Then you can use
ALTER TABLE meetings ADD FOREIGN KEY (ownerName) REFERENCES employees(name);
What am I doing wrong? Error 1215 is probably the least of the problems here.
Some of the answers given for this question suggest making username the referenced column in employees rather than name, which is fine as far as it goes, but ignores some really fundamental issues in the schema and quite possibly wasn't the poster's intention for these columns. The rest of this answer is based on my own set of assumptions.
meetings table
Looking at the meetings table, I'm left wondering about the purpose of the ownerID column. Since the intention is to have ownerName as a foreign key to employees, what exactly is ownerID? The name suggests it also somehow references employees, but there is no id or ownerID in employees. Also, if any column starting owner... refers to an employee then why would you need both in the meetings table? One of them is surely redundant. Why is ownerID a VARCHAR(30)? ID columns tend to be INT. Of course, I may be reading to much into this and ownerID may have some other purpose that has nothing to do with an employee, but if that's the case the name is likely going to cause confusion in the future.
The meetings table also has an INT surrogate key in id. There's another INT for room. Since room isn't a foreign key, it suggests that rooms are either consistently identified only by number (which would be strange in my experience) and that there is nothing more to a 'room' that's worth capturing (e.g. location, capacity, equipment etc.) to bother with modelling data about the room in a separate table (again unlikely). Alternatively, room might itself be a foreign key referencing an INT id column in an, as yet undefined, rooms table.
employees table
If we accept ownerID as a more appropriate foreign key to the employee that owns the meeting (it uses less memory to index than either name or username) then consistency would suggest another surrogate key id as the primary key in the employees table. It's not necessary to do this, username would be unique and is fine on it's own, but it's simpler and more efficient. The other suggestion made that name should be the PK in employees is wrong - it presupposes that names are always unique.
A single column to cover an employee name would also be unusual.
The point made about referencing a PK or a unique index is well made (even if it's not strictly necessary in Innodb), I'd just say that ownerName is the wrong foreign key and username and name are the wrong references because there is a better alternative.
And, finally, is a NULL password (pswd) a good idea?

MySQL add dynamic amount to an table

i am very new to MySQL and making my first steps with it. I have right now 2 tables that look like this:
Event:
+-------+-------------+
| Field | Type |
+-------+-------------+
| id | int(11) |
| name | varchar(30) |
| date | datetime |
+-------+-------------+
User:
+----------+-------------+
| Field | Type |
+----------+-------------+
| name | varchar(30) |
| amount | int |
+----------+-------------+
Now i would like to be able to add an dynamic amount of Users to an Event but i am not sure how i should create an dynamic table for that or how otherwise i should implement such an behaviour. What would be the best practice?
Help would be appreciated.
That is a classic many-to-many relation. You handle it by adding a new table
event_users table
-----------------
event_id
user_id
For an event (id=1) having two users (id=3,4) it looks like this
event_id | user_id
1 | 3
1 | 4
To get all users of an event you would do this
select u.name
from users u
join event_users eu on eu.user_id = u.id
join events e on eu.event_id = e.id
where e.name = 'my event'
You need a third table, a junction table:
create table UserEvents (
UserEventId int auto_increment primary key,
UserId int,
EventId int,
constraint fk_userevents_userid foreign key (UserId) references Users(id),
constraint fk_userevents_eventid foreign key (EventId) references Events(id)
);
Notes:
I name tables in the plural.
The id for the table is the singular followed by "id" (so I prefer Users(UserId) and Events(EventId).
This has declared foreign key relationships.
If duplicates are not allowed, then you also want a unique constraint on (UserId, EventId).
For this you should use a third table in which you should maintain event and related user id.
user_event
id user_id event_id created_date
user_id and event_id are foreign keys for this table and will point primary keys of user and event table respectively

Show concatened composite primary key

I am working on the design of a database that will be used to get an unique ID. The "main" table will have a composite primary key by getting the id from others tables
As an example, consider the following table that illustrates the problem:
----------------------------------------------------------------
| PK_main_table| FK1 | FK2 | ... |
----------------------------------------------------------------
| 102_245 | 102 | 245 | ... |
| 102_984 | 102 | 984 | ... |
| 98_298 | 98 | 298 | ... |
| 564_114 | 564 | 114 | ... |
----------------------------------------------------------------
So I will wrote the following :
CREATE TABLE main_table
(
`id` INT NOT NULL AUTO_INCREMENT,
FK1 int(5),
FK2 int(5),
...
primary key(`FK1`, `_`, `FK2`, ...)
);
Note that all the foreign keys have an unique ID and it is possible for the same foreign key to be found many time (as you can see with FK1='102').
I have a decent understanding of relational databases, but am far from an expert or even an experienced user.
My question is : How can I get the primary key ? I wish I could do a SELECT [something there] where FK1='98' and get '98_298' as a result.
My solution was to add a new field "primary_key" add fill in with a trigger with the following code :
select
id,group_concat(concat(`FK1`,':',`FK2`) separator ',')
as Result from main_table group by id
Then I just have to
select main_table.primary_key where [my condition]
I do not know if it is the best solution but it works great like that.

Should the auto increment column be the primary key?

I'm confused as to how to assign primary keys.
For example, let's say I have these two tables:
users table where the user_id is unique:
+---------+----------+--------------+
| user_id | username | password |
+---------+----------+--------------+
| 1 | hello | somepassword |
| 2 | world | another |
| 3 | stack | overflow |
+---------+----------+--------------+
posts table where the post_id is unique:
+---------+---------+--------------+
| post_id | user_id | content |
+---------+---------+--------------+
| 1 | 1 | Hello World! |
| 2 | 1 | Another. |
| 3 | 3 | Number 3. |
| 4 | 2 | Stack. |
| 5 | 1 | Overflow. |
+---------+---------+--------------+
Obviously for the users table the primary key should be user_id, but what should the primary key be in the posts table? post_id or user_id? Please explain.
The primary key for the Posts table should also be the auto increment value, post_id, because it's the only thing that uniquely identifies each post, because each post has an id unlike any other. The user_id won't always be unique because the same user could have multiple posts (as far as I know) so it can't uniquely identify the posts. If you need to relate information between the tables you can always do a join on the user_id from both tables, however to identify things with a primary key, the post_id would be your best bet.
Surely, you have this sceneraio:
A user can post several posts.
A post can be posted, logically, by one user only.
Thus, you are dealing with a One-To-Many model.
Once these things are clear to you, you can guess that the primary key of users must appear as a foreign key in posts. This is what you obviously have done already.
Now, wether post_id is enough as the primary key of posts depends on the whole entity relationship model you have (how many other entities do you have and what are their relationship to each others).
However, you will not need, for this specific scenario to combine the foreign key user_id as a part of the primary key of posts.
Note: when you implement your tables, please add the constraints of auto_increment and not null to user_id and post_id.
Let's summerize all this mess in SQL:
Table users:
mysql> create table users (user_id int(2) unique auto_increment not null, username varchar(15) not null, password varchar(20) not null, primary key(user_id));Query OK, 0 rows affected (0.33 sec)
Table posts:
mysql> create table posts(post_id int(2) unique auto_increment not null, user_id int(2) not null, content varchar(50) not null, foreign key(user_id) references users(user_id), primary key(post_id));
Query OK, 0 rows affected (0.26 sec)
Of course it should be user_id because when you use ORM then it will map tables automatically from proper naming of keys
You may refer ORM here : Good PHP ORM Library?

Should I make a FK relation on which table?

I have two tables like:
-- users
+----+--------+---------------------+----------+--------------------+
| id | name | email | password | cookie |
+----+--------+---------------------+----------+--------------------+
-- user_detail
+---------+-----+-------------------+----------------+
| user_id | age | about | birthday |
+---------+-----+-------------------+----------------+
I need to make a relation between users(id) and user_detail(user_id) columns. Now I want to know, should I open user_detail table and create a relation on the user_id column of it (which refers to users(id)) or vice versa?
You are looking for syntax like this:
alter table user_details add constraint fk_user_details_user_id
foreign key (user_id) references users(id);