MySQL Alter table add column that is unique together with another column - mysql

I have such a table:
+---------+--------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+---------+--------------+------+-----+-------------------+-----------------------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| url | varchar(255) | YES | UNI | NULL | |
| ts | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| content | longblob | YES | | NULL | |
| source | varchar(255) | YES | | NULL | |
| state | int(11) | NO | | 0 | |
+---------+--------------+------+-----+-------------------+-----------------------------+
I'd like the id to stay the only PRIMARY KEY and I'd like to add field "VERSION" which will be unique.
What I want is to create unique pair (url, version) unique together but not separately. How can I do that? Should I add field version just like that, alter url so it's not unique and then add constraint?
Thanks in advance!

If what you're looking for is to store multiple versions of the same URL together in the table, then yes, what you need to do is:
Drop the unique constraint on URL
Add non-unique column version (assume integer here)
Create unique constraint or index on (url, version). I would suggest an index since I think that should make the unique checks faster.

Related

Should I use FOREIGN KEY or ADD INDEX in sql?

Today I have seen a video lecture in which they gave the foriegn key by using ADD INDEX on a table -
CASE 1 -
DECRIPTION OF TABLE 1 : subjects
+-----------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| menu_name | int(11) | YES | | NULL | |
| position | int(3) | YES | | NULL | |
| visible | tinyint(1) | YES | | NULL | |
+-----------+------------+------+-----+---------+----------------+
DECRIPTION OF TABLE 2 : pages
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| subject_id | int(11) | YES | | NULL | |
| menu_name | varchar(255) | YES | | NULL | |
| position | int(3) | YES | | NULL | |
| visible | tinyint(1) | YES | | NULL | |
| content | text | YES | | NULL | |
+------------+--------------+------+-----+---------+----------------+
So in the column subject_id of table pages should store the id of table subjects.
Which one should i use and why ? -
ALTER TABLE pages ADD INDEX fk_subject_id (subject_id);
OR
ALTER TABLE pages
ADD FOREIGN KEY (subject_id) REFERENCES students(id);
video lecture uses ALTER TABLE pages ADD INDEX fk_subject_id (subject_id);.
CASE 2 -
Now Please cosider one more example -
According to above details, If I have 5 more tables including pages table(defined above).
All 5 tables have column subject_id which should store the data accodring to column id of table subjects.
So in this case
In this case, Which one Should I use ADD INDEX or FOREIGN KEY and why ?
Q : case 1 - Which one should i use ?
A : I'll choose fk not index,because the reference between pages and subjects is multi to one,if you add index on column with duplicate values that would not be helpful,because in most cases, only one index can be used to optimize a database query,and there's a primary index on subjects,so don't do that again.
note : you have to make pages - subject_id not null
Q : case 2 - Which one should i use ?
A : if the 5 tables between subjects are also multi to one,i'll choose FK not index,the reason like case1's answer.
Using a FOREIGN KEY and an INDEX are different things. FOREIGN KEYs are used for data integrity, so that you cannot have a reference, which points to nothing and that you cannot delete the "base" row without deleting the "linking" rows first (unless you use ON CASCADE DELETE stuff).
Indices are used to improve the search speed to find the correct rows faster in an SELECT and UPDATE query. This has nothing to do with data integrity.
To answer your question: You use a FOREIGN KEY if you want to reference the Id of rows from the other table (like you do with subject_id). Also, you don't need to add an INDEX on the column subject_id, because the InnoDB engine already does that.

MySql; proper way to update fields of a table

When trying to describe a table I get a table with missing information (see first table); what would be the best way to update that table in a way that looks like the second one? My SQL background is not so strong, so I'd love to hear ideas on how to do this
First table (how it is actually)
+-----------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+------------------+------+-----+---------+-------+
| config_id | int(10) unsigned | NO | | 0 | |
| scope | varchar(8) | NO | | default | |
| scope_id | int(11) | NO | | 0 | |
| path | varchar(255) | NO | | general | |
| value | text | YES | | NULL | |
+-----------+------------------+------+-----+---------+-------+
Second table (how it should be)
+-----------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+------------------+------+-----+---------+----------------+
| config_id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| scope | varchar(8) | NO | MUL | default | |
| scope_id | int(11) | NO | | 0 | |
| path | varchar(255) | NO | | general | |
| value | text | YES | | NULL | |
+-----------+------------------+------+-----+---------+----------------+
I see following differences between the two tables :
column config_id should be auto_increment and also primary key of the table
a (non-unique) index is missing on column scope
The following statement should change the table as required :
ALTER TABLE mytable
MODIFY COLUMN config_id INT auto_increment,
ADD PRIMARY KEY (config_id),
ADD INDEX idx_scope(scope)
;
PS : DEFAULT NULL does not make sense for config_id : since it is a primary key, your RDBMS will never allow it to be set to NULL.
Please note that this answer is based on the information you provided only. Running this statement will not necessarily make the table structures strictly equivalent, since there could be other differences that can not be seen in the representation that you provided. You can get a complete DDL statement describing the table using the SHOW CREATE TABLE mytable syntax.

