What does the line " KEY `idx_pid` (`person_id`), " mean? - mysql

I am new to mysql and am working on an online server (MYSQL version 5.1.69) and i have the following table
CREATE TABLE `person_info` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`person_id` int(11) NOT NULL,
`info_type_id` int(11) NOT NULL,
`info` text NOT NULL,
`note` text,
PRIMARY KEY (`id`),
KEY `idx_pid` (`person_id`),
KEY `person_info_info_type_id_exists` (`info_type_id`)
)
Can someone explain to me what " KEY idx_pid (person_id)," does?

KEY, in MySQL, is an alias for INDEX; you can see this in the pseudo grammar in the CREATE TABLE documentation:
[INDEX|KEY] [index_name] (index_col_name,...)
It represents the definition of an index on a table, and nothing more. Here,
KEY `idx_pid` (`person_id`),
…creates an index named "idx_pid" on the column "person_id". This could have also been written as,
INDEX `idx_pid` (`person_id`),
However, MySQL's SHOW CREATE TABLE command (and other commands) will prefer KEY. It is an unfortunate choice for a keyword here, as it has nothing to do with a “key¹” in the relational databases sense of the word.
¹A key, in relational database theory, is a set of columns that uniquely identify a row.

It means you're creating an index named "idx_pid" on the person_info.person_id column.

This adds an index named idx_pid on the person_id column which speeds up queries using the persond_id as condition.
You can read up on MySQL indexes here.

Related

Cannot drop index '*': needed in a foreign key constraint -> But which one?

Context
I am having problems deleting a row from one of our tables.
I use these queries to first drop it's foreign key and afterwards drop the column the key pointed to.
ALTER TABLE resources drop foreign key fk_res_to_addr;
ALTER TABLE resources drop column address_id;
Dropping the constraint works just fine. Dropping the column fails with Cannot drop index 'fk_res_to_addr': needed in a foreign key constraint.
What I tried so far
I first tried (and am still trying) to figure out what still relies on this index. I used this query (found in this answer):
SELECT
TABLE_NAME,
COLUMN_NAME,
CONSTRAINT_NAME,
REFERENCED_TABLE_NAME,
REFERENCED_COLUMN_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE
TABLE_SCHEMA = 'some_db' AND
REFERENCED_TABLE_NAME = 'resources';
But there was nothing there.
I then tried to just disable the checks with:
SET FOREIGN_KEY_CHECKS=0;
And then of course re-enabling them afterwards. This, too, had no effect.
Is there anything else I can do to figure out what depends on this index? Is there something else I am missing?
** Edit - the table definition as requested**
This is the table definition as it is right now. As you can see, there is now foreign key for address_id but the index remains.
create table resources
(
id bigint auto_increment primary key,
created bigint not null,
lastModified bigint not null,
uuid varchar(255) not null,
description longtext null,
internalName varchar(80) null,
publicName varchar(80) not null,
origin varchar(80) null,
archived bigint unsigned null,
contact_id bigint null,
colorClass varchar(80) null,
address_id bigint null,
url mediumtext null,
constraint uuid
unique (uuid),
constraint FK_contact_id
foreign key (contact_id) references users (id)
)
charset = utf8;
create index fk_res_to_addr on resources (address_id);
create index idx_resources_archived on resources (archived);
create index idx_resources_created on resources (created);
I haven't come across this before but it's so bad I suspect there may be a mysql bug. And it works 'properly' in mariadb.
You should be seeing an error Can't DROP 'fk_res_to_addr'; check that column/key exists as well as the error you are reporting - see https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=c5b0bbc9d6c12f74e00ba8d059a15638
On the create mysql creates an index with the name you have allocated to the fk and allocates it's own name to the fk. The result is the error mentioned above plus https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=c5b0bbc9d6c12f74e00ba8d059a15638.
I suggest you try dropping the key, then the foreign key then the column.
If you will try
SHOW INDEXES FROM database_name.table_name;
it may show you whether fk_res_to_addr' was really dropped.

MySQL - Error: 150 "Foreign key constraint is incorrectly formed")

