MySQL View where foreign key can be NULL - mysql

I would like to know how to create view which also works even if the foreign key is NULL. For example we have table Person which has a primary key and two foreign keys:
IdPerson
FkName
FkSurname
Both foreign keys can be NULL. Now we also have two tables, table Name:
IdName
Name
And table Surname:
IdSurname
Surname
Now we create view to display name and surname for each Person:
CREATE VIEW `Database`.`ViewPerson` AS
SELECT `N`.`Name`, `S`.`Surname`
FROM `Person` `P`, `Name` `N`, `Surname` `S`
WHERE (`P`.`FkName` = `N`.`IdName`) AND (`P`.`FkSurname` = `S`.`IdSurname`)
The problem is, if the foreign key FkSurname is NULL, than that row will not be displayed even though FkName is defined. I want that even if both foreign keys are NULL it still returns row where both columns are NULL. Now I know that I could solve it by adding in table Name and in table Surname row, that has NULL under Name/Surname and then in the FkName and FkSurname reference a row that has NULL values under those two columns. But I would still like to find out if there is a solution where foreign key is NULL and the row is returned.

If I understand your question correctly, you want to get the corresponding values (even if null) for the Name and Surname fields in the Name and Surname table for each record in the Person table.
This seems like a straightforward case where LEFT JOIN would work correctly. So, based on your query above, the SQL would be:
CREATE VIEW Database.ViewPerson AS
SELECT
N.Name, S.Surname
FROM Person P
LEFT JOIN Name N ON N.IdName = P.FkName
LEFT JOIN Surname S ON N.IdSurname = S.FkSurname;
(sorry of the syntax isn't 100% correct, I didn't go through and create a test table to confirm it)

Related

Using relations in MySQL

Let's say that I have the following tables:
Elements:
(int) ID
(int) Name_id
Names:
(int) ID
(varchar) Name
The Elements.Name_id has an internal relation with Names.id. The user enters an element name in a html form. Then a php script inserts the element name to the Elements table. And here comes my question:
Is it possible to specify the element name instead of the element name_id in the insert query? If not I will have to:
SELECT `ID` FROM `Names` WHERE `Names`.`Name` LIKE "$php_variable";
...
INSERT INTO `Elements` SET `Name` = "$php_variable";
Of course the second $php_variable is a result from the previous query.
You can just do:
insert into elements(name)
select n.name
from names n
where n.id = $php_variable;
Now, having said this, do not take this approach. Your data structure is wrong. You want to connect to names.id, not names.name, in most cases. (There are some exceptions where copying the name might be one solution for a slowly changing dimension, but I doubt that is your use-case.)
So, fix the data structure. The create table statements would look like:
create table names (
name_id int auto_increment primary key,
name varchar(255) unique
);
create table elements (
element_id int auto_increment primary key,
name_id int,
foreign key (name_id) references names(name_id)
);
Then use an explicit JOIN to get the name when you need it.
Note: I changed the ids of the table to be "tablename_Id". This is not required, but I find it helpful to have foreign keys and primary keys have the same names.

MySql replace with multiple primary keys

I have a table which has three primary keys and references three other tables
Here is the table scheema:
CREATE TABLE IF NOT EXISTS training_matrix_reference(
employee INT NOT NULL,
training_matrix INT NOT NULL,
training_record INT UNSIGNED NOT NULL,
PRIMARY KEY (employee, training_matrix,training_record),
FOREIGN KEY (employee) REFERENCES employees(id),
FOREIGN KEY (training_matrix) REFERENCES training_matrix_courses(id),
FOREIGN KEY (training_record) REFERENCES training_records(m_id)
)
I'm trying to craft a REPLACE statement which updates the training_record column or training_matrix column or both columns or creates a new row if not exists, but I also need to check that the employee belongs to the same company.
Here's what I tried so far:
REPLACE INTO `training_matrix_reference`
( employee, training_matrix, training_record ) (
SELECT id, '5', '100'
FROM employees
WHERE id =22
AND company =64
)
So my theory was that this should have replaced the first row in the table, updating training_record to 100 but in fact it actually created a new row:
22 | 5 | 100
My guess is that this happened because training_record is a primary key?
But I'm not sure that removing the primary keys/references is the right way to go as this table is used as a many to many table in other queries.
Effectively what I'm trying to do is:
REPLACE INTO `training_matrix_reference`
( employee, training_matrix, training_record )
VALUES
(22,33,18)
WHERE
employee = 22
and training_matrix = 5
and training_record = 2189
But obviously a replace statement doesn't have a where clause.
I did check out these similar questions:
MySQL REPLACE INTO on multiple keys?
mysql REPLACE query with multiple primary keys
But unfortunately MySql is not my strong suit and I could really use some help.
I hope I explained things clearly, Thanks
The PRIMARY KEY of the training_matrix_reference table is the combination of three columns. The table doesn't have multiple primary keys, it has a single PRIMARY KEY.
The REPLACE syntax you have is equivalent to performing:
DELETE FROM training_matrix_reference
WHERE employee = 22
AND training_matrix = 5
AND training_record = 100
;
INSERT INTO training_matrix_reference (employee, training_matrix, training_record)
VALUES (22, 5, 100);
;
The DELETE action only removes rows where the entire primary key is matched. Given the information you provided, we'd expect a row to be added to the table.
Did you have a question?
you should make a joining table between (employee, training_matrix_reference)
or dispense at lest one relation

