I am trying to figure out how to structure this database. I have used Apple's core data before just fine, I'm just working on a different project now that requires MySQL. I am very new to MySQL so please go easy on me. :)
For this example, let's say I have three tables, User, Device, and Location. Drawing it out, a Location can have many Devices, but the Device can only have one Location; Each User has its primary key, UserID, of which I need to use to fetch the correct information.
So how do I create a relationship like this here? I've heard of creating an index and a foreign key and I'm not sure how they work exactly.
In the end, what I need to do is be able to access the User's specific table and view all of the Locations associated with that User. I will also need to be able to add a Device at a certain Location for a certain User.
Again, please forgive me as I'm trying to wrap my head around MySQL. I am using HeidiSQL to do my database editing.
User - Device is a many-to-many relationship, so you'll want to introduce an intermediary table to resolve that relationship. That table simply consists of two foreign keys, one referencing the User table and one referencing Device. Device - Location can be handled with a simple foreign key in the Device table pointing to a Location table.
Related
Let us say I need to design a database which will host data for multiple companies. Now for security and admin purposes I need to make sure that the data for different companies is properly isolated but I also do not want to start 10 mysql processes for hosting the data for 10 companies on 10 different servers. What are the best ways to do this with the mysql database.
There are several approaches to multi-tenant databases. For discussion, they're usually broken into three categories.
One database per tenant.
Shared database, one schema per
tenant.
Shared database, shared schema. A tenant identifier (tenant key) associates every row with the right tenant.
MSDN has a good article on the pros and cons of each design, and examples of implementations.
Microsoft has apparently taken down the pages I referred to, but they are on on archive.org. Links have been changed to point there.
For reference, this is the original link for the second article
In MySQL I prefer to use a single database for all tenants. I restrict access to the data by using a separate database user for each tenant that only has access to views that only show rows that belong to that tenant.
This can be done by:
Add a tenant_id column to every table
Use a trigger to populate the tenant_id with the current database username on insert
Create a view for each table where tenant_id = current_database_username
Only use the views in your application
Connect to the database using the tenant specific username
I've fully documented this in a blog post:
https://opensource.io/it/mysql-multi-tenant/
The simple way is: for each shared table, add a column says SEGMENT_ID. Assigned proper SEGMENT_ID to each customer. Then create views for each customer base on the SEGMENT_ID, These views will keep data separated from each customers. With this method, information can be shared, make it simple for both operation & development (stored procedure can also be shared) simple.
Assuming you'd run one MySQL database on a single MySQL instance - there are several ways how to distinguish between what's belonging to whom.
Most obvious choice (for me at least) would be creating a composite primary key such as:
CREATE TABLE some_table (
id int unsigned not null auto_increment,
companyId int unsigned not null,
..
..
..,
primary key(id, company_id)
) engine = innodb;
and then distinguishing between companies by changing the companyId part of the primary key.
That way you can have all the data of all the companies in the same table / database and at application level you can control what company is tied to which companyId and determine which data to display for certain company.
If this wasn't what you were looking for - my apologies for misunderstanding your question.
Have you considered creating a different schema for each company?
You should try to define more precisely what you want to achieve, though.
If you want to make sure that an HW failure doesn't compromise data for more than one company, for example, you have to create different instances and run them on different nodes.
If you want to make sure that someone from company A cannot see data that belong to company B you can do that at the application level as per Matthew PK answer, for example
If you want to be sure that someone who manages to compromise the security and run arbitrary SQL against the DB you need something more robust than that, though.
If you want to be able to backup data independently so that you can safely backup Company C on mondays and Company A on sundays and be able to restore just company C then, again, a purely application-based solution won't help.
Given a specific DB User, you could give a user membership to group(s) indicating the companies whose data they are permitted to access.
I presume you're going to have a Companies table, so just create a one-to-many relationship between Companies and MySQLUsers or something similar.
Then, as a condition of all your queries, just match the CompanyID based on the UserID
in my file Generate_multiTanentMysql.php i do all steps with PHP script
https://github.com/ziedtuihri/SaaS_Application
A Solution Design Pattern :
Creating a database user for each tenant
Renaming every table to a different and unique name (e.g. using a prefix ‘someprefix_’)
Adding a text column called ‘id_tenant’ to every table to store the name of the tenant the row belongs to
Creating a trigger for each table to automatically store the current database username to the id_tenant column before inserting a new row
Creating a view for each table with the original table name with all the columns except id_tenant. The view will only return rows where (id_tenant = current_database_username)
Only grant permission to the views (not tables) to each tenant’s database user
Then, the only part of the application that needs to change is the database connection logic. When someone connects to the SaaS, the application would need to:
Connect to the database as that tenant-specific username
I'm trying to design a system for giving users permissions on objects. Currently I have a database schema where there are roles and each role can have a permission on multiple 'securable objects'. Such an object can be a sensor, an other user or whatever new thing we might add later. So I have a table role_permissions that links a role to a user, sensor etc. A user can also have a permission directly, so there would also be a user_permissions table that link a user directly to a user, sensor etc.
Now the field that refers to a securable object can't be a foreign key, because the target objects can be of different types and thus come from different tables.
The problem I'm facing right now is how I can make Hibernate work with this. One-to-many relations won't work here I think because Hibernate can't possibly know in which table to look.
An alternative would be to create a role_user_permissions table, a role_sensor_permissions table, a user_user_permissions talbe, a user_sensor_permissions table, and a new role_other_type_permissions table + user_other_permissions table for every securable type that's in the system. So for every single type that needs to have permissions on it I would need 2 new tables to manage the permissions.
But now the database is cluttered with permissions tables that actually serve the exact same purpose but for different types. However, Hibernate IS happy to take this because through foreign keys it always knows what table to look in and what type the object is.
Does anyone know a best practice to solve this issue?
Thanks in advance,
Stan
I have one question regarding database design.
Here is the first example:
User may have a multiple Websites, and user can request specific resource for every of his websites. All requests are saved in RequestForResource table.
Now, if I want to see the name of an user who requested a resource, I have to join tables RequestForResource Website and table User.
To avoid this, I can make foreign key between RequestForResource and User table like it is demonstrated here:
Now, in order to get an user name, I have to join table RequestForResource and table User which is probably easier for SQL server, but at the other hand I have one foreign key more.
Which approach is better and (or) faster and why?
You can always duplicate information to gain execution speed. This is called: denormalisation. Yes, it will probably speed up the queries by lowering the required count of index seeks.
BUT
You have to write your code to make sure, that the data is consistent:
With the second design it is possible, to insert Website.User_idUser and a RequestForResource.User_idUser with different IDs for the same site! According to the design this is valid (but probably this will not satisfy your business rules).
Consider to update the foreign key constraint (or add a second one) which refers only to the Website table (User_idUser, Website_idWebsite) and remove the User-RequestForResource one.
Also consider to build a view to query your data with all the required info (probably with a clustered index).
I need to setup a MySQL database for a bugtracker, that's paired with a changelog.
Therefore I essentially have three tables: product, version, problem, problem_solution. The reason I splitted problems and their solutions is that I want to be able to provide my users with a set of possible solutions.
Now I want to add attachments to each of these tables and manage them via the database as well. There should be pictures, PDFs, ... for each product, version and possibly for each problem and solution.
Would I rather
Create 4 attachment-tables (product_attachments, version_attachments, ...), or
Create one attachment-table and create a column stating what it is for?
If latter, how should I do it? I want to reference to the specific ID of the product, version, problem or solution using a foreign key. Should I then just create 4 columns, each of them with a foreign key and decide whether it's an attachment for a product, a version, ... depending on which of these columns is not NULL? Wouldn't this make my queries unnecessarily complex?
I say create one table, have its primary key available, and create another table of EAV type for multi-to-multi relation between attachments and other entities, with "value" corresponding to attachment ID, "entity" to foreign ID and "attribute" to a value out of a fixed set of product, version, problem, solution in any form you like (1,2,3,4?). This way the attachments will be stored in a table of id, blob structure, maybe with corresponding count column storing the amount of links in the relation table, so that an orphaned attachment could be detected and removed with ease.
My questions are very simple, but I do not know an answer.
There is a table User. The User has a few photos in his profile on the site. There are at least two way to store links to photo. I can serialize an array of references to a string and store it, or create another table and store pair userId-link. Which way is better?
The user has a unique username column, email, phone. Is the following code right?
ALTER TABLE [User] ADD CONSTRAINT [LoginUk] UNIQUE CLUSTERED ([Login])
ALTER TABLE [User] ADD CONSTRAINT [EmailUk] UNIQUE CLUSTERED ([Email])
The user has the description of one car and one of the services, which he provides. Number of services and machines will not change. I can store the vehicle details (make, photos) in the profile of the user, or I can create a new table Car and create a 1-1 relationship. Similarly, I can do with the service. Which way is better?
Actually it's better to have one photos table and have a users_photos link table, then when you add photos to other entities, there's less to change.
People tend to have more than one phone number. If it's a business rule that they only have one number then leave that in the application layer, not the data layer.
One type of thing, one table for that thing. A car is a different thing than a user.