Got an odd problem I cant solve after browsing dozens of forum posts, and my local SQL Books.
I've got two tables, and want to add a foreign key to one of them. The foreign key and primary key share the same datatype and charset and yet I cannot add the Foreign Key at all.
addon_account
name
type
comments
id
int(11)
Primary Key
name
varchar(60)
Primary Key
label
varchar(255)
shared
int(11)
addon_account_data
name
type
comments
id
int(11)
Primary Key
account_name
varchar(60)
Primary Key
money
double
owner
varchar()
The query I ran:
ALTER TABLE `addon_account_data` ADD FOREIGN KEY (`account_name`) REFERENCES `addon_account`(`name`) ON DELETE RESTRICT ON UPDATE RESTRICT;
Can't get it to work. Tosses out the same issue the entire time.
You are creating a foreign key on addon_account_data(account_name) that references addon_account(name). You have a composite primary the referred table : addon_account(id, name).
This is not allowed in MySQL, as explained in the documentation:
MySQL 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.
Possible solutions:
add an additional column in the referring table: addon_account_data(account_id, account_name) and create a composite primary key to the corresponding columns in addon_account
create an index on addon_account(name) (probably the simplest solution)
change the order of the columns in the primary key of the referred table, like: addon_account(name, id) (you might want to first consider the impacts this may have in terms of performance)
I am not exactly a MySQL guy, but:
I believe the problem is that you are referencing only part of the primary key:
Your table addon_account has a composite key PK(id, name).
So, to put your relationship to work, you will need to add 'account_id' as part of the foreign key as well:
ALTER TABLE addon_account_data ADD FOREIGN KEY (account_id, account_name) REFERENCES addon_account(id, name)
This thread deals with something similar.
I hope this helps.
EDITED
I have installed a MySQL server instance on my local machine... (MySQL 8).
I have run the script below, and it worked (giving warnings about integer display being a deprecated feature, so I would recommend ommitting it):
CREATE TABLE addon_account(
id INT(11) NOT NULL,
`name` VARCHAR(60) NOT NULL,
label VARCHAR(255),
shared INT(11),
CONSTRAINT pk_addon_account PRIMARY KEY(id, `name`));
CREATE TABLE addon_account_data (
id INT(11) NOT NULL,
account_name VARCHAR(60) NOT NULL,
account_id INT(11),
money DOUBLE,
`owner` VARCHAR(255),
CONSTRAINT pk_addon_account_data PRIMARY KEY(id, account_name),
CONSTRAINT fk_addon_account_account_data FOREIGN KEY(account_id, account_name)
REFERENCES addon_account(id, `name`));
Could you try it and see if this works for you?
I am not that familiar with MySQL.
make sure that the 2 tables have the same collation
like
COLLATE='utf8_general_ci'

MYSQL How to safely remove UNIQUE KEY? What to have in mind?