how to find primary key for table in mysql

I have a given table in MySQL called inventory.. all the descriptions in table null = 'Yes' and default = 'Null'. the field names in the table are inventory, items, sales and Staff.
in inventory table I have part_no, decript,on_hand,location,unitcost, discontinue..
is it correct in stating that part_no would be my primary key as this this record can not have a duplicate value.
thank you for confirming or correcting my assumption.. Is there a query that would validate this.
did you already create your table? and could find the primary key? primary key ensure unique row and restrict duplicate value. if you want to find primary key of a table use.
SHOW KEYS FROM tablename WHERE Key_name = 'PRIMARY'
The below query gets the part_no and it's number of appearances, if you see 2 or above, then part_no can't be your primary key, and you have to select another or more primary keys. Make sure part_no IS NOT NULL !!! as you can't have null primary keys
select part_no, count(*) as appearances
from inventory
group by part_no
if you want to know it faster because of many rows, you run this
select max(appearances)
from ( select part_no, count(*) as appearances
from inventory
group by part_no )
if max is 1 you are ok. If not, add to group by and select another collumn and do the same. Then you can determine what collumn/s is/are your primary key. And with alter table, or some GUI you can change it.

Why don't I get any output from my relation table?

I have created 'students' table where 'sid' is the primary key and I have inserted many values into sid. I have created a second table called 'courses' and it has a primary key 'cid' I have entered values for cid as well. Now, I want to create a relation table called 'enroll' which I have done like-
create table enroll(
grade char(2),
sid int not null,
cid int not null,
primary key(sid,cid),
foreign key (cid) references courses(cid) on delete cascade,
foreign key (sid) references students(sid) on delete cascade
);
Now, when I try to view the table using select * from enroll;
I don't get any output. It says "0 rows returned". Why is this? Isn't it supposed to have all the values of sid and cid from the other tables?
In Order to create a new table from values in your other table you can do something like this:
CREATE TABLE new_table AS (SELECT * FROM old_table);
The select statement will be the fields that will be pulled.
You can rename the columns like: Select [field name] as [what you want field name to be]
For More information read this article
Anyway for your particular case:
Create table enroll AS (Select s.sid AS 'Sid', c.cid AS 'Cid' from courses c inner join students s on c.something = s.something)
replace '.something' with the id of the student
you just created the table structure, the schema, your table is empty, so you dont get any results.

Is it possible to have a mysql table accept a null value for a primary_key column referencing a different table?

I have a table that has a column which holds the id of a row in another table. However, when table A is being populated, table B may or may not have a row ready for table A.
My question is, is it possible to have mysql prevent an invalid value from being entered but be ok with a NULL? or does a foreign key necessitate a valid related value?
So... what I'm looking for (in pseudo code) is this:
Table "person" id | name
Table "people" id | group_name | person_id (foreign key id from table person)
insert into person (1, 'joe');
insert into people (1, 'foo', 1)//kosher
insert into people (1, 'foo', NULL)//also kosher
insert into people(1, 'foo', 7)// should fail since there is no id 7 in the person table.
The reason I need this is that I'm having a chicken and egg issue where it makes perfect sense for the rows in the people table to be created before hand (in this example, I'm creating the groups and would like them to pre-exist the people who join them). And I realize that THIS example is silly and I would just put the group id in the person table rather than vice-versa, but in my real-world problem that is not workable.
Just curious if I need to allow any and all values in order to make this work, or if there's some way to allow for null.
If you set the column as nullable then it can contain NULL even if it is a foreign key referencing a column in another table.
Foreign keys can be null.
When the row in the referenced table is entered you'll have to UPDATE that row to point to it.
You set a foreign key column to accept nulls by setting the optionality of the column to NULL:
DROP TABLE IF EXISTS `example`.`tableb`;
CREATE TABLE `example`.`tableb` (
`id` int(10) unsigned NOT NULL auto_increment,
`person_id` int(10) unsigned default NULL, -- notice, !say "NOT NULL" like id
PRIMARY KEY (`id`),
CONSTRAINT `FK_tableb_1` FOREIGN KEY (`person_id`) REFERENCES `tablea` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
That said, tablea has to have at least one record in it before you attempt to insert a null value into the tableb reference column. Otherwise, MySQL will throw an error (for me anyways, on 4.1).