I'm a total newbie and I'm trying to do a mysql database, using xampp for linux 1.8.1.
I want to make a relation between two tables A and B. For what I know foreign keys create a bijection, or a one-to-one relation. I must not have such a strict relation, so I only created a column inside table A that stores the id of table B.
Is this correct? There's not a way to enforce it? I mean, this way you could delete a row of table B that is referenced in table A. you could store a value inside A that doesn't correspond to an id of any row of B. How to prevent this?
The main problem for me is to prevent deletion of a row of table B if the row id is referenced by a row of table A.
create table table_b (
b_id integer primary key
);
create table table_a (
b_id integer primary key references table_b (b_id)
);
insert into table_b values (1);
insert into table_a values (1);
The following statement will fail.
delete from table_b where b_id = 1;
If you'd built that with PostgreSQL, the error message would say
ERROR: update or delete on table "table_b" violates foreign key constraint "table_a_b_id_fkey" on table "table_a" Detail: Key (b_id)=(1) is still referenced from table "table_a".
That structure gives you a "1 to 0 or 1" relationship between the two tables. For "1 to 0 or many", add one or more columns to table_a's primary key.
create table table_b (
b_id integer primary key
);
create table table_a (
b_id integer references table_b (b_id),
checkout_date date not null default current_date,
primary key (b_id, checkout_date)
);
That structure will let table_a store multiple rows for one value of b_id, but each of those rows must have a different checkout_date.
I think you allways need an primarykey for this, or you write a trigger who checks the consistence of ID from B when a change occurs.
I dont know that it would be possible without a trigger or a constraint ...
Related
I want to store if two events are combinables.
It's a n to n relation, so I need to have a pivot table with these constraints :
PK(event_1, event_2) = PK(event_2, event_1)
event_1 is a reference to id in table events
event_2 is a reference to id in table events
I tried to create my table with this query :
event_id_1 INT UNSIGNED,
event_id_2 INT UNSIGNED,
cumulative_place INT,
PRIMARY KEY(event_id_1,event_id_2),
FOREIGN KEY(event_id_1)
REFERENCES events(id)
ON DELETE CASCADE,
FOREIGN KEY(event_id_2)
REFERENCES events(id)
ON DELETE CASCADE
);
Following MySQL Documentation
I have some questions about that :
Is it optimized for search query, for example if i want all events that are combinables with event1 whatever if event1 is in the first column or second ?
Do I need to manually manage primary key for INSERT and UPDATE or MySQL do the job ? for example can I just insert cumulative place number for (event1, event2) primary key and if row is store as (event2, event1) this works as well.
Sort the pair.
INSERT ...
VALUES (
LEAST("e1", "e2"),
GREATEST("e1", "e2"),
...)
Similarly, sort the pair when doing a lookup. That way you have 1 row, not 2, and you don't have to look for both orders.
Assume I have two tables, a and b. Table a contains an optional FOREIGN KEY reference to b. Table b does not have a FOREIGN KEY reference to table a, and should not. The reason for this is that table a is not the only table that might reference a row from table b: tables x and y might also reference b, and more tables might be added in the future which might reference a row from b.
So, every row from table b has exactly one "owner row" which may belong to a, x, y, or potentially any one of a number of other tables.
Now, if a row from table b is deleted, I want it to set the foreign key reference to itself from a, x, or y, if there is one, to null. I know I can accomplish this using ON DELETE SET NULL in the foreign key constraints for a and the other tables, so that is taken care of.
However, if the "owner row" is deleted, regardless of whether that row lives in a, x, y, or whatever, I want the corresponding row from b to be deleted as well. This is what I'm not sure how to do.
In short:
a references b. This is an optional reference, not all as will have a b.
(x, y, and other tables also have similar relationships to b)
b does not and should not reference a or any of those other tables.
If I delete from a and if the given a has a corresponding b, that b should be deleted.
If I delete from b, and any other table contains a reference to that b, the reference should be set to null.
How would I accomplish this?
create table a
( ...
, b_id bigint default null comment 'fk ref b.id'
, constraint a_b_id foreign key (b_id) reference b (id) on delete set null
, ...
) engine=innodb
tables x and y are defined similarly, with nullable foreign key columns
create table x
( ...
, b_id bigint default null comment 'fk ref b.id'
, constraint x_b_id foreign key (b_id) references b (id) on delete set null
, ...
) engine=innodb
and
create table y
( ...
, b_id bigint default null comment 'fk ref b.id'
, constraint y_b_id foreign key (b_id) references b (id) on delete set null
, ...
) engine=innodb
When a row is deleted from b, then any values of b_id column in any of the three tables references the deleted row, those values will be change to NULL.
There is no declarative constraint in MySQL that will accomplish 3.
"If I delete from a and if the given a has a corresponding b, that b should be deleted."
We might be able to accomplish this with a TRIGGER, but we get into some issues with which tables can be referenced by statements in the trigger. This would probably better be handled with the application logic, rather than a database rule or trigger.
If I was going to attempt a trigger, then something like
DELIMITER $$
CREATE TRIGGER a_ad
AFTER DELETE ON a
FOR EACH ROW
BEGIN
DELETE FROM b WHERE b.id = OLD.b_id ;
END$$
DELIMITER ;
(I'm not sure that this will be allowed, or if an error is going to be thrown... consider
table b
---------
row id=42
and
table a
-------
row id=2 b_id=42
row id=3 b_id=42
consider this SQL statement
DELETE FROM a WHERE a.id IN (2,3);
The delete of row id=2 is going to fire the "after delete" trigger; and that will perform a DELETE on b, the foreign key will find the row id=3 referencing, and attempt to set the b_id column to NULL... but that row might already be locked by the initial DELETE statement... I'm just not sure what will happen in this scenario; and we run into some limitations and restrictions on triggers (like against modifying rows in tables that are referenced in the statement that fires the trigger, )
I'm working on a Django application and created a new table tblA which has a foreign key that is linked to the primary key of tblB.
Now tblB already has several entries (and thus several primary keys in it already).
I want to run an SQL query that will create a new row for every primary key in tblA inside tblB with the corresponding foreign key copied and default values of all other columns in tblB inserted in the rows.
I hope I was clear enough!
you have forgot to paste your table structure .. I am considering as below-
tblA
(
aCol1_PK (primary key),
acol2_desc (description)
)
as of now just take an example of two columns only.
Now for table B
tblB
(
bCol1,
bCol2,
bCol3_FK (foreign key)
)
Now let say you have default values as -
bCol1 - "B_Col1_default_val"
bcol2 - "B_Col2_default_val"
for this situation if you want to insert rows for p_key from table A which is not present in Table B, you can try below query -
insert into tblB(col1,col2,col3)
( select 'b_col_default_val','b_col_default_val', acol1_pk
from tbla a
where a.acol1_pk not in ( select b.bcol3_fk from tblb b))
if you want to insert one row for all the primary key value present in table A then -
insert into tblB(col1,col2,col3)
( select 'b_col_default_val','b_col_default_val', acol1_pk
from tbla a )
I hope it will help you ..
if you require any clarification you can ask/comment.
I'm writing an application that requires all users to access data on a central database using MySQL, and I was wondering something.
Let's say I have this setup.
CREATE TABLE A
(
id INT PRIMARY KEY AUTO_INCREMENT,
data INT NOT NULL;
);
CREATE TABLE B
(
id INT PRIMARY KEY AUTO_INCREMENT,
a_id INT,
FOREIGN KEY (a_id) REFERENCES A(id) ON DELETE SET NULL
);
Now, the way I want this set up is, table A must ALWAYS be referenced by a row in table B. However, a row in table B may or may not reference a row in table A. The relationship is 1:n in that multiple rows in table B can reference a single row in table A. I am just wondering if it is possible to have the MySQL database automatically delete a row in A if it is no longer referenced by any row in table B.
The idea here is that I can simply set a_id in table B to NULL and have the database cleanup whatever is left. I guess that's similar to Java garbage collection now that I think about it. If there is no key to automatically enforce the constraint, would a trigger executed after an update work?
EDIT: Adding in the additional relationship constraint.
Run the following query at a specific interval:
DELETE tableA
FROM tableA LEFT JOIN tableB B ON A.id = B.a_id
WHERE B.a_id IS NULL;
Or, to maintain real-time consistency, you could create an OnChange trigger on tableB that performs similar.
Is there a reason for the table structure you are using? The way you are using foreign keys looks backwards to me. Instead of placing your key in table B, you could move it to table A.
This would give you a structure that looked more like:
tableA columns tableB columns
id
b_id id
[values] [values]
fk: a.b_id=b.id
A record added to table A would require a corresponding field in table B, but B would be free to have no values in table A. Then if you wanted to clean out the values in table A, you could simply use:
delete from tableA where b_id=[recordIdToNull];
You could even set A's foreign key up to cascade actions taken on B, so any values deleted from B would also delete the corresponding rows in A.
I have 2 tables: let say table 1 (userid, username, password) and table 2 (userid, a, b, c).
table 1 has a userid field (primary key), table 2 also has userid (references table 1).
If I do an insert statement, to add a row to table 2, how does table 2 generate the userid field?
Edit:
I want to insert things into table 2 where the userid in table 2 MUST match userid in table 1 - what constraints do I need to set up
The database doesn't understand the relationship between table1 and table2 unless you explicitly specify it. You can use SQL foreign keys if you are using a database engine the supports them (InnoDB).
CREATE TABLE table1 (
userid INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255) UNIQUE NOT NULL,
password VARCHAR(255) NOT NULL);
CREATE TABLE table2 (
rowid INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
userid INTEGER NOT NULL
REFERENCES table1(userid)
ON DELETE CASCADE ON UPDATE CASCADE
-- other columns here
);
The REFERENCES option will tell the database engine that table2.userid requires that a row exist in table1 such that table1.userid = table2.userid. The ON DELETE and ON UPDATE clauses will cause the deletion of a row in table1 to automatically delete/update rows in table2.
You cannot create a row in table2 until you have created a row for the user in table1. The row in table1 will auto-generate the userid. When you insert into table2, you will explicitly include the user id from table1 to establish the linkage between the rows.
If the userid field on table2 is not autoincrement then you have to provide the value or the insert will fail.
If you have defined userID in table2 as foriegn key constraint, then you will need to have the corresponding userID in the table1 as reference when inserting rows to table2, else if you have not defined any such constraints, then it will not matter.
Keep in mind, if the constraint is defined, then table2 will not generate ID by itself. It would require the ID to be present in the table1 column which is referenced.
If username and password is not null then don't insert in tabel 1 and give error