Select from a relative with foreign key? - mysql

I have these tables:
create table CLIENTE (
idCliente int primary key auto_increment,
name varchar(255)
create table ANIMAL (
idAnimal int primary key,
name varchar(255),
foreign key (idCliente) references CLIENTE (idClinete) on delete set null on update cascade
How do I list (with Select * from methood) the names of the animals from the client John?
It's sort of an executable so I know that it wouldn't actually show the names if I runned the code, but aside that how can I just make the code?

You need to have an idCliente column in the ANIMAL table:
create table ANIMAL (
idAnimal INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255),
idCliente INT,
FOREIGN KEY (idCliente) REFERENCES CLIENTE (idCliente) ON DELETE SET NULL ON UPDATE CASCADE
);
Then you use it in a JOIN:
SELECT a.*
FROM ANIMAL AS a
JOIN CLIENTE AS c ON a.idCliente = c.idCliente
WHERE c.name = 'John';

Related

How to create a table with a composite key made of 2 foreign keys referencing to other tables?

I have three tables A, B and funding:
Table A has a primary key partner_id
Table B has a primary key branch_id
When I try to create table C with the following code:
CREATE TABLE Funding (
partner_id INT,
branch_id INT,
total_fund FLOAT,
PRIMARY KEY (partners_id, branch_id),
FOREIGN KEY (partners_id) REFERENCES A(partner_id) ON delete SET NULL,
FOREIGN KEY (branch_id) REFERENCES B(branch_id) ON delete SET NULL
);
I get error message:
1830: column partner_id cannot be NOT NULL: needed in a foreign key constraint.
How can I solve this problem?
Create a separted ID for PK:
SQL DEMO
CREATE TABLE A (
partner_id INT,
PRIMARY KEY (partner_id)
);
CREATE TABLE B (
branch_id INT,
PRIMARY KEY (branch_id)
);
CREATE TABLE Funding (
id INT PRIMARY KEY AUTO_INCREMENT,
partner_id INT,
branch_id INT,
total_fund FLOAT,
FOREIGN KEY (partner_id) REFERENCES A(partner_id) ON DELETE SET NULL,
FOREIGN KEY (branch_id) REFERENCES B(branch_id) ON DELETE SET NULL
);
You can also add:
ALTER TABLE `Funding` ADD UNIQUE `unique_index`(partner_id, branch_id);
But that can cause problem when multiple partners from same branch are deleted
In CREATE TABLE Funding just add NOT NULL statement to partner_id and branch_id.
CREATE TABLE Funding ( partner_id INT NOT NULL, branch_id INT NOT NULL,...

MySQL create table one to many, what is the best option below?

I have below data and using mysql. Person_name is unique and TelephoneNumbers are unique per person.
Person_name1=TelephoneNumber1, TelephoneNumber2, TelephoneNumber3...
Person_name2=TelephoneNumber4, TelephoneNumber5, TelephoneNumber6...
Option 1. Create 1:Many master and child table.
CREATE TABLE Person (
personName varchar(50) NOT NULL,
id int NOT NULL AUTO_INCREMENT,
PRIMARY KEY (id),
UNIQUE KEY personName (personName)
);
CREATE TABLE Telephone (
telephoneNumber int,
mappingId int,
PRIMARY KEY (telephoneNumber),
foreign key(mappingId) references Person(id)
);
Option 2. Create one table with personName, telephoneNumber as Composite Key.
CREATE TABLE
Person_Telephone (
personName varchar(50) NOT NULL,
telephoneNumber int NOT NULL,
PRIMARY KEY(personName, telephoneNumber)
);
Option 1 is it over complicating creating two tables for just two fields?
Option 2 looks perfect and will there be any issues if Option 2 chosen over Option 1?
The option 2 gives you duplicate persons that you must control in every query.
The best is have the entities separate, it's a classic 1-N relation
Since users can have multiple phone numbers, I think 2 tables would be the best solution.
CREATE TABLE person (
PRIMARY KEY (id) AUTO_INCREMENT,
person_name VARCHAR(45) NOT NULL,
);
CREATE TABLE phone_number (
PRIMARY KEY (id) AUTO_INCREMENT,
phone_number VARCHAR(11) NOT NULL,
FOREIGN KEY (person_id) REFERENCES person(id)
)
Now you can simply JOIN the tables like this:
SELECT
t1.id,
t1.person_name,
t2.phone_number
FROM person t1
LEFT JOIN phone_number t2
ON (t1.id = t2.person_id);

SQL issue with multiple foreign

Issue:
I'm using PostgreSQL Database.
I have one table (Albums) to be linked to two other tables (Clients, Domains). So if you are Client or Domain you can have Album. But in Albums table owner can handle only single foreign key. How can I solve this issue?
Dream: Single Album can own only (1) Client or Domain. Need fix issue with foreign keys. Albums: id | owner (multiple foreign -> Clients:id or Domains:id) --> can not do this | name. I just need some smart rework.
Tables (now can have Album only Domain):
Albums
Clients
Domains
Albums (table with foreign key yet):
id | owner (foreign key -> Domains:id) | name
Clients:
id | first_name | last_name
Domains:
id | owner | name
Add 2 FK columns, and a CHECK constraint, to enforce only one of them is NOT NULL...
Something like this:
CREATE TABLE albums (
id serial PRIMARY KEY,
client_id integer,
domain_id integer,
name varchar(255) NOT NULL,
FOREIGN KEY (client_id) REFERENCES clients(id),
FOREIGN KEY (domain_id) REFERENCES domains(id),
CHECK ((client_id IS NULL) <> (domain_id IS NULL))
);
To query you can use something like this:
SELECT a.id, COALESCE(c.id, d.id) AS owner_id, COALESCE(c.name, d.name) AS owner_name,
a.name AS title
FROM albums a
LEFT JOIN clients c ON a.client_id = c.id
LEFT JOIN domains d ON a.domain_id = d.id
#e_i_pi's version
CREATE TABLE entities (
id serial PRIMARY KEY,
type integer, -- could be any other type
-- any other "common" values
);
CREATE TABLE client_entities (
id integer PRIMARY KEY, -- at INSERT this comes from table `entities`
name varchar(255) NOT NULL,
);
CREATE TABLE domain_entities (
id integer PRIMARY KEY, -- at INSERT this comes from table `entities`
name varchar(255) NOT NULL,
);
CREATE TABLE albums (
id serial PRIMARY KEY,
owner_id integer FOREIGN KEY REFERENCES entities(id), -- maybe NOT NULL?
name varchar(255) NOT NULL,
);
Query:
SELECT a.id, owner_id, COALESCE(c.name, d.name) AS owner_name, a.name AS title
FROM albums a
LEFT JOIN entities e ON a.owner_id = e.id
LEFT JOIN client_entities c ON e.id = c.id AND e.type = 1 -- depending on the type of `type`
LEFT JOIN domain_entities d ON e.id = d.id AND e.type = 2
Righto, so as suggested in the comment to the answer by #UsagiMiyamoto, there is a way to do this that allows declaration of entity types, with cascading. Note that this solution doesn't support unlimited entity types, as we need to maintain concrete FK constraints. There is a way to do this with unlimited entity types, but involves triggers and quite a bit of nastiness.
Here's the easy to understand solution:
-- Start with a test schema
DROP SCHEMA IF EXISTS "entityExample" CASCADE;
CREATE SCHEMA IF NOT EXISTS "entityExample";
SET SEARCH_PATH TO "entityExample";
-- We'll need this to enforce constraints
CREATE OR REPLACE FUNCTION is_entity_type(text, text) returns boolean as $$
SELECT TRUE WHERE $1 = $2
;
$$ language sql;
-- Unique entity types
CREATE TABLE "entityTypes" (
name TEXT NOT NULL,
CONSTRAINT "entityTypes_ukey" UNIQUE ("name")
);
-- Our client entities
CREATE TABLE clients (
id integer PRIMARY KEY,
name TEXT NOT NULL
);
-- Our domain entities
CREATE TABLE domains (
id integer PRIMARY KEY,
name TEXT NOT NULL
);
-- Our overaching entities table, which maintains FK constraints against clients and domains
CREATE TABLE entities (
id serial PRIMARY KEY,
"entityType" TEXT NOT NULL,
"clientID" INTEGER CHECK (is_entity_type("entityType", 'client')),
"domainID" INTEGER CHECK (is_entity_type("entityType", 'domain')),
CONSTRAINT "entities_entityType" FOREIGN KEY ("entityType") REFERENCES "entityTypes" (name) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "entities_clientID" FOREIGN KEY ("clientID") REFERENCES "clients" (id) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT "entities_domainID" FOREIGN KEY ("domainID") REFERENCES "domains" (id) ON DELETE CASCADE ON UPDATE CASCADE
);
-- Our albums table, which now can have one owner, but of a dynam ic entity type
CREATE TABLE albums (
id serial PRIMARY KEY,
"ownerEntityID" integer,
name TEXT NOT NULL,
CONSTRAINT "albums_ownerEntityID" FOREIGN KEY ("ownerEntityID") REFERENCES "entities"("id")
);
-- Put the entity type in
INSERT INTO "entityTypes" ("name") VALUES ('client'), ('domain');
-- Enter our clients and domains
INSERT INTO clients VALUES (1, 'clientA'), (2, 'clientB');
INSERT INTO domains VALUES (50, 'domainA');
-- Make sure the clients and domains are registered as entities
INSERT INTO entities ("entityType", "clientID")
SELECT
'client',
"clients".id
FROM "clients"
ON CONFLICT DO NOTHING
;
INSERT INTO entities ("entityType", "domainID")
SELECT
'domain',
"domains".id
FROM "domains"
ON CONFLICT DO NOTHING
;
If you don't like the idea of inserting twice (once in client, once in entites, for example) you can have a trigger on inserts in the clients table, or alternately create an insert function that inserts to both tables at once.

How to update value of foreign key automatically

I have two table in a database. First one is
CREATE TABLE persons
(
P_Id int NOT NULL,
LastName varchar(30) NOT NULL,
FirstName varchar(30),
Address varchar(200),
City varchar(20),
PRIMARY KEY (P_Id)
)
and the second one is
CREATE TABLE Orders
(
O_Id int NOT NULL,
OrderNo int NOT NULL,
P_Id int,
PRIMARY KEY (O_Id),
FOREIGN KEY (P_Id) REFERENCES Persons(P_Id)
)
My question is there any way to update value of FOREIGN KEY (P_Id) automatically in Orders table once primary key (P_Id) in Persons table get updated.
Thank You.
your second table should be
CREATE TABLE Orders
(
O_Id int NOT NULL,
OrderNo int NOT NULL,
P_Id int,
PRIMARY KEY (O_Id),
FOREIGN KEY (P_Id) REFERENCES Persons(P_Id),
ON UPDATE CASCADE
)
This means that "ON UPDATE CASCADE" will do the same thing when id of the parent is updated.
The mentioned can be easily achieved by Using After Update Trigger on the Table persons.
Please do..
Create Trigger trgUpdatePersonsPIDinOrders On dbo.persons After Update
AS Begin Declare #OP_ID Int,#NP_ID Int Select #OP_ID =
Deleted.P_ID From Deleted Select #NP_ID = Inserted.P_ID From
Inserted If #OP_ID <> #NP_ID Then
Update DBO.Orders Set P_ID = #NP_ID Where P_ID = #OP_ID End
May It will Help You
Thanks

Nesting of groups or elements

I'm fairly new in Mysql, but I have problem that I cannot solve. I will give you an example to demonstrate it. Please note that I know that (for current example) there are other simpler and more efficient ways to solve it... but just take it as an example of the required procedure.
First the data: The data would be the name of a Person.
CREATE TABLE person(
id INT,
name VARCHAR(100)
) TYPE=innodb;
Second: Group Creation... So this is fairly simple... and could easily done using a table 'group' with a foreignkey to person. These groups could be arbitrary, containing any number of persons, duplicated... or not... (that is simple!!)
Third: MY REAL PROBLEM--- I also would like to have Groups that have other Groups as elements (instead of persons). This is where a really get stuck, because I know how to create a groups of persons, a group of groups (having a self-referencing foreign key)... but I don't know how to create a group that MAY HAVE persons AND Groups.
I appreciate any suggestion to solve this issue.
Thank you very much for your comments.
Regards
ACombo
I'd go with firstly setting up the myGroup and person tables.
Secondly, I'd set up a myGroupGroup table with columns myGroupId, parentMyGroupId. This will allow you to relate group rows to child group rows i.e. "this group has these groups within it". If a group has no rows in this table then it has no child groups within it.
Thirdly, I'd set up a personGroup table with columns personId, myGroupId. This will allow you to relate person rows to a given group. If a group has no rows in this table then it has no persons within it.
CREATE TABLE person(
id INT UNSIGNED PRIMARY KEY,
name VARCHAR(100)
) ENGINE=innodb;
CREATE TABLE myGroup(
id INT UNSIGNED PRIMARY KEY,
groupName VARCHAR(100)
) ENGINE=innodb;
-- Holds groups within groups
CREATE TABLE myGroupGroup(
id INT UNSIGNED PRIMARY KEY,
myGroupId INT UNSIGNED,
parentMyGroupId INT UNSIGNED DEFAULT NULL,
CONSTRAINT `fk_myGroupGroup_group1` FOREIGN KEY (`parentMyGroupId`) REFERENCES `myGroup` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `fk_myGroupGroup_group2` FOREIGN KEY (`myGroupId`) REFERENCES `myGroup` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=innodb;
-- Holds persons within a group
CREATE TABLE personGroup(
id INT,
personId int UNSIGNED NOT NULL,
myGroupId int UNSIGNED NOT NULL,
CONSTRAINT `fk_personGroup_group1` FOREIGN KEY (`myGroupId`) REFERENCES `myGroup` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `fk_personGroup_person1` FOREIGN KEY (`personId`) REFERENCES `person` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=innodb;
I've tweaked your SQL a bit:
1) Replaced TYPE with ENGINE
2) Replaced table name group with myGroup (GROUP is a reserved word)
Good luck!
Alternative:
CREATE TABLE Entity
( EntityId INT --- this id could be AUTO_INCREMENT
, PRIMARY KEY (EntityId)
) ENGINE = InnoDB ;
CREATE TABLE Person
( PersonId INT --- but not this id
, PersonName VARCHAR(100)
, PRIMARY KEY (PersonId)
, FOREIGN KEY (PersonId)
REFERENCES Entity(EntityId)
) ENGINE = InnoDB ;
CREATE TABLE Grouping
( GroupingId INT --- and neither this id
, GroupingName VARCHAR(100)
, PRIMARY KEY (GroupingId)
, FOREIGN KEY (GroupingId)
REFERENCES Entity(EntityId)
) ENGINE = InnoDB ;
CREATE TABLE Belongs
( EntityId INT
, GroupingID INT
, PRIMARY KEY (EntityId, GroupingId)
, FOREIGN KEY (EntityId)
REFERENCES Entity(EntityId)
, FOREIGN KEY (GroupingID)
REFERENCES Grouping(GroupingId)
) ENGINE = InnoDB ;