Foreign Keys: Multiple insertions reference one key - mysql

I have created 4 different tables, with one value in each:
A1(A1_ID), A2(A2_IDFK), A3(A3_IDFK), and A4(A4_IDFK).
They all have foreign keys which relate to each other. The data flow is such:
A1 -> A2 -> A3 -> A4
In order to insert data in A4, one would had to already have inserted data
into A1, A2, and A3 respectively.
Is there any way to have new insertions reference one foreign key?
Ex: A4 FK values of 2,3 and 4.. and so on, all point to A3 FK's value of 8.
How can one continuously insert new data into AF4 (A4_IDFK) and have that data and all new entries be equal to a single A3 (A3_FKID) entry?
A3_IDFK would have the same value, regardless of what the other values of A4_IDFK are.

Related

Many to many relationship defaulting to "all"

I have to tables A and B. I also have an associative table A_B that stores the relationships between table A and B. In table A, there are records that I want to relate to all records in table B (even records that can be added in the future).
Let's say I have A1, A2, A3 and B1, B2 and B3.
I want A1 related to B1 and B3
A2 related to B1 and B2
A3 related to all Bs
Then the A_B table will look like:
A1, B1
A1, B3
A2, B1
A2, B2
A3, B1
A3, B2
A3, B3
If I add B4, I will need to add a new record in A_B table to relate it to A3. How can I define "A3 is related to all Bs" without requiring the A_B table? I was thinking in adding a flag in A (a boolean is_related_to_all) but I think it looks wrong (I may end up with hundreds of is_related_to_all = false)
Is there any way of doing this using relationships?
EDIT
To add a bit of more of context:
Table A stores partners and Table B stores websites. Some partners are related to specific websites and some partners are related to all websites (and some partners may be not related to any website).
If you add the Boolean, it will no longer be a traditional many:many mapping table. Probably FOREIGN KEYs will no longer work.
But you can certainly code for it -- however, you would need to have special code a la:
if flag is set, do ...
else do ...
That may turn into a UNION of two SELECTs. Or it may turn into something else. (I can't predict without understanding the use of this mapping table.)
Meanwhile, those partners that are related to no website can probably be handled by not being in the table at all. (This may need a 3rd if/then and/or UNION.)
You could consider a trigger on table B:
DELIMITER ;;
CREATE TRIGGER relate_all_b_to_a3
AFTER INSERT ON B
FOR EACH ROW
BEGIN
INSERT INTO (A_B)
VALUES ('A3', NEW.B)
ON DUPLICATE KEY UPDATE B=B;
END;;
DELIMITER ;
Well, if this thought is too weird - dont mind it - but you could roll it up the other way around. You could hava a A_HASNOT_B (a more intelligent name would be better) table. This way, new records in B will always be assigned to all records from A. You would simply have to invert a UX based user selection before storing relations.
So in your scenario, there would be the following records:
A | B
=======
A1 | B2
---+---
A2 | B3
Depending on your scenario/usecase, this could either be elegant or completely stupid. If you end up having only a few relations, this is a bad solution, in this case, i would go for reaanbs solution (trigger). If you think most records of type a will be assigned to type b it could do the job in a very simple way.
I would suggest a different approach from those of the other solutions. Looking at the problem from a more abstract point of view, you have two "subclasses" of A: those related with one or more B (let's call them A_relatable) and those with are always related to all B (let's call them A_related).
So I will suggest to represent your situation with five relations:
A(attributes of A)
B(attributes of B)
A_relatable (only primary key of A as foreign key, also primary key)
A_related (only primary key of A as foreign key, also primary key)
A_B(foreign key of A_relatable, foreign key of B)
In this way all the constraints can be verified, and you can define a few stored procedure to simplify the management of the data.

A very complicated SQL query that probably involves some JOINs and updating, deleting certain columns in a table

I am not sure if this can be accomplished in one query but since I am new to SQL I might not know what SQL is capable of..
Say I have a table T, that looks like this -
id | some_other_fields | managed_by_sarah
1 | some_other_values | 1
2 | some_other_values | 1
3 | some_other_values | 0
So some rows will have managed_by_sarah=1 and some will have it =0, it is treated as a boolean value.
Then I have some other values pulled from backedend. I have already formatted into values so now it is a list of values (let's call it list L) that can be inserted into table T. Every record in the list has managed_by_sarah=1.
I want to update all the records in table T that has managed_by_sarah=1. Four scenarios below -
If a record has managed_by_sarah=1 in table T and another record with the same id appears in list L, then update the original record in table T to have all the new field values from list L.
If a record has managed_by_sarah=1 in table T but no matching record in list L with the same id, then delete this record
If a record in list L does not show up table T then add it to table T.
If a record has managed_by_sarah=0, don't do anything regardless.
I was only able to write a query to cover the 1st scenario, 3rd and 4th one. Can all four scenarios be accomplished in one query?
Here is my query so far -
INSERT INTO T (id, name, ... managed_by_sarah)
VALUES (())
ON DUPLICATE KEY UPDATE
id=VALUES(id),
name=VALUES(name),
...
managed_by_sarah=VALUES(managed_by_sarah);

Is it possible to reference a mysql table entry value from a second table entry dynamically?

I can't find anything about dynamically referencing one MySQL table entry to another. It may not be possible.
Essentially, I'd like to know if in MySQL you can do the equivalent to referencing the value of a certain Excel cell to another. For example, if in Excel I set Sheet 1 Cell A1 to some value like "MyVal". Then if I set Sheet 2 Cell A1 to "=Sheet1!A1" and Sheet 3 Cell A1 to "=Sheet2!A1" the value of Sheet 3 Cell A1 is "MyVal". If I go back to Sheet 1 Cell A1 and change the value to "MyNewVal" then the value is automatically updated on Sheet 2 Cell A1 and Sheet 3 Cell A1 to "MyNewVal".
My question is... in MySQL can I set the value of a certain entry in the first table to be dynamically linked to the value of a different entry in a second table such that when I query the first table (using existing PHP code) I get the value that's in the second table? I imagine that if it's possible then perhaps the value of the entry in the first table would look like a query that queries the second table for the correct value.
I understand how to write an UPDATE query in PHP to explicitly make the values the same but I don't want to change the existing php code. I want to link them in a relative/dynamic way. The short reason is that I don't want to change the PHP code since the same code is used on several of the sites I maintain and I want to keep the existing php code the same for cleaner maintenance/upgrading.
However, since the databases on the various sites are already different, it would be very clean to somehow dynamically link the appropriate entries in the different tables in the database itself.
Any help would be very appreciated. If this is possible, if you could just point me in the right direction, I'd be happy to do the research.
There are 2.5 ways to do this (basically two, but it feels like there's three):
From easiest to hardest...
Option 1:
If you need tableA to reflect tableB's value, don't store the value in tableA at all, just use tableB's value. Use either a join:
select a.*, b.col1
from tableA a
join tableB b on <some join condition>
or a subselect
select *, (select col1 from tableB where <some condition>) col1
from tableA
Option 2:
If you're happy with option 1, convert it to a view, which behaves like a table (except are restrictions on updating views that are joins):
create view myview as
select ... (one of the above selects)
Option 3:
Create a database trigger that fires when tableB's value is changed and copies the value over to the appropriate row/column in tableA
create trigger tableB_update
after update on tableB
for each row
update tableA set
tablea_col = new.col1
where id = new.tableA_id;
Note that new and old are special names given to the new and old rows so you can reference the values in the table being updated.
Choose the option that best suits your needs.
Databases don't really provide this type of facility, it's a completely different paradigm.
You can achieve the same results using joins, groupings or functions.
ALternatively if you wish to save the representation, store the query into a view which makes it more re-usable from various interfaces. More information on views can be found here; http://www.mysqltutorial.org/mysql-views-tutorial.aspx
Anything more complex and you will need to look at some business analysis tools.
Perhaps you have oversimplified the question, but you should not need to use a trigger. Just join the tables and any time 'MyVal' is changed it will automatically be available through query.
CREATE TABLE Sheet1
(
`ID` int auto_increment primary key
, `A` varchar(5)
)
;
INSERT INTO Sheet1
(`A`)
VALUES
('MyVal')
;
CREATE TABLE Sheet2
(
`ID` int auto_increment primary key
, `Sheet1FK` int)
;
INSERT INTO Sheet2
(`Sheet1FK`)
VALUES
(1)
;
CREATE TABLE Sheet3
(
`ID` int auto_increment primary key
, `Sheet2FK` int)
;
INSERT INTO Sheet3
(`Sheet2FK`)
VALUES
(1)
;
Query 1:
select
sheet3.id id3
, sheet2.id id2
, sheet1.id id1
, sheet1.a
from sheet1
inner join sheet2 on sheet1.id = sheet2.sheet1fk
inner join sheet3 on sheet2.id = sheet3.sheet2fk
Results:
| ID3 | ID2 | ID1 | A |
|-----|-----|-----|-------|
| 1 | 1 | 1 | MyVal |

Query with primary key obtained from primary keys of underlying tables

I have a table in Access which I'd like to substitute with a query which gathers data from the table and other new tables. The table is used by many queries which look to a primary key (autonumber) in the table, so the new query must have a primary key which is a unique combination of the primary keys of the tables used by the query. What can I do?
--EDIT--
Solution found: Since I want to "merge" tables with a query, and since the pk is an autonumber, I can define the new pk (of the query) by "expanding the numbering": I multiply both pkeys by 2 (because I have two tables) and add or subtract 1 to one of the two (or 1 for the first table and 2 for the second, and so on).
For example:
PK1 = 1,2,3,4,5,6
PK2 = 1,3,4,5,8,9,10 (some records may have been deleted, so the number is skipped)
new PK = (2*PK1, (2*PK2 + 1)) = (2,4,6,8,10,12),(3,7,9,11,17,19,21)
as you can see they will never overlap (no new value of PK2 can be obtained from any value of PK1, because of the "+1") because math says they belong to different vector spaces.
Hope it may help somebody
Use composite key (Multiple-field primary key)

Need suggestions to get a unique index keys for two or more tables on mysql

Usually, I use auto_increment attribute to get an unique key/id for each row on a single table to use as a primary index. Now I have two tables and unfortunately auto_increment can't create a new key using the last id/key on another table to keep all the keys/id unique in both. If I'll use auto_increment on both index columns, the possibility to have two identical ID is assured! There is a easy way to do it?
At least from a perspective of relational database design, your requirement seems unsound. You ought to create a separate table with the common auto_increment field and point to that from the other two tables with foreign keys.
If you have:
table A with ids 1,2,3.
table B with ids 1,2,3.
Then you already have the following (virtual) unique identifiers:
A1, A2, A3, B1, B2, B3
You don't need to make any changes to your database. This is purely a presentation issue.