I am building a custom field feature for my application. This allows the administrator to add custom profile fields for users to fill in depending on the site's needs.
The schema is simple
field_meta (store some metadata about the field)
================================================
id
type //type of field
field_name //name of the field in the fields table
render_data //Some data to use when rendering the form field
field
===================
id
name //Default field that can't be deleted
address //Default field that can't be deleted
customfield_1
customfield_2
The field_meta table is used to store some meta data for the field, so that we can render the form fields.
Each field is then stored in a new column in the field table.
Problem:
For usability and to not have to deal with users choosing reserved words or using non-english words for the column name, I will not be asking users to choose a name for the column name.
I am currently considering calling the column name by field type (there are quite a few types in the application (email, website, text, paragraphtext, etc), just to name a few) and adding a number. Some examples:
Email_1
Text_1
Text_2
Text_3
Email_2
etc
However, the problem with this approach is that it takes a fair bit of work to come up with the column name. I need to get all the columns, pick out the ones with the same column type as I am creating, parse for the largest number, and then create the column.
Is there a better strategy to do this? Or perhaps a totally different way to name the columns that eliminates these problems?
Don't try to dynamically add columns, that's a slow (and not good form) method.
Instead, store the extra columns in a new table, each with their own ID. Then have another table that stores a user ID, the extra column ID, and the attribute information for that user. This would imitate adding new columns without actually having to do so.
Edit:
Indeed it does sound like EAV. Schema:
Attributes{id:int, name:string}
Users{id:int, name:string, (any others needed…)}
Users_attributes{Attribute_id:int, User_id:int, Attribute_info:string}
Then just input any new attributes into Attributes (with incrementing ID), and any new user information into User_attributes with the appropriate User_id and Attribute_id.
I decided to go with my original approach, that is to basically create a column name consisting of the type and an incremented number:
Email_1
Text_1
Text_2
Text_3
While it takes a fair bit of effort to generate the name, this is only done when creating the profile fields, so the performance hit would only occur during that time.
Related
I have to develop this database for my work and one part of it is that I have 4 different types of members that need to available to the system: Students, Parents, Mentors, and Coaches. Each have different information associated, so they all have their own table. Another table is a "notes" table that I want to be able to attach and unlimited number of notes to each member.
So for each table, there is a formatted autonumber. For students this number should be S#### in an incremental order. It doesn't matter the number and there will be far fewer than 9,999 students so I'm confident that's all I'll need. Then there's also P#### for parents, and so on.
It needs to be this way because the database also houses survey questions and responses. My notion is that survey responses can be uniquely identified by the member_ID, year, and term taken (since they're only open certain times). The problem is that without the formatted autonumber being found in the query, then ID's will be repeated and non-unique.
So my question is, does format autonumber not work? Am I going to have to use some VBA to build my own autonumbered string that will carry over through queries and other table lookups?
EDIT: So HansUp (below) suggested using a master list that the member tables feed off of. I've set this up since I haven't thought of an alternative. Basically, the flow is this:
Database user clicks "New Student"
"new student" form opens, along with "new member".
"new member" form creates a new ID # and assigns S group, sets viability off
Concatenated ID is then passed to "New student" form
If OK, then all changes are comitted
If cancel, then DoCMD.Undo for both new student and new member.
Would this do it? I'm not exactly sure how to pass that undo statement to the "New member" form though...
Leave the auto-number field as it is. it won't help you even if it does to your current business requirement it will create problem once your application grows further.
Use GUID/UUID to overcome database-level (or even global level) unique ID issues. This way you will maintain an unique ID throughout your database which will help in your case to have only one "notes" table for all of your entities.
in short:
Add a GUID field in your tables
Use triggers or public function/macro to generate the GUID
try to merge students, parents, mentor & coach into one table by separating them by "Type"
Remember an auto-number field is not continuous (in case if some records get deleted the gab will be there)
you can always perform string concatenation/format to produce S12355 number in your query to present it to your end-users.
I guess your main goal is to use only one note table for all of your users. GUID would be the way to go.
here some starting point: How can I generate GUIDs in Excel?
From another question of mine:
What I need to achieve is this: Create multiple categories with their
own designated information fields (ie. Cars have different fields from
Pets) and once such a category is created, the commands I need will be
invoked and a new table for each category will be made. I know I could
store all fields as some sort of string and then process it to display
it properly, but I need a advanced search function for my web app and
creating separate tables for each category seems the best way to
achieve it. I would really like to hear alternatives for this
So I have this situation where I need categories to hold all input fields needed for that certain category. So in administration I'd have this form where I'd be able to add the category name, some other relevant information to the category itself, and then these fields that would collect information on what HTML fields to present to the user when making an entry to this certain category.
For example this would be a Dog category:
Category name: Dog
Category enabled: 1
Category parent: Pets
Fields:
Title - text field (will be auto added to each category)
Breed - select field
Age - number field
Color - text field
Price - number field (will be auto added to each category)
Description - text area field (will be auto added to each category)
So now at this stage when the user created all these certain fields for the Dog category, Im having trouble figuring what would happen when the user hits the submit button to save this category. I thought of these two solutions:
Create a new model/table for each new category (Read linked question above) with all the HTML fields as columns and also store a row on the categories table with some basic info about this category
Store everything in the categories table and have a fields_json column which will store all HTML field information (I wont be actually storing HTML, but basic info what the fields are about then create the HTML form fields dynamically in a controller) as a JSON string. I would be able to present the fields nicely on create, but on update it would be a hassle to populate those fields (maybe) and a search function would not be very efficient with this alternative.
So what I'm looking for is a third alternative so I can fix my problem. What would be an efficient way to solve this problem and be able to have categories with different input fields and also be able to efficiently perform searches on these categories?
The project I'm working on is being created in Ruby on Rails 4 and the database is in MySQL.
For given scenario I would:
create table categories to store each category
create table category_fields to store each category field
create table collected_categories to store all collected data from category fields in serialized hash
Collected data can be easily (de)serialized into text column (no matter of db engine you will use).
Check those sources which utilize your problem: dynamic forms
I have a MySQL table that stores user emails:
user_id | user_phonenumber
----------------------------
id1 | 555-123456789
I want to allow the user to store multiple phonenumbers and I don't want to limit the number of numbers a user can be associated with.
What's the best way of structuring my data, and how would a query work in PDO?
For example, should I store them all in the same field with comma separators and then parse the output when the query is returned, or should I use another table and have each row as a separate number with common user_ids? How would a lookup work then (please provide example code if possible)?
Thanks
Generally RDBMS systems are designed to access fields/rows. Everything will be much harder when you start to break the data-field link/consistency/logic.
I mean when you start to store more data in a single field.
But you know your system's future. It can happen that you won't ever have to access for example the first phone number, and if you can handle it everywhere as a blob then it can be fine to store more values in a single field.
Anyway If this is not a homework or similar short living task then you should choose the 1 phone number/1 record approach.
I mean something like this can be future proof:
create table user_phonenumbers(
id auto_increment primary key.
user_id integer references user(id),
phonenumber varchar(32)
);
Yes, use another table to store user phone numbers.
use inner join to lookup, it would be good.
I have a fairly simple database that I inherited. For the purposes of this question, there are two tables:
Mastertable and Providertable.
Mastertable references Providertable thruogh provid, which is a FK to Providertable PK (provid).
So it looks like this:
Mastertable:
acct (PK)
(other fields)
provid (FK)
Providertable
provid (PK)
provname
provspecialty
Simple right? However, the Mastertable!provid field is actually a lookup table which displays Providertable!provname but stores provid. There is a form the users use to populate the Mastertable, and it has this lookup field shown.
The users now want to show the provider specialty based on what they select as the provid. I can't figure this out to save my life. I'm pretty well versed in SQL, having written many stored procedures and created a few db apps using .NET, but this is quite challenging. I tried creating a lookup field called provspeciality, but that's not what they want. I tried changing the "OnUpdate" event for the lookup field to point the Provider Specialty label to the right thing.
Right now, I can't even get a simple select going that joins the two tables since they are using this lookup field as the FK and Access I guess can't understand it. Any help appreciated.
Since the Mastertable provid field is a lookup type, the displayed value is the lookup value rather than the value which is actually stored in the field. This query will show you the stored provid values.
SELECT acct, provid
FROM Mastertable;
And I think you should be able to retrieve the matching provider specialties with a query similar to this:
SELECT m.provid, p.provname, p.provspecialty
FROM
Mastertable AS m
INNER JOIN Providertable AS p
ON p.provid = m.provid;
You may even be able to use that query as the Row Source for a combo or list box on your form. Make provid the bound column. You may wish to set the provid column width to 0" so it is not actually displayed in the control, but still stored in Mastertable.
I think you should modify the table to make provid a normal (numeric?) field instead of a lookup. Fortunately you indicated this is "fairly simple database", so that will hopefully limit the amount of additional changes you need to be compatible with the redesigned table. Good luck.
I created an "On Change" event for the form field "provid" which is a lookup field that displays the provider name while putting the provider id into the master table as a FK. However apparently Access is not able to do lookups based on this field (or I am doing something wrong) using queries - as shown above in comments. What I did is use this as the event code. Important, you must enable macros for this to work!
Private Sub provid_Change()
Me.txtProviderSpecialty = DLookup("Provspecialty", "Providertable", "provid = " & Me.provid.Value)
End Sub
I am currently building a small crm application. I need each user to be able to define their own custom fields. I am currently building this crm using php and mysql.
Example: I have a "customer" table which has the standard fields: name, phone, address, email, etc. But i want to allow the user (unique session) to add fields that are custom to his/her business which are only accessible to him (not other users). I then want these custom fields to function just like all the other fields in the table (ability to search, send and received data). I am hoping i can accomplish this in mysql and php but am open to any technology or solution that is considered best practice. Thank you for your help.
This can be done by creating a table called "customfields" with the elements "id, fieldname, company_id", then another table that would associate those custom fields with data, eg "customercustomdata: id, customfields_id, customer_id". Associate "ownership" of a field the same way
To create a new custom field, "insert into customfields (fieldname,company_id) values ('Birthday',companyid);"
Does that help?
#Matt H: Is this method considered AEV or just standard relational db?
So because i will have many users in many dif industries that will want to add their own custom fields to a number of different tables (contacts, transactions, events, etc) i am assuming that i would need the customfield table to have a user_fk/id or company fk/id, a related table fk/id, an id, and a field name? Am i on the right track? Then in the need to create a 2nd table to hold the data for each custom field buy having a customfield fk/id, customer fk/id, id and a data field to hold the actual data. Is this correct?
Ok so once i build those two additional tables how do I add them to the contacts table so it looks like one big table for the user, instead of the 3 tables?
Thanks again for you help.
Answer
after much research i have found that most people who wish to accomplish this are using document databases not relational databases.
You could place an extra column for storing string data and store an array describing the contents for custom cells. For example:
$custom = array(
array("field" => "bikesOwned", "value" => 4),
array("field" => "travelled", "value" => 14)
);
then use something like PHPs json_encode to store that data in the extra cell. Then all you would need to do is decode and process the array.
Some people suggesting using the Entity-Attribute-Value design, but before you do, please read Bad CaRMa, a story about an EAV-like design that nearly destroyed a company because it was unmaintainable.
To solve this better, read How FriendFeed uses MySQL to store schema-less data. You can lump all the custom columns into a single BLOB, and store it that way. Then if you want individual attributes to be searchable, create a table for that attribute, that maps values back to the customers table.