Array association and DB design - mysql

I'm trying to create a shopping cart sort of DB, where users can checkout certain items and I would be able to see what items each person has and I would also be able to see who a specific item is checked out to.
I would also like to have an image for each item. (not sure how efficient that is?)
Currently I have something like this:
CREATE TABLE person(
id CHAR(9) NOT NULL PRIMARY KEY,
name VARCHAR(30) NOT NULL
);
CREATE TABLE items(
id CHAR(9) NOT NULL PRIMARY KEY,
itemName VARCHAR(30) NOT NULL,
category VARCHAR(30) NOT NULL,
subcategory VARCHAR(30) NOT NULL,
image LONGBLOB
);
CREATE TABLE person_items(
personID CHAR(9) NOT NULL,
itemID CHAR(9) NOT NULL,
FOREIGN KEY (personID) REFERENCES person(id),
FOREIGN KEY (itemID) REFERENCES items(id)
);
Is this an efficient way to basically store an array of items that a person is allowed to check out, or are there better ways?
Also, is storing a LONGBLOB for an image a good idea or is there a better way to do that?

First of all your IDs in your tables should be INTEGERs. The relation table 'person_items' enables a n:m relation between person and items, which should be your goal, if I understood your question.
I suggest to save a path and the image file name in your db, so that you can get this value and use it as link or something similar in your app. I would not save the image as a blob cause you have a lot of unneccesary work with headers and so on. And if using a path in the db, you will easily be able to use different file formats. Just my opinion.

Related

Convention for IDs of child tables

