Database schema many-to-many with defaults - mysql

I am hoping someone would be willing to take a look at this many-to-many relationship. This example is for a Laravel project, but the specifics shouldn't matter too much.
action
+----+------+--------+-------------+------+--------+------------+
| id | name | script | description | icon | custom | project_id |
+----+------+--------+-------------+------+--------+------------+
pipeline(action_server this is the pivot table)
+----+-----------+-----------+-------+
| id | action_id | server_id | order |
+----+-----------+-----------+-------+
server
+----+------+------------+------------+
| id | name | ip_address | project_id |
+----+------+------------+------------+
This many-to-many relationship is used for a deployment server an action is part of a deployment's pipeline.
An action can be executed on multiple servers.
A user can add an action with a custom script.
All the actions for a deployment pipeline can be fetched through a project_id
This concept works within Laravel and I could simply fetch my actions based on a given project_id. In turn I could fetch the server actions needed to run the deployment by using action->servers().
I need a way to add default actions though. Instead of actions always having a user supplied script, I want the ability to provide actions with pre-defined scripts for a user to select from and add to a deployment pipeline.
These pre-defined actions can't be stuffed in the action table because the actions defined there are tied into a project_id. These need to be generic.
I can't simply create another table for these pre-defined actions in my current setup because the action_id in my pipeline is already set up with a foreign key.
So far it feels like I am mixing 2 concepts, which are pre-defined actions and the user-defined actions which users have created themselves. They need to be in the same pipeline and eventually run in the right order though.
Any thoughts on how this might be achieved? I am open to all suggestions.
Edit
After drawing this out it seems a possible solution would be to add another pivot table in the form of action_project which allows me to decouple(remove) the project_id from the action table. I am wondering how to keep this clean in Laravel though.
action_project
+----+-----------+------------+
| id | action_id | project_id |
+----+-----------+------------+

Summarizing your problem in a conceptual way:
applications ("projects") have associated custom actions,
standard actions are not defined for a specific application
servers have/host applications
pipelines define which "actions" to perform on which server in which order
I think what you need is simply a generalization of custom actions and standard actions, corresponding to a superclass "action" that subsumes both cases. This leads to the following tables:
actions(id, type, name, description) with type being either custom or standard
custom_actions(id, script, icon, custom, project_id)
Alternatively, you could append the attributes of custom_actions to actions and have them all NULL for standard actions.

Related

Create a new record for every user in a database based on a column

I have a MySQL database with a user table, after a new requirement I had to create a new table called social_media and from now on every new user will be created with a social_media_id column that holds a reference to their social media.
+===================+ +===================+
| user | | social_media |
+===================+ +===================+
|PK id | |PK id |
|FK social_media_id | | instagram |
| first_name | | facebook |
| last_name | | twitter |
| email | +===================+
+===================+
I want to update my database so that every user that didn't had a social media reference before gets one (even if the values inside are null), so they can update them if they wish, is there something I can do to make a new social_media record for every user that doesn't have one, and add the correct social_media_id foreign key for that user?
Ok #Jorche, this is too long to be a comment, but I do want to help.
First off, this is probably what youre data structure should look like:
Second, to be able to tell you how you enter these records is very difficult for me at this moment because I have absolutely ZERO requirements or any other business logic that would help me to help you on how to pinpoint the best approach to doing so. Odds are, you would have to work hand in hand with application developers, or ETL developers (that might even be you though) to figure out what that approach is. Maybe its a stored procedure that gets called, maybe its a trigger set up, hard to say for sure without additional context, ya know?
All we know at this point is that users exist and sometimes they have relational data related to social media entities. Your job is literally to understand that process flow and make the appropriate decisions on how to log that data in a way that makes sense from both an operational perspective and a database design perspective.
Hate to say it hombre, but the questions you have now are all entirely dependent on details you haven't provided.

Can one have optional fields in a 3NF / BCNF database?

I have a database that I am trying to set up and I would like it to be in at least 3NF. However, some fields are not necessary in all situations, and the necessity of this field, not the value itself, depends on another.
In essence, I want to keep track of jobs that are on hold for one reason or another.
My main table right now includes these fields:
Job No (primary Key) | Short Text | Storage Location | Coordinator
I have other tables for employee list and storage locations. Now my problem is if the job is in the storage location "LAB," then it will have an associated Lab Ticket number that I want to track. I will have another table of Lab Tickets that contains status, ECD, etc. If the storage location is "MR" then the job should have a Notification number, and a separate table will contain info about the Notifications.
Although a job can only have 1 storage location at any given time, it can move. For instance, if a job goes to "LAB" and fails the test, it will get moved to "MR" and have a Notification created.
Is it a violation of 3NF, or otherwise just bad form, to have my tblJobs have fields:
Job No (primary Key) | Short Text | Storage Location | Coordinator | Lab Ticket | Notification | ...
even if not all fields are populated or used for every job? BTW I'm using MS Access, though I don't think that matters.
Edit: I see the related posts about Null values, but my question is less about the programming (I can easily enter a non-null value [ex. "N/A"] in the not-applicable fields), and more on an abstract database design level: In short, is it bad form to have fields that may not apply to a majority of the records? I normally hate seeing a bunch of N/A fields in any table, but I'm starting think some well thought-out Queries will allow me to see only the relevant information for a specific subset. Ex. for all items in "LAB", show the lab number status.

Recommendations for table structure in MySQL

