PRIMARY and FOREIGN key in one field - mysql

I have 3 tables: users, pages and users_pages
Users Table
+----+------+-----
| id | name | ...
+----+------+-----
Pages Table
+----+------+-----
| id | name | ...
+----+------+-----
users_pages table, which says, which user is admin of which page.
+---------+---------+
| user_id | page_id |
+---------+---------+
| 1 | 1 | // means, user 1 is admin of page 1
+---------+---------+
in users_pages table, combination of user_id and page_id is a compound key ( primary key )
Is it possible to define user_id and page_id as foreign key while they both together are primary key?

Yes, Absolutely. You havn't mentioned which relational database you are using, but this is common practice, and allowable in all relational databases i know of.
My attempt at an additional explanation:-
Primary and foreign keys are more like 'theoretical' things rather than hard physical things. When looking at the nuts and bolts, I find it useful to think of only indexes and contraints, not of 'keys' as such
Thinking this way a 'primary key' is actually a combination of two separate things :-
A unique contraint. This checks for and refuses any attempts to
create duplicates.
An index based on the field. This just makes
it much faster to retrieve the record if you use that field to look
it up (select * from table where pkey = 'x')
A 'foreign key' in practice is just a contraint, not much different from the unique key contraint. It checks the records exist in the other table, and refuses any attempts to create records with no corresponding entries in the referred to table.
There is no reason why you cant have multiple contraints on the same field (that it is both unique and exists in another table), and whatever indexes is on the table in no way prevents you from adding any contraint you like. Therefore there is no problem having the same field as part of a primary key and it also have a foreign key contraint.

Related

MySQL primary key that I never select

Quite often I encounter situation like this:
table `user_adress`
+----------+-------------+--------------+---------+
|adress_id | user_id | adress_type |adress |
+----------+-------------+--------------+---------+
| 1 | 1 | home |adressXXX|
| 2 | 2 | home |adressXXX|
| 3 | 3 | home |adressXXX|
| 4 | 1 | work |adressXXX|
| 5 | 2 | work |adressXXX|
| 6 | 1 | second_home |adressXXX|
+----------+-------------+--------------+---------+
If I want to use it, I'm using queries like this:
SELECT `adress` FROM `user_adress` WHERE `user_id`=1;
Seems quite normal, but the thing is, that I use "useless" adress_id column, that has no other purpouse but to be an primary key with autoincrement just for the sake of having an primary key in MySQL table. I never use or need this number. So I figured out that I should not use primary key in my table at all, remove totally adress_id, and set INDEX (without unique) at user_id column. That seems to be good - or am I wrong?
I have some doubts, because as much as I'm reading, everywhere I see advices, that every table should, or even need to have primary key. But why? Perhaps my database is badly designed if I allowed this to happen, but looking on my extreamly simple example table - I can't imagine how this could be the case in every situation, especially in such simple cases. I deffinetly missunderstanded some simple, basic rules about creating tables and properly indexing them - where is the hole in my toughts?
Purely based on your table structure, I would say that your primary key is incorrect.
Instead, it looks like your primary should be:
PRIMARY KEY (user_id, address_type)
You are correct that every table should have a primary key ideally, but primary keys can be over multiple fields.
It is still sometimes easier to have a simple auto-incrementing id as your primary key. The Innodb storage engine will actually do this secretly in an invisible field.
Maybe in your limited example it's not needed, but in a lot of real-world cases it can just make it easier to work with the data. In that sense I would say that having an artificial auto-incrementing primary key is not a best practice from an academic standpoint, but it can be good idea from a 'real world, operational, and MySQL admin' perspective.
There's also ORM systems out there that simply require this (bad as that is).
As is evident in your data the primary key allow the access directly to a single row without any problem or ambiguity .. (expecially for delete or updated)
this is specifically the purpose of a primary key ..
di the fact you could need join this table to others table by user_id
and index (not unique ) on user_id
create index myidx on mytable(user_id)
is really useful for faster join allow a direct access only at the rows related to a single user_id
It's true that a relational database table needs a primary key.
But it all comes down to the definition of a primary key. A primary key is NOT necessarily a single integer column that auto-increments.
A primary key is any column or set of multiple columns that can uniquely identify every row. In your case, the combination of user_id and address_type can do this (as Evert posted already).
So if you make your table like this:
CREATE TABLE user_address (
user_id INT NOT NULL,
address_type varchar(10) NOT NULL,
address TEXT NOT NULL,
PRIMARY KEY (user_id, address_type)
);
Then you can update or delete one specific row at a time like this:
UPDATE user_address SET ...
WHERE user_id = ? AND address_type = ?;
Some people feel that it's more convenient to enforce a convention that every table should have a single integer column as its primary key. They even may insist that the column must be called id for the sake of consistency.
There's some advantage in consistency, but on the other hand, it's kind of brainless to insist on that convention even when it's not helpful.

