Table Name : Members (member_id PK), Member_Articles (articles_id PK)
I want to design, like below:
Member can write Articles, and there should be strong relationship. Without member_id, Member_Articles table can't insert any data.
Sometimes in the future, some member_id [e.g) member_id : 7] must be deleted.
However, some articles which are written by some member_id [e.g) member_id : 7] must remain in the table.
I tried PK, FK relationship. However, as you know, I had to delete first Articles before delete Member.
How can I implement this situation?
While defining relationship set null on delete to the FK, and keep an extra column let say deleted_member_id and set it default with null if you delete the user programmatically or with the help of triggers set the deleted_member_id with the memeber_id and the delete will set null to memeber_id
Better Approach (in my view)
In my view the better approach could be setting flags into your eahc table,
For example: Create a column status with default 1 when you delete any data rather then of deleting them just set the status to 0, similarly in all your SELECT add an extra condition WHERE status = 1
make member_id not null in your member_article table, and use on delete no action, to retain the articles.
Related
Let's assume I have 2 tables: foo and bar.
In third table I want to store different kind of data, however every row will have a reference to either foo OR bar.
Is it correct if I create 2 NULLable foreign keys - foo_id and bar_id - in the third table, or is it againts database design principles?
Basically, I thought all the time that foreign keys need to ALWAYS have a "parent", so if I try to e.g. INSERT a row with no primary key matched (or, in this case, with a foreign key set to NULL), I will get an error. Nullable FK-s are new to me, and they feel a bit off.
Also, what are the alternatives? Is it better to create separate tables storing single reference? Isn't this creating redundancy?
Linking tables?
Help.
A nullable FK is "okay". You will still get an error when you try to insert a non-existing parent key (it is just NULL that is allowed now).
The alternative is two link tables, one for foo and one for bar.
Things to consider:
Link tables allow for 1:N. If you don't want that, you can enforce it by primary key on the link table. That is not necessary for the id column solution (they are always 1:N).
You can avoid columns with mostly NULL values using link tables. In your case, though, it seems that you have NULL for exactly half the values. Probably does not qualify as "mostly". This becomes more interesting with more than two parent tables.
You may want to enforce the constraint that exactly one of your two columns is NULL. This can be done with the id column version using a check constraint. It cannot be done with link tables (unless you use triggers maybe).
it is depend on the business logic of the program. if the foreign key field must has a value , it is bad to set it null-able .
for example .
a book table has category_id field which the value is reference from bookCategory table.
each record in book table must has category . if for some reason you set it as nullable . this will cause some record in book table with category_id is null.
the problem will show up in report. the following 2 query will return different total_book
select count(*) as total_book from book;
select
count(*) as total_book
from
book
inner join bookCategory
on book.category_id = category.id
my advice is don't use null-able unless you expect value and no-value . alot of complex system that sometime have value different from one report and another , usually is cause by this.
I need to add a Foreign Key to a table that already exists and is populated with data that would contain invalid Foreign Key Values. (MYSQL)
I know there are several questions along these lines, but I can't seem to find any that answer my scenario.
Table and Data Structure
"GblTable" contains an "Org" field that needs to become a FK of the Org table. The Org table has a PK field called "number".
Currently, the GblTable contains non-existent Org numbers (ie. If the Org table has rows with PKs 1,2, and 3, GblTable might have rows with Org as 4 or 5). While this is the case, I cannot apply the constraint to reference GblTable.org to Org.number.
I believe the best approach for this particular situation will will be to set the FK field in those rows to NULL before I apply the constraint. NULL is a valid GblTable.Org value for the program, so this would achieve an acceptable outcome.
What I Have so Far
I want to set all GblTable.Org values to NULL where they do not match a valid Org.Number.
In pseudocode:
set GblTable.ORG to NULL
where the GblTable.number is one of the following:
( select all GblTable.numbers where the GblTable.Org does not match an existing Org.Number )
In Sql, but I get the error "You can't specify target table 'GblTable' for update in FROM clause":
update GblTable set Org=NULL
where number IN (
select number
from GblTable
where Org NOT IN (select number from Org)
)
What's the best way to achieve my requirement?
You don't need the extra level of subquery:
update GblTable set Org=NULL
where Org NOT IN (select number from Org)
our database contain 5+ tables
user
----------
user_id (PK) int NOT NULL
name varchar(50) NOT NULL
photo
--------
photo_id (PK) int NOT NULL
user_id (FK) int NOT NULL
title varchar(50) NOT NULL
comment
-------
comment_id (PK) int NOT NULL
photo_id int NOT NULL
user_id int NOT NULL
message varchar(50) NOT NULL
all primary key id's are unique id's.
all data are linked to http://domain.com/{primary_key_id}
after user visit the link with id, which is unique for all tables.
how should i implement to find what table this id belongs to?
solution 1
select user_id from user where user_id = {primary_key_id}
// if not found, then move next
select photo_id from photo where photo_id = {primary_key_id}
... continue on, until we find which table this primary key belongs to.
solution 2
create object table to hold all the uniqe id and there data type
create trigger on all the tables for AFTER INSERT, to create row in object table with its data type, which was inserted to a selected table
when required, then do select statement to find the table name the id belongs to.
second solution will be double insert. 1 insert for row to actual table with complete data and 2 insert for inserting unique id and table name in object table, which we created on step 1.
select type from object_table where id = {primary_key_id}
solution 3
prepend table name + id = encode into new unique integer - using php
decode id and get the original id with table name (even if its just as number type)
i don't know how to implement this in php, but this solution sounds better!? what are your suggestion?
I don't know what you mean by Facebook reference in the comments but I'll explain my comment a little further.
You don't need unique ID's across five DB tables, just one per table. You have couple of options how to create your links (you can create the links yourself can you?):
using GET variables: http://domain.com/page.html?pk={id}&table={table}
using plain URL: http://domain.com/{id}{table}
Depending on the syntax of the link you choose the function to parse it. You can for example use one or both of the following:
http://php.net/manual/en/function.explode.php
http://www.php.net/manual/en/function.parse-url.php
When you get the simple model working you may add encoding/decoding/hashing functions. But do you really need them? And in what level? (I have no experience in that area so I'll shut up now.)
Is it actually important to maintain uniqueness across tables?
If no, just implement the solution 3 if you can (e.g. using URL encoding).
If yes, you'll need the "parent" table in any case, so the DBMS can enforce the uniqueness.
You can still try to implement the solution 3 on top of that,
or add a type discriminator1 there and you'll be able to (quickly) know which table is referenced for any given ID.
1 Take a look at the lower part of this answer. This is in fact a form of inheritance.
I'm developing a helpdesk-like system, and I want to employ foreign keys, to make sure the DB structure is decent, but I don't know if I should use them at all, and how to employ them properly.
Are there any good tutorials on how (and when) to use Foreign keys ?
edit The part where I'm the most confused at is the ON DELETE .. ON UPDATE .. part, let's say I have the following tables
table 'users'
id int PK auto_increment
department_id int FK (departments.department_id) NULL
name varchar
table 'departments'
id int PK auto_increment
name
users.department_id is a foreign key from departments.department_id, how does the ON UPDATE and ON DELETE functions work here when i want to delete the department or the user?
ON DELETE and ON UPDATE refer to how changes you make in the key table propagate to the dependent table. UPDATE means that the key values get changed in the dependent table to maintain the relation, and DELETE means that dependent records get deleted to maintain the integrity.
Example: Say you have
Users: Name = Bob, Department = 1
Users: Name = Jim, Department = 1
Users: Name = Roy, Department = 2
and
Departments: id = 1, Name = Sales
Departments: id = 2, Name = Bales
Now if you change the deparments table to modify the first record to read id = 5, Name = Sales, then with "UPDATE" you would also change the first two records to read Department = 5 -- and without "UPDATE" you wouldn't be allowed to make the change!
Similarly, if you deleted Department 2, then with "DELETE" you would also delete the record for Roy! And without "DELETE" you wouldn't be allowed to remove the department without first removing Roy.
You will need foreign keys if you are splitting your database into tables and you are working with a DBMS (e.g. MySQL, Oracle and others). I assume from your tags you are using MySQL.
If you don't use foreign keys your database will become hard to manage and maintain. The process of normalisation ensures data consistency, which uses foreign keys.
See here for foreign keys. See here for why foreign keys are important in a relational database here.
Although denormalization is often used when efficiency is the main factor in the design. If this is the case you may want to move away from what I have told you.
Hope this helps.
Been reading the tutorial How to handle a Many-to-Many relationship with PHP and MySQL .
In this question I refer to the "Database schema" section which states the following rules:
This new table must be constructed to
allow the following:
* It must have a column which links back to table 'A'.
* It must have a column which links back to table 'B'.
* It must allow no more than one row to exist for any combination of rows from table 'A' and table 'B'.
* It must have a primary key.
Now it's crystal clear so far.
The only problem I'm having is with the 3rd rule ("It must allow no more than one row to exist for any combination").
I want this to be applied as well, but it doesn't seem to work this way.
On my test instance of mysql (5.XX) I'm able to add two rows which reflect the same relationship!
For example, if I make this relation (by adding a row):
A to B
It also allows me to make this relation as well:
B to A
So the question is two questions actually:
1) How do I enfore the 3rd rule which will not allow to do the above? Have only one unique relation regardless of the combination.
2) When I'll want to search for all the relations of 'A', how would the SQL query look like?
Note #1: Basically my final goal is to create a "friendship" system, and as far as I understand the solution is a many-to-many table. Suggest otherwise if possible.
Note #2: The users table is on a different database from the relations (call it friendships) table. Therefore I cannot use foreign keys.
For the first question:
Create a unique constraint on both
columns
Make sure you always sort the columns. So if your table has the
colummns a and b than make sure
that a is less than or equal to
b
For the second question:
SELECT
*
FROM
many_to_many_table
WHERE
a = A or b = A
It sounds like you want a composite primary key.
CREATE TABLE relationship (
A_id INTEGER UNSIGNED NOT NULL,
B_id INTEGER UNSIGNED NOT NULL,
PRIMARY KEY (A_id, B_id)
);
This is how you setup a table so that there can only ever be one row that defines tables A and B as related. It works because a primary key has to be unique in a table so therefore the database will allow only one row with any specific pair of values. You can create composite keys that aren't a primary key and they don't have to be unique (but you can create a unique non-primary key, composite or not), but your specification requested a primary key, so that's what I suggested.
You can, of course, add other columns to store information about this specific relationship.
Ok WoLpH was faster, I basically agree (note that you have to create a single constraint on both columns at the same time!). And just to explain why you collide with the rules you mentioned: Typically, A and B are different tables. So the typical example for n:m relations would allow entries (1,0) and (0,1) because they'd be refering to different pairs. Having table A=table B is a different situation (you use A and B as users, but in the example they're tables).