MySQL 2 columns index

I have unique index on 2 columns: name(varchar) and add_date(date).
If i add non unique indexes on name and on add_date its increase select speed or not?
name and add_date apart may not be unique.
UPD
MySQL console show columns says:
| Field | Type | Null | Key | Default | Extra |
| name | varchar(10) | NO | MUL | NULL | |
| time | date | NO | MUL | NULL | |
it will speed if you selecting on each one separately.
but make sure you need it.

How to create a table that automaticly updates another table when content is changed?

What I try to accomplish is that I want to update rows in tableA when one row from tableB gets deleted.
The layout of tableA is this:
+----------------------------+--------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------------------+--------------+------+-----+---------------------+----------------+
| user_id | int(11) | NO | PRI | NULL | auto_increment |
| nickname | varchar(32) | NO | | NULL | |
| password | varchar(129) | NO | | NULL | |
| mafia_id | int(11) | NO | | 0 | |
+----------------------------+--------------+------+-----+---------------------+----------------+
and of tableB this:
+-------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+----------------+
| mafia_id | int(11) | NO | PRI | NULL | auto_increment |
| mafia_name | varchar(32) | NO | | | |
| mafia_tag | varchar(5) | NO | | | |
| mafia_color | int(11) | NO | | 0 | |
| mafia_car | int(11) | NO | | 0 | |
| mafia_base | int(11) | NO | | 0 | |
+-------------+-------------+------+-----+---------+----------------+
I want to set all tableA.mafia_id to 0 when the corresponding mafia_id in tableB is deleted.
I read in the documentation that the database will automaticly do it for you, but you have to specify some stuff at table creation (in CREATE TABLE, create_definition: | CHECK (expr)?). The documentation is a bit unclear to me.
I also read this topic:
Create a trigger that updates a column on one table when a column in another table is updated
but this doesn't apply to me, i think?
So how would I create such a table (create table ...) or delete row statement?
Thanks in advance!
Since you are using InnoDB, you can achieve this with a foreign key constraint:
ALTER TABLE tableA
MODIFY mafia_id INT(11) NULL,
ADD FOREIGN KEY (mafia_id) REFERENCES tableB (mafia_id) ON DELETE SET NULL
As explained in the manual:
SET NULL: Delete or update the row from the parent table and set the foreign key column or columns in the child table to NULL. This is valid only if the foreign key columns do not have the NOT NULL qualifier specified. Both ON DELETE SET NULL and ON UPDATE SET NULL clauses are supported.
If you specify a SET NULL action, make sure that you have not declared the columns in the child table as NOT NULL.
Note that the constraint has the additional advantage of ensuring that mafia_id values in tableA must always reference an existing record in tableB.

In mysql can I have a composite primary key composed of an auto increment and another field? Also, please critique my "mysql partitioning" logic

I am experimenting with mysql partitioning ( splitting the table up to help it scale better ), and I am having a problem with the keys on the table. First, I am using a python's threaded comments module... here is the schema
+-----------------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+------------------+------+-----+---------+-------+
| content_type_id | int(11) | NO | MUL | NULL | |
| object_id | int(10) unsigned | NO | | NULL | |
| parent_id | int(11) | YES | MUL | NULL | |
| user_id | int(11) | NO | MUL | NULL | |
| date_submitted | datetime | NO | | NULL | |
| date_modified | datetime | NO | | NULL | |
| date_approved | datetime | YES | | NULL | |
| comment | longtext | NO | | NULL | |
| markup | int(11) | YES | | NULL | |
| is_public | tinyint(1) | NO | | NULL | |
| is_approved | tinyint(1) | NO | | NULL | |
| ip_address | char(15) | YES | | NULL | |
| id | int(11) | YES | | NULL | |
+-----------------+------------------+------+-----+---------+-------+
Note, I have modified this database by dropping the id col (primary by default), and re adding it.
Essentially, I want to have id AND content_type_id as my primary keys. I also want id to auto increment. Is this possible.
Second question. Since I am just learning about mysql partitioning, I am wondering if my partitioning logic is sound. There are 67 different content_types, and some (maybe all) of those content types allow comments to be made on them. My plan is to partition based on the type of object that is being commented on. For instance, the images will be commented on a lot, so I put any content type pertaining to images into one partition, and another content type that can be commented on is "blog entries", so there is a separate partition for that, and so on and so on. This will allow me to spread these partitions possibly to dedicated machines as the load grows. How is my understanding of this concept so far?
Thanks so much!
Since id will be auto incremented, it can be the primary key all by itself. Adding content_type to the primary key would not gain you anything in regards to the uniqueness of the key.
If you want to add an index for faster performance to the 2 columns, then add an alternate unique index to the table with the 2 columns instead of trying to add them both to the primary key. However, be aware that enforing uniqueness on the 2 columns would be a waste since id is already guaranteed to be unique by itself, so a regular index would make more sense if needed.