How to make multiple foreignkey value in 1 column? - mysql

how to make the output like this? From 4 tables (rate, cost, tools, car)
|`RateID` | `Costing` | `Toolsfk` and `CarFK` |
|---------------------------------------------|
| 1 | 1000 | 1004 |
| 2 | 2000 | 2003 |
this is the tables
i want to 2 or more Foreignkey in 1 column, should I use CONCAT? but, as I know, CONCAT is for output only. So, what if for output and input data in database? just use Insert?

polymorphic association is not possible, polymorphic association means single column has more than one foreign key for different tables. foreign key can target only one table at a time, a single column foreign key can't refer more than one tables, if u want to refer more than one table using single column then there are two ways..
1- creating identical table of referenced table
2- use two columns in a table, one column refer tools table and one column refer car table
below is a link from where you can take refrence
(Possible to do a MySQL foreign key to one of two possible tables?)

Related

Why do many to many relation use all the key from previous table?

While using mysql workbench and for designing database using designer the relation tool uses a third table to form a many to many relation between 2 tables.
I have 3 tables
TABLE1
TABLE2
TABLE3
TABLE2 has foregin key from primary key of TABLE1,having a many to one relation
TABLE2 and TABLE3 are related using a many to many relation,
as soon as I create the relation
a new table TABLE3_has_TABLE2 is created with all the key from TABLE2(primarykey of table2 & foreign key of table1) and TABLE3 (primary key of table3).
Now,
why is there foreign key of table1.?
Even if i remove I will be able to query data from table1 and table3 using table2 as intermediate, so is it good to have this kind of relation or avoided?
For Example in below diagram
This is a geographical distribution of location, on right side it shows the hirarchy.
Now,
Table1(Zone) is the primary table i.e Zone
Table2(state) is related to table1 using zone_id
Table3(division) is related to table2(state) using state_id & zone_id of table1(zone)
Question: Should this zone_id column be in the table3 or not?
similarly table4 contains all the previous key columns of table3.
Strictly from a denormalization point-of-view, the DIVISION.STATE_ZONE_ID isn't required.
Since you can get the ZONE_ID from the DIVISION by joining STATE on the state_id.
And it's the same with the division_state_state_id & division_state_zone_id in DISTRICT.
Having the division_division_id is enough to join DIVISION, then STATE, then ZONE.
However, what if you would remove those 'extra' fields?
Then a SQL always needs to go through that cascade of joined tables to get the ZONE.zone_name.
So there's an advantage that by having those 'extra' fields, it becomes possible to JOIN directly to the ZONE table. Which can simplify/speed up certain popular queries.
The disadvantage is that it becomes harder to assure referential integrity.
Because for example, you could assign a different zone_id to a DIVISION.state_zone_id than the STATE.zone_id you can get via DIVISION.state_state_id.
It is best practice in relational models to avoid many-to-many relationships. Workbench usually compensates for user trying to do that as you have seen.
Let us use an example (or check the tl;dr), where there are two identified entities; buyers and hardware items. Some people buy 1 item, others buy more than one. The thing is, that same item can be bought by many people. So the buyer table has Mr. A buying nails. Simple enough to record in one row. But lo' and behold, he ups and gets another item! How do we show that he buys another item?
One way is by adding another attribute to the table (say "item_number_two"). But then he gets another! We can't keep going adding attributes like that. Databases were designed more for vertical addition of records, rather than horizontal addition of attributes (to give a visual picture). There is a longer explanation but you should read up, or probably might figure it out after reading this.
Another way is to re-enter a record for Mr. A and then put the ID of another item in that column, showing that he bought two items (not really "he" from a database stand-point, it's two different people!).
A better method would be to create a table that consists of the unique identifiers found in the original tables (just one per table may be necessary). This is called an intermediary table. The original tables themselves do not have foreign keys from the other table.
This is where the concept of a composite key comes in. It means that two or more candidate keys are used to uniquely identify a record rather than just one. This is how it works:
Person Table:
| person_ID | person_Name |
| P0001 | Mr. A |
| P0002 | Mr. B |
| P0003 | Mr. C |
| P0004 | Mr. D |
Cat Table
| item_ID | cat_Name |
| I0001 | Nails |
| I0002 | Screws |
| I0003 | Hammers |
| I0004 | Power-Saw |
Intermediary table
| person_ID | item_ID |
| P0001 | I0001 |
| P0001 | I0002 |
| P0001 | I0003 | //Shows that person 1 bought more than one item
| P0002 | I0004 |
| P0002 | I0001 | //Shows that an item has been bought by more that one person
So this new table matches a record of one table(through the use of a primary key) to a record of another. The only thing that will ever be repeated is one of the two ID's. A unique record is made as long as no two combinations are repeated.
tl;dr - Having tables mapped in a many to many relationship inevitably wastes space in the DB when entering records, as new records of the same data have to be made to show a small difference (adding no real value in proportion to the space). Another issue is that it causes more calculations than necessary when a query is made, wasting time and space. Or the results returned may just be plain wrong...
EDIT:
If you have tables A and B having a many-to-many relationship, do the following as an alternative. Create a table C. Take the primary keys from table A and B and place them in tables C. In table C they both exist as primary and foreign keys. This would mean the following relationship is created.
| Table A |-----------<| Table C |>------------|Table B|
Table A and B are linked through C.
Sample query:
SELECT C.itemID FROM A, C WHERE A.personID = P0001 AND A.personID = C.personID;
This query will return all ID's of the items bought by the person with an ID of P0001. Records must match the condition of having a personID of P0001, but the record selected must have that matching ID in Table C (the intermediary table). An extended query could be to take the item names from the Table B. Each attribute in C has a recorded value that corresponds to a value of a key in either Table A or B, meaning that a query can be run to pull other info, where the value in Table C is = to the values in Table A/B (depending on which one you want).

Insert row only if it doesn't exist already in MySQL

I have a table table with two columns (idA and idB). The table assigns Bs to As, like this:
A | B
1 | 4
3 | 2
3 | 4
4 | 1
4 | 3 ...
So one A can have multiple Bs and thus shows up in more than one row. Hence, the table cannot have a primary key and I cannot use a unique column.
Is there a way to insert new rows only if an equal value pairing does not already exist, all in one query?
I tried REPLACE INTO and INSERT IGNORE INTO as mentioned here, but both seem to work for tables with primary keys only.
You can add a primary key! It just has to be over two columns and not just one.
ALTER TABLE your_table
ADD PRIMARY KEY(idA, idB)
That will make sure you only have unique records for both columns.

Is it possible to have a MySQL column containing multiple values as foreign keys?

I am learning MySQL and have MariaDB installed in Fedora 19.
I have a scenario where I require a column to contain multiple values in order to reduce possible redundancy of column allocation.
In the example below, is it possible to have each value in the tags column of the log table reference the tag_id column in the tags table?
users
user_id |
1 |
activities
activitity_id |
1
log
user_id | activity_id | tags
1 | 1 | 1,3,5 # multiple foreign keys?
tags
tag_id |
1 |
2 |
3 |
4 |
5 |
If it is not possible, could anyone provide the logic for the most feasible solution based on the data scenario above?
Similar Questions:
Are multiple foreign keys in a single field possible?
MySQL foreign key having multiple (conditional) possible values
it is possible to reference one column as multiple foreign keys
If you do not wish to make up a "middle man" table for linking the two tables you can have a comma separated value in the field, you would just need to use the find_in_set mysql function when doing queries
USING find_in_set
SELECT
log.user_id, log.activity_id, log.tags,
GROUP_CONCAT(tags.name) as taggedNames //This assumes there is a field called `name` in tags table
FROM
log
LEFT JOIN tags
ON
FIND_IN_SET(tags.tag_id,log.tags)
GROUP BY
log.activity_id
GROUP_CONCAT will group together a field and separate them by a deliminator, default is ,

Mysql Relational Database duplicate with different keys

I'm trying to correct a relational db for a month, but i cant find efficient solution.
Hier is my problem:
I have like 534 M rows Relational Db with lots of foreig keys(30).
I can handle normal duplicates with union...group by...havin count(*)=1 by inserting, but there are also duplciates with different keys.
example:
table 1
id | key1 | value
1 | 11 | a1
2 | 22 | a1
table 2
key1 | value
11 | a2
22 | a2
Foreign key table1(key1) references table2(key1)
I'm trying to find, remove duplicate , correct the parents.
I have tried 3 different ways,
1: PHP Script,Arrays
export tables (dump) --> array_unique, find duplicates, correct the parents array --> import tables
Its pretty fast, but need 80GB Memory, which could be problem in the future
2: PHP Script,SQL Query
exporrt tables(dump) --> find duplicates --> send queries to parent table
No need memory, but the tables are really big and 5 queries take 1 second, 50 M duplicates would take days, months, years
3: ON DUPLICATE UPDATE KEY: I added one column 'duplicate' to store duplicate keys and I defined all columns except key as unique key,
insert.... on duplicate update concat(duplicate,';',VALUES(key)).
But some tables has more than 1 key and sometimes I should define 24 column as unique index and memory problem again
I hope I could explain my problem. Do you have any idea ?
Why don't you simply create a unique key on column. Just use "Ignore" keyword it will remove the duplicate records.So your query will be something like: ALTER IGNORE TABLE testdb.table1
ADD UNIQUE INDEX column1 (column1 ASC) ;

Primary key on 2 tables

i have two tables, one 'master' and one 'child' table.
Each table has a field named 'ProductNo', which is defined as PRIMARY KEY and UNIQUE.
Is it possible to define the field 'ProductNo' in the table 'child' and the same field in table 'master' as PRIMARY + UNIQUE together?
master:
ID | ProductNo
child:
ID | MasterID (FK on master.ID) | ProductNo
Relation >> 1 (master) : n (child)
example data:
master:
1 | 1234
2 | 4567
child:
100 | 1 | 3333
101 | 1 | 4444
102 | 2 | 5555
103 | 1 | 1234 <----- NOT ALLOWED! PRODUCT NO ALREADY EXISTING IN TABLE `MASTER`
104 | 2 | 1234 <----- NOT ALLOWED! PRODUCT NO ALREADY EXISTING IN TABLE `MASTER`
It is needed to check on inserting/updating table 'child' if 'ProductNo' already exists in table 'master'.
How can I define it?
Or am I needed to create a trigger for this?
TIA Matt
no, there is no such thing as composite PKs among tables.
Just for data consistency, if the Ids are the same, you should add a FK from child to the master.
To solve your problem, a trigger with a check like this:
if exists (select 1 from master where prodcutId=new_productId)
would be a good idea
EDIT:
actually the best idea is to have only one table called product with a ID and a masterID field with a relation to itself. The way you have today Im pretty sure that you have a lot of duplicate data and you are stuck with 2 levels on hierarchy.
(Original answer) You can declare a foreign key from master to child, even if that foreign key points to the primary key of child. This would be a one to zero-or-one relationship, and is not that uncommon. A row cannot exist in child without a matching row in master already being inserted, but a row can exist in master without a matching child row. Your inserts therefore need to happen in the order master then child.
(Edited in light of question edit) HOWEVER, in your case, the column you are referring to looks like it should not actually be the primary key of either table, but rather you have a separate primary/foreign key, and the column in question needs to be unique across the two tables, which has become clear now you've edited some sample data into your question. In this case, you'd be best to use a trigger on both tables, to check existence in the other table and prevent the insert/update if the ProductNo already exists.
Just as #DavidM said, it can be done, but it seems you are with some modelling issues. First, if you have a natural primary key ProductNo, why do you define a surrogate ID? The other thing you might consider is to combine these two tables into a single one (as might make sense for most of 1-to-1 cases).
Are you sure you need the two tables?
Keep just one, having productID plus parentID.
Then productID can be a primary key and auto increment, while everything having a parentID other than null (f.keyed to the same table) would be a child item.
You can add a column named ProductNo in child table and add a foreign key reference to the parent table.