Indexes for references in same table - mysql

I have a table:
CREATE TABLE person (
person_id INTEGER NOT NULL,
parent_person_id INTEGER REFERENCES person(person_id),
CONSTRAINT PK_person_id PRIMARY KEY (person_id)
);
Is there need to create index on parent_person_id column or it is created automatically?

You don't need to create the index on parent_person_id. Indexes are required on the referenced column, not the referencing one.
Also, be aware that there are some restrictions on creating same-table relationships. At the MySQL website, on the section on foreign-key relationships, it reads, "If ON UPDATE CASCADE or ON UPDATE SET NULL recurses to update the same table it has previously updated during the cascade, it acts like RESTRICT.
This means that you cannot use self-referential ON UPDATE CASCADE or ON UPDATE SET NULL operations. This is to prevent infinite loops resulting from cascaded updates."
This is a known limitation of MySQL and you should be aware to prevent apparently nonsensical errors.

foreign key indexed automatically in only InnoDB. In referencing table, there must be a column
where the foreign key columns are listed as the first columns in the same order.
Such an index is created on the referencing table automatically if it does not exist.

Related

Do you still need to define foreign key constraint if you have already added a reference constraint to the column definition?

I am trying to understand the syntaxes for defining tables and I noticed that the column definitions include an option to indiciate that the column references a column from another table.
If I can already define this here, do I still need to explicitly define a FOREIGN KEY constraint specifying that column again? Why?
Because I imagine the REFERENCE definition added as a column constraint should already take care of the fact that the column is a foreign key (since it is referencing another table).
Example code for clarity:
a)
create table SAMPLE (
sample_id INT PRIMARY KEY,
client_id INT REFERENCES CLIENT (client_id)
);
b)
create table SAMPLE (
sample_id INT PRIMARY KEY,
client_id INT NOT NULL,
CONSTRAINT fk_sample_client
FOREIGN KEY (client_id) REFERENCES CLIENT (client_id)
);
Does definition (a) ensure that the clientId is identified as the foreign key, the same way definition (b) does?
REFERENCES as part of the column definition is ignored.
Important
For users familiar with the ANSI/ISO SQL Standard, please
note that no storage engine, including InnoDB, recognizes or enforces
the MATCH clause used in referential integrity constraint definitions.
Use of an explicit MATCH clause does not have the specified effect,
and also causes ON DELETE and ON UPDATE clauses to be ignored. For
these reasons, specifying MATCH should be avoided.
The MATCH clause in the SQL standard controls how NULL values in a
composite (multiple-column) foreign key are handled when comparing to
a primary key. InnoDB essentially implements the semantics defined by
MATCH SIMPLE, which permit a foreign key to be all or partially NULL.
In that case, the (child table) row containing such a foreign key is
permitted to be inserted, and does not match any row in the referenced
(parent) table. It is possible to implement other semantics using
triggers.
Additionally, MySQL requires that the referenced columns be indexed
for performance. However, InnoDB does not enforce any requirement that
the referenced columns be declared UNIQUE or NOT NULL. The handling of
foreign key references to nonunique keys or keys that contain NULL
values is not well defined for operations such as UPDATE or DELETE
CASCADE. You are advised to use foreign keys that reference only keys
that are both UNIQUE (or PRIMARY) and NOT NULL.
MySQL parses but ignores “inline REFERENCES specifications” (as
defined in the SQL standard) where the references are defined as part
of the column specification. MySQL accepts REFERENCES clauses only
when specified as part of a separate FOREIGN KEY specification. For
more information, see Section 1.7.2.3, “FOREIGN KEY Constraint
Differences”.
Source: https://dev.mysql.com/doc/refman/8.0/en/create-table.html
As Simon shared , inline REFERENCES in column definitions are ignored by mySQL and this link gives further explanation as to why.
Defining a column to use a REFERENCES tbl_name(col_name) clause has no
actual effect and serves only as a memo or comment to you that the
column which you are currently defining is intended to refer to a
column in another table.
Simply put, the syntax will still only create the column; it will not specify it as a foreign key or carry out any checks on it.