Do I really need Foreign key when using Pivot table?

let's say, I have a simple database with 3 tables = posts, categories and post_category (which is pivot table).
posts - ID | title | body | created_at/updated_at
categories - ID | name | created_at/updated_at
post_category - post_id | category_id
The primary key is an ID, but I have not specified a foreign key (in posts). Should I specify the foreign key (category_id) as a column in my posts table, or is it okay to use pivot table (post_category) where I already specified the relationship between those 2 tables?
Thanks in advance!
SQL does not require foreign keys to be explicitly declared, particularly with respect to querying tables. Foreign keys enforce relational integrity. That is, they ensure that tables that should refer to each other actually do refer to each other.
That said, MySQL differs from most databases by actually doing something with a foreign key declaration: MySQL builds a secondary index. This index can be quite handy for queries by improving performance.
However, nothing is required about a foreign key relationship.

Copying related tables, without the primary key but preserving the foreign key relationship

I have a badly designed database in hands. It has some tables with are related to each other by fields that were supposed to be foreign keys. For example, if they were to tables, each of them have a primary key, and the second contains the a column which was supposed to be a foreign key, but it is just a filed manually controlled to maintain the relationship.
My problem is finding a way to copy those tables to a second database, which have the same tables, with its own entries.
I tough about a select statement, excluding the primary key, and putting NULL in the first column(the primary key). By doing so, I could dump the records into a CVS and send it to the second DB, which would use automatic increment for the primary key. However, this would be a problem for the second table, as I would not know the new keys.
| Table A | | Table B |
| keyA | | keyB |
| fields | | keyA |

Mysql table design two primary keys vs one

I was wondering which of following is better design.
I've got these tables
users
ID | NAME
Categories
ID | NAME
Which one is better, this:
users_to_categories
CAT_ID | USER_ID
In this case CAT_ID and USER_ID are primary keys
or one primary key
users_to_categories
ID | CAT_ID | USER_ID
only ID is primary key
I assume that you are trying to create a many-to-many relationship between the two tables with a third table titled Users_to_Categories. If so, then CAT_ID and USER_ID would be foreign key pointers to the primary keys in Users and Categories.
All that being said, I would refer to the answer given in this thread (SQL - many-to-many table primary key). I agree with the answer given here, saying that there is really no advantage to creating a new auto-increment primary key when the combination of the CAT_ID/USER_ID can serve as a primary key itself.
Altought both designs are fine, I recommend go for one single field for key approach.
It's easier for doing queries.
It's also easier when you want to change some details records from a header o parent table to another, just change the parent foreign key.

MySQL: how should I draft this database?

I'm designing a plugin for a high traffic forum. What I am doing is listing related threads using a search API, which has a maximum of 800 searches per day
What I'm wanting to do is create a database to store the results, cache them for one day so it will be used instead of the API.
Would a table layout such as this be optimal:
Table:
+---------+-----------+------------+
| threadid | relatedids | dateentered |
+---------+-----------+------------+
| 129314 | 1124;2144 | 1234567890 |
| 124129 | 1251;1241 | 1234567890 |
| 185292 | 1151;5125 | 1234567890 |
+----------+-----------+-----------+
related urls being thread ID's too, separated by colons. I am not too much an expert in SQL so I do not know if setting index to threadID is a good idea, or what!
You clearly have a one-to-many relationship here, so you should use 2 tables instead of a separator, something like (MySQL syntax, assuming there is also a table named thread) :
create table search_thread (
thread_id int,
date_entered datetime,
PRIMARY KEY (thread_id)
FOREIGN KEY (thread_id) REFERENCES thread(thread_id));
create table search_results (
thread_id int,
result_id int,
PRIMARY KEY (thread_id, result_id),
FOREIGN KEY (thread_id) REFERENCES search_thread(thread_id),
FOREIGN KEY (thread_id) REFERENCES thread(thread_id).
FOREIGN KEY (result_id) REFERENCES thread(thread_id));
The benefit of this model is that it's open to extension, meaning you can add an attribute specific to the related threads. Also, you can perform some queries that are not possible with your approach, like finding how many threads are related to another (in both directions).