Hi I've got a small internal project I am working on. Currently it only serves my company, but I'd like to scale it so that it could serve multiple companies. The tables I have at the moment are USERS and PROJECTS. I want to start storing company specific information and relate it to the USERS table. For each user, I will have a new column that is the company they belong to.
Now I also need to store that companies templates in the database. The templates are stored as strings like this:
"divider","events","freeform" etc.
Initially I was thinking each word should go in as a separate row, but as I write this I'm thinking perhaps I should store all templates in one entry separated by commas (as written above).
Bottom line, I'm new to database design and I have no idea how to best set this up. How many tables, what columns etc. For right now, my table structure looks like this:
PROJECTS
Project Number | Title | exacttarget_id | Author | Body | Date
USERS
Name | Email | Date Created | Password
Thanks in advance for any insights you can offer.
What I would do is create 2 tables:
I would create one table for the different companies, lets call it COMPANY:
Company_id | Title | Logo | (Whatever other data you want)
I would also create one table for the settings listed above, lets call it COMPANY_SETTINGS:
Company_id | Key | Value
This gives you the flexibility in the future to add additional settings without compromising your existing code. A simple query gets all the settings, regardless of how many your current version uses.
SELECT Key, Value FROM COMPANY_SETTINGS WHERE Company_id = :companyId
Te results can then be put into an associative array for easy use throughout the project.

Database Schema allowing for multiple login opportunities (Facebook-Connect, Oauth, OpenID, etc.) for the same account

I want to accomplish nearly the same thing as this question, which is to store authentication data from multiple sources (Facebook, Twitter, LinkedIn, openID, my own site, etc.) so that one person can log in to their account from any/all of the mentioned providers.
The only caveat being that all user data needs to be stored in a single table.
Any suggestions?
If there is no clean way to accomplish this, is it better to have tons of columns for all of the possibly login methods or create additional tables to handle the login methods with Foreign Keys relating back to the user table (as described in this answer)?
perhaps you want to create a table dedicated to the account types, along with a table for the actual user.
Say you have a users table with an auto_increment uinique ID for each user. Then, you want to create another table example: user_accounts, with it's own auto_icnrement ID, another column for relational ID (to the users table and a 3rd (or/and) 4th table for account type / extra data for authentication if needed.
You then insert a record for each account type for each user. Basically it may look like this:
user_accounts
| ID | User_ID | account_type | authentication
| 1 | 1 | facebook | iamthecoolestfacebookerever
| 2 | 1 | google | mygoogleaccount
In it's most simplistic form. you will probably be storing much different data than that, but hopefully you get the point.

Which way is better to implement custom fields in a web application

I have a self made web application in PHP and MySQL. The many different clients using my system would like to augment entities with custom fields. Each client would like to store their own additional data, so this should be done in a dynamic way.
For example client1 would like to add the "color" property to their products, client2 want a field called "safety_level" for their products.
I want a methodology that can be applied not only for products but for users and for any other entities as well.
Here are 2 options I found the optimal, but can't decide which one is the most effective:
OPTION 1:
For every entity I make a [entityname]_customfields table in which I store the additional field values in 1:1.
e.g.:
+---------------------------------------------+
|products_custom_fields |
+---------------------------------------------+
|product_id (PK and FK related to products.id)|
|safety_level |
|some_other_fields |
+---------------------------------------------+
pro: this table can has no more records than the entity table (in this case the products) which means fewer records and it is quite easy to overview.
con: adding new fields or deleting old ones require DDL queries. I don't want to confide DDL to users...not even operators with admin permissions.
OPTION 2:
[entity]_custom_field_values will have N:1 relations to [entity] table. Each row contains the the type of the custom field and the value itself. In this case we need another table which contains the custom field types. e.g.:
custom field values:
+----------------------------------------------------------------------+
|products_custom_field_values |
+----------------------------------------------------------------------+
|custom_field_id |
|custom_field_type (FK product_custom_field_types.custom_field_type_id)|
|value |
+----------------------------------------------------------------------+
custom field types:
+---------------------------------------------------------+
|products_custom_field_types |
+---------------------------------------------------------+
|custom_field_type_id (PK AUTO_INCREMENT) |
|product_id (FK related to products.id) |
+---------------------------------------------------------+
pro: managing fields is easy, does not require to alter table structures
con: more records, all kind of custom field values in a big mess...which is not necessary wrong, because that's the point of MySQL, to extract useful data from a big mess. The question is what about efficiency and performance?
Note: this topic is actually covered in the "SQL Antipatterns", which I strongly recommend you read
I am a lazy person, which means that I tend to apply YANGI to my code. So this is my approach.
So. Let's assume that there are two groups of products:
ProductFoo ProductBar
- productID - productID
- name - name
- price - price
- color - supply
- weight - manufacturerID
- safety
In this case there are three common elements, that go in the main Products table. And the custom parameters would be stored using table inheritance (it's a thing, google it). So, basically you would end up with three tables: Products, ProductsFoo and ProductsBar, where Products table has a "type" field and both of the "child tables" would have a productID foreign key, that's pointing to its parent table.
That's if you know at the development time, what "custom fields" each client will want.
Now, lets assume clients are being difficult and want make up custom fields whenever they feel like it.
In this case I would simply create a Products.data fields, which contains a JSON with all the custom attributes for each product. And only "extract" special attributes to an inheriting table, when client wants to search by that custom attribute (there is not sane way to index JSON, if clients want to search by their new "wallywanker" attribute).
You end up with same basic structure, but the "sub-tables" only contain the attributes, that are expected to be searchable
I hope this made sense.
If its is a company project, follow the standards followed on previous projects.
Have a look at conventions such as Hungarian notation, that would make more sense than repeating a prefix. Also it is more likely your model name is your table name.
Also if you are planning to use ORM they might have some best practices as well.
https://en.wikipedia.org/wiki/Hungarian_notation