I have a table in database.
CREATE TABLE `comment_sheets` (
`id` mediumint(9) NOT NULL AUTO_INCREMENT,
`doc_id` mediumint(9) NOT NULL,
`level` varchar(10) DEFAULT NULL,
`author` varchar(30) DEFAULT NULL,
`status` varchar(10) DEFAULT NULL,
`creation_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `cs` (`doc_id`,`level`,`author`)
) ENGINE=InnoDB AUTO_INCREMENT=3961075 DEFAULT CHARSET=utf8 ;
My UNIQUE KEY cs (doc_id,level,author) is a problem now. I want to remove it, becouse i need duplicate values.
My question is. What should i have in my mind or what shoud I be worry about, when i want delete unique key?
Thanks.
To drop unique key
ALTER TABLE table_name
DROP INDEX index_name;
To drop primary key
ALTER TABLE table_name
DROP INDEX `PRIMARY`;
You need to alter table:
alter table comment_sheets drop INDEX `cs`
It really depends on how the key is used apart from enforcing uniqueness of data.
Check if the key is used in any foreign key relationships. If yes, you need to drop the foreign key before you can drop the unique one. (Well, mysql won't let you drop the index if the foreign key exits anyway)
Check what queries may make use of the key and how its removal would affect their performance. You may have to add a non-unique key on these fields back.
I this particular case dropping the index is relatively simple task because it is not the primary key, and it is not a fulltext index. The only thing that may take long is the removal of the index data if your table is big (judging from the auto increment value, it is not a small table)

Declaring MySQL PK as only Unique Key

Can creating a UNIQUE index on an Id as shown in the create table below be enough to make the id a Primary Key? TO be more specific, can you say that the table below has a Primary Key?
test` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`role` varchar(32) NOT NULL,
`resources_name` varchar(32) NOT NULL,
`access_name` varchar(32) NOT NULL,
`allowed` int(3) NOT NULL,
UNIQUE KEY `id` (`id`),
UNIQUE KEY `roles_name` (`role`,`resources_name`,`access_name`)
) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8
What query can you use to prove that this has or has no PK?
Logically speaking if a relational table has at least one candidate key enforced in it (minimally unique and non-nullable) then de facto it has a "primary" key. There is no absolute need to single out any one key using a special "primary" label because in principle all keys are equal (historically the term "primary key" used to be used for any and all candidate keys and not just one key per table).
There is a constraint in SQL called a PRIMARY KEY constraint. Logically speaking, the SQL PRIMARY KEY isn't much more than syntactical sugar because the NOT NULL UNIQUE syntax achieves essentially the same thing. Technically the PRIMARY KEY constraint doesn't have to refer to the same thing as the relational concept of a "primary key" but clearly if you are going to designate any one key as primary and if you feel you need a syntactical way of indicating that choice then the PRIMARY KEY constraint is the generally recognised way to do it.
So perhaps the best answer is "it depends". It depends to a large extent on your motivation for defining a primary key in the first place. If you intend to single out one key to developers and users of the database then maybe the NOT NULL UNIQUE syntax won't achieve that for you. If you don't find the need to do that using SQL syntax then maybe NOT NULL UNIQUE is just as good a way to define your keys as the PRIMARY KEY constraint is.
This is either too long or too short for a comment: No.
A primary key and a unique key -- although similar -- are not the same. So, no your table does not have a primary key. The biggest functional difference is that primary keys cannot be NULL whereas unique keys can be.
Primary keys are also typically clustered (if the underlying storage engine supports clustered indexes). This means that the data is actually physically stored on the page in the order of the primary key. Unique keys are just another index with the characteristic of having no repeated values.
EDIT:
Interesting. SHOW COLUMNS documents this behavior:
A UNIQUE index may be displayed as PRI if it cannot contain NULL
values and there is no PRIMARY KEY in the table.
I wasn't aware of this.

Understanding / mySQL aka tricking ForeignKey relationships in Django

So I've inherited some django.
The mySQL table is simple enough where parent is NOT a FK relationship just the "Parent" id:
CREATE TABLE `Child` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`parent` int(10) unsigned NOT NULL,
`name` varchar(255) NOT NULL,
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=24;
But then the originator did this..
class Child(models.Model):
"""Project Child information"""
id = models.AutoField(primary_key=True)
parent = models.ForeignKey(Parent)
name = models.CharField(max_length=255)
class Meta:
managed = False
Admittedly I am NOT a SQL Jockey but I know that a "real" Foreign Key Relationship looks similar to this notice CONSTRAINT...
CREATE TABLE `Child` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`parent_id` int(11) NOT NULL,
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
KEY `child_63f17a16` (`parent_id`),
CONSTRAINT `parent_id_refs_id_34923e1e` FOREIGN KEY (`parent_id`) REFERENCES `Parent` (`id`)
) ENGINE=InnoDB;
What I want to know is the following:
What problems could I expect to see by this "trickery".
While this appears to work - is it recommended or advised.
Would we be advised to modify the SQL to add in the constraint?
Thanks so much!
Not having an actual constraint might lead to broken references, invalid parents and other sorts of data inconsistencies. I am not a Django expert but I would venture a guess that in most cases Django will still handle the relations fine unless you purposefully add some invalid records.
Normally, if your RDBMS supports foreign key constraints, there is absolutely no reason not to use them, and it could potentially be considered a design flaw to ignore them.
You should consider adding the key constraints. Not only do they give your DBMS a good idea of how to optimize the queries, they also ensure consistency in your data. I am pretty sure Django has a setting somewhere that will automatically generate the SQL to add the key constraints when you run manage.py syncdb
For more information about why you should prefer foreign keys, you should read the MySQL Foreign Key Documentation
Most interestingly:
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.
Its supposed to be faster ... since you mysql doesn't check the constraint before adding a row in the child table.
But with the foreign key, it would make your life easier since you can use the on update and on delete.
I'd go with the constraint.