Foreign Key Tables Updates

I just started learning SQL so I am a bit confused.
If I have Table A that has a primary key : CustomerID & Table B with foreign key CustomerID
I added the foreign key constraint by using CASCADE so that the foreign key should update or delete automatically when primary key is deleted or updated.
However, it only works for delete. When I add a new record in the primary field table, that record is not shown in the foreign key table, why is that ?
Corresponding rows are updated or deleted in the referencing table
when that row is updated or deleted in the parent table. CASCADE
cannot be specified if a timestamp column is part of either the
foreign key or the referenced key. ON DELETE CASCADE cannot be
specified for a table that has an INSTEAD OF DELETE trigger. ON UPDATE
CASCADE cannot be specified for tables that have INSTEAD OF UPDATE
triggers.
As mention in MSDN. They have mentioned the only update and delete operation of primary key table will affect the Foreign key table's column. If any insert made to primary key, it will not affected the foreign key. Since the Main objective in primary key and foreign key relationship
"An each every record is available in the foreign key table, it should contain corresponding record should be present in the primay key table and vice versa is not applicable".
If you insert any record to foreign key table that it will throws foreign referential integrity error. It will not allows you to insert a record in the foreign table unless and until you will corresponding record in the primary key table.
for information take look in following in MSDN links
http://msdn.microsoft.com/en-us/library/ms179610.aspx
Note:
if you want to achieve this functionality then you have write a logic in Stored procedure or trigger.
No,is not automatic add in your foreign key table , it's not make sense , for example if you have two table ,"City" and "People" , People in the City , so there must be a FK refer for People , if you add record in City e.g. New York , How is database know who's need to insert to People table?How many people? , and what this people properties? e.g. People Name?
So database can't do that automatic , you have to do it manually!

Can't create FOREIGN KEY CONSTRAINT in MySQL

I created my MySQL database using phpMyAdmin 3.5.8.1deb1 in Ubuntu.
Instead of that all my tables are InnoDB, I can't add a foreign key, and this is an example:
ALTER TABLE element ADD CONSTRAINT FK_element_id_user FOREIGN KEY (id_user) REFERENCES user(id) ON DELETE SET NULL ON UPDATE CASCADE;
When I run this script I get this error :
#1005 - Can't create table 'tpw.#sql-4d8_e2' (errno: 150) (Details...)
When I click on details I get this :
InnoDB Documentation Supports transactions, row-level locking, and foreign keys
I tried to add the FK manually in the relation view
There could be a couple of things going one here. Here are some things to look for:
Do the data types of each field between the tables match?
Are both both tables using the same MySQL engine?
Here is a good resource to help you debug this issue further.
Excerpt from the resource linked to above:
1) The two key fields type and/or size is not an exact match. For example, if one is INT(10) the key field needs to be INT(10) as well and not INT(11) or TINYINT. You may want to confirm the field size using SHOW CREATE TABLE because Query Browser will sometimes visually show just INTEGER for both INT(10) and INT(11). You should also check that one is not SIGNED and the other is UNSIGNED. They both need to be exactly the same.
2) One of the key field that you are trying to reference does not have an index and/or is not a primary key. If one of the fields in the relationship is not a primary key, you must create an index for that field.
3) The foreign key name is a duplicate of an already existing key. Check that the name of your foreign key is unique within your database. Just add a few random characters to the end of your key name to test for this.
4) One or both of your tables is a MyISAM table. In order to use foreign keys, the tables must both be InnoDB. (Actually, if both tables are MyISAM then you won’t get an error message – it just won’t create the key.) In Query Browser, you can specify the table type.
5) You have specified a cascade ON DELETE SET NULL, but the relevant key field is set to NOT NULL. You can fix this by either changing your cascade or setting the field to allow NULL values.
6) Make sure that the Charset and Collate options are the same both at the table level as well as individual field level for the key columns.
7) You have a default value (ie default=0) on your foreign key column.
8) One of the fields in the relationship is part of a combination (composite) key and does not have it’s own individual index. Even though the field has an index as part of the composite key, you must create a separate index for only that key field in order to use it in a constraint.
9) You have a syntax error in your ALTER statement or you have mistyped one of the field names in the relationship.
10) The name of your foreign key exceeds the max length of 64 chars.
User.ID has to be declared as an INDEX

