can't add foreign key for table that has files - mysql

I'm building a project with angular and php, I added to my database table "file" that I can send files to him and retrieve all files information. now I'm trying to add a foreign key("Customer_id") from "Customers" table to connect the customer to specific file.
But when I try to add a relation it says:
error relational features are disabled
Can any one please help?can it be that the problem because the table has files?
This is my table :
CREATE TABLE `file` (
`id` Int Unsigned Not Null Auto_Increment,
`name` VarChar(255) Not Null Default 'Untitled.txt',
`mime` VarChar(50) Not Null Default 'text/plain',
`size` BigInt Unsigned Not Null Default 0,
`data` MediumBlob Not Null,
`created` DateTime Not Null,
PRIMARY KEY (`id`)
)

Verify that the engines used in both of the tables are innoDB.
As you mentioned in chat, your files table was MyISAM, hence the Foreign Constraints were disabled!!.

Related

is a field in a fulltext key indexed and fast to use in join?

I am currently working with a database that was auto generated by a tool (and is used in production)
(I will only speak about what is interesting for the question)
I have three tables : user, movie and userMovie.
the command show create table user return something like :
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
`other_field_1` varchar(255) DEFAULT NULL, -- not actual field name
PRIMARY KEY (`id`),
FULLTEXT KEY `SEARCH_USERS` (`username`,`other_field_1`)
)
the command show create table movie return something like :
CREATE TABLE `movie` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`link` varchar(255) DEFAULT NULL,
`another_field_1` varchar(255) DEFAULT NULL, -- not actual field name
`another_field_2` varchar(255) DEFAULT NULL, -- not actual field name
PRIMARY KEY (`id`),
FULLTEXT KEY `SEARCH_MOVIES` (`name`,`link`,`another_field_1`,`another_field_2`)
)
the command show create table userMovie return something like :
CREATE TABLE `userMovie` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`Name` varchar(255) DEFAULT NULL,
`user` int(11) DEFAULT NULL,
`field1` varchar(255) DEFAULT NULL, -- not actual field name
`field2` varchar(255) DEFAULT NULL, -- not actual field name
`field3` varchar(255) DEFAULT NULL, -- not actual field name
PRIMARY KEY (`id`),
FULLTEXT KEY `SEARCH_USER_MOVIE` (`Name`,`field1`,`field2`,`field3`)
)
Obviously, there is several issue with this code, the main ones being :
There is no foreign key,
The field userMovie.Name contain the name of the movie, not the id
I'm well aware of the inconsistency risk, but I'm more ignorant about the potential performance issue. Especially, there is a lot of records in the userMovie table, and we have to join it quite often with the movie table (and the user table)
However, as userMovie.Name is in the "FULLTEXT KEY", does that mean it is indexed ?
By the way, I think that only the tool previously mentioned had an use of this, and can probably be removed if needed.
I would want to know if there is a performance issue and ways to improve it. (It would also be awesome if the modification I'll be doing are "safe", as I don't want to break anything)
The column(s) in a FULLTEXT index are usable only for MATCH...AGAINST.
If you also want a BTree index on the column(s), provide a separate INDEX.
You can do
WHERE MATCH(`Name`,`field1`,`field2`,`field3`) AGAINST("...")
AND field4 > 123
Or even
WHERE MATCH(`Name`,`field1`,`field2`,`field3`) AGAINST("...")
AND name = 'abc'
However, this second format makes little sense. Usually a column is searched by either FULLTEXT or a regular index, not both.
What is the intent of the table userMovie? The name sounds like a many-to-many mapping table (eg, which movies each user has watched), but the columns do not reflect that.
To address a "performance issue", we need to see the SELECTs -- they have performance issues, not the schema. They guide what indexes are useful.

MySQL to Postgres syntax

I am working on a maven project and for that I am using Postgres as database. Unfortunately the database I know more is MySQL. I have the basic details of SQL file which I want to include in the database. If possible, can someone with knowledge of postgres help me to convert the syntax. One more question, for maven project, do I need to include the .sql file within the project(if yes, where). Kindly let me know.
person.sql.
CREATE TABLE `Person` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL DEFAULT '',
`country` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
Thank you.
CREATE TABLE Person
(
id bigserial NOT NULL primary key,
name varchar(20) NOT NULL DEFAULT '',
country varchar(20) DEFAULT NULL
);
More details in the manual: http://www.postgresql.org/docs/current/static/sql-createtable.html

