Need clarification on mysql syntax - mysql

CREATE TABLE `table1` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`email` varchar(128) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`)
)
-
CREATE TABLE `table2` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY,
`email` varchar(128) DEFAULT NULL UNIQUE,
)
Questions:
When created, is there any difference between table1 and table2?
(I assume no, but better to ask than live in blissful ignorance;)
if (yes) what is it?; if (no) why do we have different syntax?
in larger tables show create table tbl_name displays UNIQUE KEY email_2 (email) or some other _num. Why? What does tlb_name_num mean and what is it used for?
What syntax is preferable and why?
show create table tbnm always displays sql in table1 form, even if table is created by table2 sql syntax. Why?
UNIQUE KEY (email) also works. but it's transformed to UNIQUE KEY email (email) on show create table. Why does it work, why is it transformed, etc?

There will be no difference between the two tables.
there are different syntaxes to declare everything first and then add primary key, unique ... Or if some people like to do it immeadiately they also have the possibility
No idea, edit this if found
they both do the same thing, use what you prefer.
No idea, edit this if found
No idea, edit this if found

Related

MYSQL ON DELETE CASCADE - Only works when set on a primary key

I have been facing to an issue with ON DELETE CASCADE in MySQL. It works perfectly when it is set on a primary key field, but not in other cases.
For example, I have a child table where I have a foreign key referring to a field in the parent table, but the child table has its own Auto-Incremental ID field which needs to be a primary key because grandchildren tables refer to it.
When I delete a row from the parent table, all records disappear as expected and no errors appear, however, the child's data depending on the deleted row of the parent table stays untouched.
I made researches without results. Although I assume it is something to do with the system identifying a row by its primary key, I could not find any relevant info about this.
The parent table:
CREATE TABLE IF NOT EXISTS table_parent (
ID TINYINT(3) UNSIGNED PRIMARY KEY AUTO_INCREMENT,
`level` TINYINT(1) NOT NULL,
updated DATETIME NOT NULL DEFAULT NOW()
);
The child table:
CREATE TABLE IF NOT EXISTS table_child (
ID TINYINT(3) UNSIGNED PRIMARY KEY AUTO_INCREMENT,
parentId TINYINT(3) UNSIGNED NOT NULL,
`name` VARCHAR(16) UNIQUE NOT NULL,
updated DATETIME NOT NULL DEFAULT NOW()
);
The relation:
ALTER TABLE table_child
ADD FOREIGN KEY (parentId) REFERENCES table_parent(ID) ON DELETE CASCADE
And in a nutshell, my goal would be to delete all records in table_child table where the parentId equals to the deleted row in table_parent.
Thank you for your help and have a nice day :)
It appears to me that what you are missing is that referential integrity constraints only work with InnoDB tables. Your DDL statements are missing the engine=InnoDB and most likely are defaulting to MyISAM.
While you will not receive an error on the declarations, MyISAM tables are by default what you get when you don't specify an engine, and MyISAM ignores constraint statements.
A corrected CREATE TABLE statement would be:
CREATE TABLE IF NOT EXISTS table_parent (
ID TINYINT(3) UNSIGNED PRIMARY KEY AUTO_INCREMENT,
`level` TINYINT(1) NOT NULL,
updated DATETIME NOT NULL DEFAULT NOW()
) ENGINE=InnoDB;
Here's a SQL Sandbox demonstrating that the constraint is correct and works as you expect it to.
This is not relevant to the question, but it seems odd to me that you declared all your keys to be TINYINTs. That would mean that you could have a maximum of 255 rows in your tables....

MySQL Performance: Single Object With Multiple Types - JOIN scenario

With the following type of table design:
http://www.martinfowler.com/eaaCatalog/classTableInheritance.html
Let's use the following schema for sake of example:
CREATE TABLE `fruit` (
`id` int(10) UNSIGNED NOT NULL,
`type` tinyint(3) UNSIGNED NOT NULL,
`purchase_date` DATETIME NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `apple` (
`fruit_id` int(10) UNSIGNED NOT NULL,
`is_macintosh` tinyint(1) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `orange` (
`fruit_id` int(10) UNSIGNED NOT NULL,
`peel_thickness_mm` decimal(4,2) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `fruit`
ADD PRIMARY KEY (`id`);
ALTER TABLE `apple`
ADD KEY `fruit_id` (`fruit_id`);
ALTER TABLE `orange`
ADD KEY `fruit_id` (`fruit_id`);
ALTER TABLE `fruit`
MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `apple`
ADD CONSTRAINT `apple_ibfk_1` FOREIGN KEY (`fruit_id`) REFERENCES `fruit` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
ALTER TABLE `orange`
ADD CONSTRAINT `orange_ibfk_1` FOREIGN KEY (`fruit_id`) REFERENCES `fruit` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
Here, 'apples' and 'oranges' are types of 'fruit', and have unique properties, which is why they've been segmented out into their own tables.
The question is, from a performance standpoint, when performing a SELECT * FROM fruit query, would it be better to:
a) perform a LEFT OUTER JOIN on each typed table, i.e. apple and orange (in practice, we may be dealing with dozens of fruit types)
b) skip the joins and perform a separate query later for each fruit row in the application logic, so for a fruit row of type apple, SELECT * FROM apple WHERE fruit_id=...?
EDIT:
Regarding the specific scenario, I won't go into excruciating detail, but the actual application here is a notification system which generates notifications when certain events occur. There is a different notification type for each event type, and each notification type stores properties unique to that event type. This is on a site with a lot of user activity, so there will eventually be millions of notification rows.
Have one table with columns for the 'common' attributes (eg, type='apple', purchase_date=...), plus one TEXT column with JSON containing any other attributes (eg, subtype='macintosh') appropriate to the row in question.
Or it might make more sense to have subtype as a common attribute, since many fruits have such (think 'navel').
What will you be doing with the "inheritance"? It's great in the textbook, but it sucks in a database. SQL predates inheritance, object-oriented, etc.

Members table with one instead of three unique fields

In almost each code example by creating mysql joinUs table, there is the code like this:
CREATE TABLE `members` (
`id` int(10) unsigned NOT NULL auto_increment,
`username` text, //unique
`email` text, //unique
`pass` text,
PRIMARY KEY (`id`)
So, if username and/or email is set as unique, what is then the purpose of id field?
Can I simply set username as primary key and exclude the id from the table?
Id is a nice convention because it will never change. That lets other tables reference users via their id, and enables you to let users change their usernames and emails. Having said that, yes, you could use username as a primary key.

How work UNIQUE + INSERT IGNORE?

I have this table :
CREATE TABLE `recent_adds` (
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
`trackid` INT(11) UNSIGNED NOT NULL,
`user` VARCHAR(255) NOT NULL,
PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
And I'd like to insert data only when the pair trackd/user is not already inserted in the table.
I know there is a sort of UNIQUE + INSERT IGNORE for this kind of problems, but in fact I don't really understand how it works.
If I do this command :
ALTER TABLE recent_adds
ADD UNIQUE INDEX unique_name (`trackid`, `user`);
where I see that these fields are UNIQUE? On the mysql code I don't see it
Also, after this, can I remove the id field?
You need to add a unique index, then use insert ignore instead of a normal insert. As for the id field, that's up to you, but I would keep it:
ALTER TABLE recent_adds
ADD UNIQUE KEY recent_adds_unique_idx (trackid,user);
INSERT IGNORE INTO recent_adds (id,trackid,user)
VALUES(NULL,...,...);

Enforce unique rows in MySQL

I have a table in MySQL that has 3 fields and I want to enforce uniqueness among two of the fields. Here is the table DDL:
CREATE TABLE `CLIENT_NAMES` (
`ID` int(11) NOT NULL auto_increment,
`CLIENT_NAME` varchar(500) NOT NULL,
`OWNER_ID` int(11) NOT NULL,
PRIMARY KEY (`ID`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
The ID field is a surrogate key (this table is being loaded with ETL).
The CLIENT_NAME is a field that contains names of clients
The OWNER_ID is an id indicates a clients owner.
I thought I could enforce this with a unique index on CLIENT_NAME and OWNER_ID,
ALTER TABLE `DW`.`CLIENT_NAMES`
ADD UNIQUE INDEX enforce_unique_idx(`CLIENT_NAME`, `OWNER_ID`);
but MySQL gives me an error:
Error executing SQL commands to update table.
Specified key was too long; max key length is 765 bytes (error 1071)
Anyone else have any ideas?
MySQL cannot enforce uniqueness on keys that are longer than 765 bytes (and apparently 500 UTF8 characters can surpass this limit).
Does CLIENT_NAME really need to be 500 characters long? Seems a bit excessive.
Add a new (shorter) column that is hash(CLIENT_NAME). Get MySQL to enforce uniqueness on that hash instead.
Have you looked at CONSTRAINT ... UNIQUE?
Something seems a bit odd about this table; I would actually think about refactoring it. What do ID and OWNER_ID refer to, and what is the relationship between them?
Would it make sense to have
CREATE TABLE `CLIENTS` (
`ID` int(11) NOT NULL auto_increment,
`CLIENT_NAME` varchar(500) NOT NULL,
# other client fields - address, phone, whatever
PRIMARY KEY (`ID`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `CLIENTS_OWNERS` (
`CLIENT_ID` int(11) NOT NULL,
`OWNER_ID` int(11) NOT NULL,
PRIMARY KEY (`CLIENT_ID`,`OWNER_ID`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I would really avoid adding a unique key like that on a 500 character string. It's much more efficient to enforce uniqueness on two ints, plus an id in a table should really refer to something that needs an id; in your version, the ID field seems to identify just the client/owner relationship, which really doesn't need a separate id, since it's just a mapping.
Here. For the UTF8 charset, MySQL may use up to 3 bytes per character. CLIENT_NAME is 3 x 500 = 1500 bytes. Shorten CLIENT_NAME to 250.
later: +1 to creating a hash of the name and using that as the key.