Specify constraints in a MySQL table

I am in the process of designing the databases for my system. There are a lot of foreign key constraints.
I was wondering whether I could get some advice, whether I should do which of the following:
1) Specify the constraints during table creation itself ie,
CREATE TABLE IF NOT EXISTS abc
(
keyword VARCHAR(20) NOT NULL,
id INT UNSIGNED NOT NULL,
FOREIGN KEY (id) REFERENCES xyz(id) ON DELETE CASCADE ON UPDATE CASCADE
)ENGINE=InnoDB;
2)create the table without FK constraints and 'alter' the table later on ie,
CREATE TABLE IF NOT EXISTS abc
(
keyword VARCHAR(20) NOT NULL,
id INT UNSIGNED NOT NULL,
)ENGINE=InnoDB;
ALTER TABLE abc ADD CONSTRAINT fk_constraint FOREIGN KEY (id) REFERENCES xyz(id)
ON DELETE CASCADE ON UPDATE CASCADE;
Table xyz is simply another table with 'id' as a primary key.
You may create the FK at once. But this is not always possible because they can refer to each other in a circular fashion. Also, you may want to add columns later, with a FK.
It may be slightly faster to add it at once, because MySQL has to validate and rebuild the table structure for some changes (although I'm not sure adding FKs is one of those). But this process will be reasonably fast on empty tables, so it doesn't matter much when you add the FK.
The result will be the same. So, there is no differences.
If I create new database, I'd create table and its foreign key in one statement. The script will look better. But in this case parent tables must be created before the child tables.
If you don't want to take into account dependencies when creating tables, you can create tables in random order in the beginning of the script and then add foreign keys using ALTER TABLE.

MYSQL: foreign keys auto indexing

The below set of commands:
alter table opportunities add column ownerId int null;
alter table opportunities add foreign key (ownerId) references users (id) on delete set null on update cascade;
Yields an error like this:
Error in foreign key constraint of table taous/#sql-318c_27:
There is no index in table "taous"."#sql-318c_27" where the columns appear
as the first columns. Constraint:
foreign key (ownerId) references users (id) on delete set null on update cascade
;
So I understand that an index is lacking on the referenced column
Now, the mysql documentation for foreign key constraints states:
InnoDB requires indexes on foreign keys and referenced keys so that foreign key checks can be fast and not require a table scan. In the referencing table, there must be an index where the foreign key columns are listed as the first columns in the same order. Such an index is created on the referencing table automatically if it does not exist. (This is in contrast to some older versions, in which indexes had to be created explicitly or the creation of foreign key constraints would fail.) index_name, if given, is used as described previously.
I run mysql 5.1 (xampp, windows) So I expect the columns to be indexed automatically on creation of a foreign key.
Any idea why can the auto indexing fail?
One more point:
The error only happens when the sql commands are run through PDO (a db update tool). When run directly in mysql console, no problems.
Thanks
Gidi
My understanding is that the auto-indexing is on the referencing table and not the referenced table.
In your case, the auto-indexing would add an index to ownerId in opportunities... except it doesn't need to, since you already did this.
I don't quite understand where "taous"."#sql-318c_27" comes from, but assuming that it relates to the users table, I believe the error is complaining that id is not indexed.
Another cause of this error could be that the types of the the referenced and referencing table columns do not match.
For example if the the ownerId column of the opportunities table is an INT but the Id column of the users is any type other than INT
That doesn't explain why it would work with the console and not a PDO however, but maybe this helps someone else down the line.