MySQL Create table with reference to non existant table

Using MySQL workbench, I copied the create statement from a few related tables to put into a clean schema. They all reference each other in some way so there is no inherent order I can create them in. How can I just force MySQL to create the tables while ignoring any warning that may occur, just until the rest of the tables are created?
Would I have to group it inside a transaction of some sort?
A very simple example would be:
CREATE TABLE `vehicle` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`gallery_id` int(11) DEFAULT NULL,
`make_id` int(11) NOT NULL,
`model_id` int(11) DEFAULT NULL,
`make` varchar(100) DEFAULT '',
`model` varchar(100) DEFAULT '',
`colour_id` int(11) DEFAULT NULL,
`currency_id` int(11) NOT NULL DEFAULT '1',
`fuel_id` int(11) DEFAULT NULL,
`status_id` int(11) DEFAULT NULL,
`stock_code` varchar(100) DEFAULT NULL,
`registration` varchar(20) DEFAULT NULL,
`title` varchar(100) DEFAULT NULL,
`description` text,
`month` tinyint(4) DEFAULT NULL,
`public` tinyint(4) NOT NULL DEFAULT '0',
`sold` tinyint(4) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `vehicle_fk_idx` (`status_id`),
CONSTRAINT `vehicle_fk` FOREIGN KEY (`status_id`) REFERENCES `vehicle_status` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `vehicle_status` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`slug` varchar(100) DEFAULT NULL,
`title` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `slug_UNIQUE` (`slug`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;
vehicle references vehicle_status which would mean that vehicle_status would have to be created first. How would I create vehicle first and then vehicle_status without adding the reference afterwards?
You do not define foreign keys when creating tables, you would have them in a separate query like this:
ALTER TABLE `vehicle`
ADD CONSTRAINT `vehicle_ibfk_1` FOREIGN KEY (`status_id`)
REFERENCES `vehicle_status` (`id`) ON DELETE SET NULL ON UPDATE CASCADE;
So you would first create tables and then create foreign keys.
The way I personally do is I have all CREATE TABLE queries in one file that I know I can simply just import without any errors. I have all CONSTRAINT queries in a separate file that I import after all the tables have been created and I have all INSERT INTO queries in a separate file that adds data after all constraints and tables have been set.
It looks like vehicle_status is a lookup table, while vehicle is a primary transaction table.
In general, lookup tables do not reference other tables, although there can be designs where one lookup table references another lookup table. In your case, it's simple: just create vehicle_status first. If your schema has a hundred tables in it, it's going to involve a little work to order the create commands in the right sequence.
There are designs where the reference chain forms a circle. In such a case, you'll have to do what GGio suggests: add the constraints later. There are other problems with designs involving circular references, and those problems may or may not be present in your schema.
When you go to populate the tables, you'll have to worry about order as well. In general, you'll have to populate the lookup tables first, before you begin to populate the transaction tables. Otherwise you'll get reference violations at load time.

Relation Between Two Tables: make relationship between two tables

I have two tables as post and gallery, and i have made a relationship gallery to post table.
My requirement is,
When user upload content it store in the post table(content field) ,
If user upload the images are video i want to store the images/video name in, gallery table and the gallery id refers to the post table. I dont know how to do it. please any one help me?
post table:
CREATE TABLE IF NOT EXISTS `post` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) unsigned NOT NULL,
`gallery_id` bigint(20) unsigned NOT NULL,
`content` longtext,
`photo` varchar(128) DEFAULT NULL,
`video` varchar(128) DEFAULT NULL,
`created` timestamp NULL DEFAULT NULL,
`updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `fk_forum_post_user` (`user_id`),
KEY `fk_forum_post_gallery` (`gallery_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=10 ;
ALTER TABLE `post`
ADD CONSTRAINT `fk_post_gallery` FOREIGN KEY (`gallery_id`) REFERENCES `gallery` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
gallery table
CREATE TABLE IF NOT EXISTS `gallery` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) unsigned NOT NULL,
`type` int(11) NOT NULL DEFAULT '1' COMMENT '1- Photo, 2-Video, 3-Documents, 4-Unknown',
`profile_picture` varchar(50) DEFAULT NULL,
`forum_image` varchar(200) DEFAULT NULL,
`forum_video` varchar(200) DEFAULT NULL,
`forum_video_link` varchar(200) DEFAULT NULL,
`created` timestamp NULL DEFAULT NULL,
`updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `fk_gallery_user` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=60 ;
is any other idea is to do or how can i move forward?
There are a lot of ways you can perform this tasks. you can perform logic on code level as well as on database level. however here is a quick answer . hope this could help you
First Remove the column (gallery_id) as it is possible that user may have more than one images or video for single post or user may not want to upload any image / video in this case your gallery id would be null.
In this case your Pk would be only postId
your gallery table is fine
Make a third table name PostGalleryRealation
make 2 column in this table PostId as fk from post table and galleryid as fk from gallery table.
this is basically for one to many relation as one post may have more than one gallery
insert the post id and gallery id in PostGalleryRealation table
Finally you can write this query to fetch the result for you.
I did not test the query, so it's just a basic idea
Select p.id, p.content, p.created, g.type, g.profilepicture, g.forum_image
from post p, gallery g, postgalleryrelation pgr
where p.id = pgr.postid
and g.id = pgr.galleryid
and p.id = 1
It's just an idea. You can do much better.
YII have relation option while creating CRUD using gii. For that, you have to create tables with foreign key relationship. So YII will automatically create the relation in coding level. You have to choose the option Build Relation while creating model for both tables.
Check the Yii relation tutorials for more information

MySQL implementing tables into database

I have to implement the tasks below:
Task:
At present, the database knows two types of messages:
Messages that a user posts and that are public for anyone and everyone to read
Messages that a user posts and that are non-public. These messages can only be read by users that the posting user has marked as friends.
In this step, you should add a third type of message. This third type of message should be readable by specified recipients only.
This means the database needs to provide the following:
A way of distinguishing between the three types of messages. This involves a change to the Message table.
A way of specifying who the recipients of a particular message are. This will probably require an additional table.
All this must again be achieved with minimal amount of storage, i.e., you must choose the appropriate data types from the MySQL manual. You may assume that the total number of messages that are added over time may reach 1,000,000,000.
Your job is to implement the necessary changes and additional table for this purpose and any keys and foreign key relationships required.
Here are my two tables first : User
CREATE TABLE IF NOT EXISTS `User` (
`user_id` int(10) unsigned NOT NULL auto_increment,
`given_name` varchar(60) default NULL,
`surname` varchar(60) default NULL,
`address` varchar(255) default NULL,
`city_id` int(10) unsigned NOT NULL,
`date_of_birth` datetime default NULL,
`email` varchar(80) default NULL,
PRIMARY KEY (`user_id`),
KEY `ix_user_surname` (`surname`),
KEY `ix_user_given_name` (`given_name`),
KEY `ix_user_name` (`given_name`,`surname`),
KEY `ix_user_date_of_birth` (`date_of_birth`),
KEY `ix_user_email` (`email`),
KEY `ix_user_city_id` (`city_id`)
) ENGINE=InnoDB
2nd table :Message
CREATE TABLE IF NOT EXISTS `Message` (
`message_id` int(10) unsigned NOT NULL auto_increment,
`owner_id` int(10) unsigned default NULL,
`subject` varchar(255) default NULL,
`body` text,
`posted` datetime default NULL,
`is_public` tinyint(4) default '0',
PRIMARY KEY (`message_id`),
KEY `ix_message_owner_id` (`owner_id`)
) ENGINE=InnoDB
MY SOLUTION: I was thinking of creating a new table called 'Message_level' and have columns 'message_level_id'(will refer to 1,2,3 as 1=public, 2=private, 3=specific) & 'message_level'(where it would state public,private and specific next to level). Then I can use the 'Message_level' as a foreign key into the 'Message' table and replace the 'is_public' column with 'message_level_id'.
Is my approach to this question right? is there another way I can do this to make it more efficient?
and how would I approach the second task of specifying who the recipients of a particular message are?
I would go like this:
User: user_id, given_name, ...
Message: message_id, owner_id (fk User), subject, body, posted, message_type_id (fk Message_type)...
Message_recipients: user_id (fk User), message_id (fk Message)
Message_type: message_type_id, description (1:public, 2:friends, 3:specific_recipients)