Every tutorial that I watched implemented child tables with two IDs, one ID for the table itself, and one ID that was just a reference to the parent's table ID, like so:
CREATE TABLE Car (
vin INT NOT NULL PRIMARY KEY,
person_ssn INT NOT NULL,
FOREIGN KEY (person_ssn) REFERENCES Person(ssn) -- Person's primary key
);
In my project, I'm doing a discord bot, and the only identifier that I need is the server's ID. There's no need for the child tables to be identified by something else than the server's ID, like so:
CREATE TABLE Server (
id VARCHAR(25) NOT NULL PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
CREATE TABLE configuration (
server_id VARCHAR(25) NOT NULL PRIMARY KEY,
FOREIGN KEY (server_id) REFERENCES Server(id),
channel_to_message_id VARCHAR(25) NULL,
master_role_id VARCHAR(25) NULL
);
So, am I wrong in making the primary key also the reference ID to the parent table? Is the "dual ID" method a convention?
If the configurations are a weak entity, which seems plausible, your implementation is right.
Weak entities occur relatively seldom, that's why you may not have seen such in a tutorial yet.
But they exist and if the configurations are weak entities according to the logic of your model (only you can judge that in the end), everything is OK.

How can i join another table with the primary of the other

I am creating an application like trello for that i am using MySQL as an database till now i have created authentication system using MySQL and express,node js now i want to create table for cards to save the data so, i want to know how can i link the users data to the users name.
I have created a table users with the following field id(primary key, auto_increment),name,email,password
now i want to create a table card in which the users card would be present so how can i link user table column correspond to the particular
use, thanks in advance really new to backed
Maybe this lines of code can help you out a little. To get a better grasp of the topic.
-- This statement creates the cards table you may want to use (alternatively see Barmars Comment, this maybe a more professional solution)
CREATE TABLE Cards (
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
customer_id INT,
firstname VARCHAR(30) NOT NULL,
lastname VARCHAR(30) NOT NULL,
email VARCHAR(50)
)
-- This statement then "connects" the tables. It makes the customer_id in the cards table a foreign key of the primary key of the customers table.
FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
After implementing this you can use JOIN in your queries to query multiple tables.
If you want more info, this video can help you understand the topic:
https://www.youtube.com/watch?v=USaXlErI-QE

table creating regarding social networking post

I want to design structure for posting image,video,url, audio,text etc for users.
I have create
CREATE TABLE users (
userID INT NOT NULL AUTO_INCREMENT,
firstName VARCHAR(50),
lastName VARCHAR(50),
password CHAR(32),
PRIMARY KEY (userID)
);
CREATE TABLE post(
postID INT NOT NULL AUTO_INCREMENT,
message VARCHAR(200)
PRIMARY KEY (postID));
MY question is should I design different tables for storing image,video,url etc
like
Image table
CREATE TABLE post_image(
imageID INT NOT NULL AUTO_INCREMENT,
imgPATH VARCHAR(200)
PRIMARY KEY (imageID));
same of video,link etc.
Or it can be done only in single table.
I've seen this done two ways.
You create a generic "asset" table that stores all possible things that could be attached to a post. Videos, images, URLs, etc.
Create a separate table for each asset type. A post_image table, post_comment, post_video, etc.
I prefer (2) only because the asset types will be pretty different from each other. Think of storing information about a video. You have the video duration, whether or not to auto-play, etc. Images will never have those properties.
So even though you could put all those things into one table, I would strongly recommend not to do it.

mysql - referencing one foreign key to multiple possible primary keys

I'd like to set up the following database scenario:
CREATE TABLE IF NOT EXISTS `points` (
`po_id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`po_north` INT,
`po_east` INT,
PRIMARY KEY (`po_id`),
) ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `lines`(
`li_id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`li_from` INT NOT NULL,
`li_to` INT NOT NULL,
PRIMARY KEY (`li_id`),
FOREIGN KEY (`li_from`) REFERENCES points(`po_id`),
FOREIGN KEY (`li_to`) REFERENCES points(`po_id`),
) ENGINE=InnoDB;
Now I want to set up a third table, that sores some metadata like who created or altered a point or a line:
CREATE TABLE IF NOT EXISTS `metadata` (
`me_type` ENUM('point','line') NOT NULL,
`me_type_id` INT UNSIGNED NOT NULL,
`me_permissions` VARCHAR(255) NOT NULL,
`me_created_by` INT UNSIGNED NOT NULL,
`me_created_on` DATETIME NOT NULL,
`me_last_modified_by` INT UNSIGNED NOT NULL,
`me_last_modified_by` DATETIME NOT NULL,
) ENGINE=InnoDB;
My first approach was to set an ENUM with two types (points and lines). But the problem is still, that I cannot properly reference a foreign key to one of the tables. Is there any recommended solution for such problem in MySQL?
BTW:
The fields for me_created_by and me_last_modified_by shall reference to a table storing some user data.
Your case appears to be yet another instance of the design pattern known as "generalization specialization" or perhaps "table design for class inheritance".
If you think of points and lines as classes of objects, they are both subclasses of some more general class of objects. I'm not sure what name to give the superclass in this case. Here's one of several previous questions that address the same issue.
Extending classes in the database
Fowler gives an extensive treatment of the subject. Your case has an added wrinkle, because you are dealing with metadata. But that need not alter the design. You need a third table, which I'll call "Items" for lack of a better term. The key, "it_id" would be assigned an auto number, and you would add an item every time you add either a point or a line. The two columns "po_id" and "li_id" would not be assigned an auto number. Instead they would be foreign keys, referencing "it_id" in the Items table.
The references to points or lines in the metadata table would then be references to "items" and you could use that information to find information about points or lines as the case may be.
How helpful this is depends on what you are trying to do with the metadata.
Your tables points and lines should contain a foreign key to metadata – not the other way around. Doing so will save you from defining any more complicated table setups. Using this approach, a single metadata-entry could be re-used several times for many different points or lines. This isn't even MySQL specific but a general, normalized database structure.
you can do this using a trigger, you need to trigger an event that can create reference key for either point or line before you insert a record based on respective tables

How do you create a constraint on parent tables that also constrains the child tables?

I am not sure how to phrase the question so I'll illustrate the tables and the explain what I want to achieve.
-- static table of the entity classes supported by the application
create table entity_type (
id integer not null auto_increment,
name varchar(30) not null,
primary key(id)
);
-- static table of statuses supported by the application
create table entity_status (
id integer not null auto_increment,
name varchar(30) not null,
primary key(id)
);
-- table of valid combinations
create table entity_type_entity_status_link (
entity_type_id integer not null,
entity_status_id integer not null,
unique key(entity_type_id, entity_status_id),
foreign key(entity_type_id) references entity_type(id),
foreign key(entity_status_id) references entity_status(id),
);
-- The tables where user types and statuses are defined
create table user_type (
id integer not null auto_increment,
name varchar(30) not null,
entity_type_id integer not null,
primary key(id),
foreign key(entity_type_id) references entity_type(id)
);
create table user_status (
id integer not null auto_increment,
name varchar(30) not null,
entity_status_id integer not null,
primary key(id),
foreign key(entity_status_id) references entity_status(id)
);
-- table of valid pairs
create table user_type_user_status_link (
user_type_id integer not null,
user_status_id integer not null,
unique key(user_type_id, user_status_id),
foreign key(user_type_id) references user_type(id),
foreign key(user_status_id) references user_status(id),
);
The basic premise behind these tables is that the system supports core types and statuses and the user is able to create their own user types and statues that derive from these.
The question I have is that I cannot see a way of creating any database constraints on the user_type_user_status_link table to ensure that the you cannot insert a file_type - file_status pair where the parent entity_type - entity_status is itself not valid. Or is this something that would have to be done with triggers.
The basic premise behind these tables is that the system supports core
types and statuses and the user is able to create their own user types
and statues that derive from these.
Although that sounds like a laudable goal on the surface, the effect is to delegate database design to your users. Database design, because the effect of your desire to set foreign key references to a subset of the rows in entity_type_entity_status_link means each of those subsets is a defacto, unnamed table.
This approach never ends well.
What you've developed is the "One True Lookup Table". Google that for a host of reasons why OTLT is an anti-pattern.
The best solution is to model real things in your tables. (Entity isn't a real thing. It's an abstraction of a real thing.) Something along the lines of either
create table file_status (
file_status varchar(30) primary key
);
or
create table file_status (
file_status_id integer primary key,
file_status varchar(30) not null unique
);
would work well for file statuses.
In the case of the second one, you can set a foreign key reference to either the id number (saves space, requires an additional join) or to the status text (takes more space, eliminates a join). Note that you need the unique constraint on the status text; your original design allows the user to enter the same text multiple times. (You could end up with 30 rows where entity_type.name is 'File'.
You should use triggers for that.
MySQL does not support constraints of the form that will prevent what you want.