I have a table called "games" in which will have games.id, games.name and games.modus fields. I know the ID should be auto increnment and integer, games.name a text value and the problem is I don't know what to make games.modus, because it will have "multiple options", another tables called "modes" will be created with modes.id and modes.name, the modes.name will have the following rows: "Singleplayer","Multiplayer","LAN","Online","LAN Co-op","Online Co-op","Offline Co-op",
and I need to be able to select multiple of those rows into the "games.modus" field. How would I achive this?
What you are describing is an N-to-N relationship. You need to model a third table so that you can have an 1-to-N and an N-to-1 relationship. N-to-N cannot be modeled otherwise, to my knowledge.
In your case, that means that you would need a table like modes_per_game which would contain a foreign key to the game id and to the mode id. If you want to make the result a bit more friendly then a simple query and form will do the job but it has to be structured with a middle table to make the links.
Related
Issue:
I am developing a simple issue tracking database and have hit a stumbling block that I’m not sure how to resolve. Have tried several approaches using queries, sql statement etc but still not working. I may have to rethink how I am doing this but hoping someone may be able to address the issue as it stands, though if a more elegant way of doing it happy to implement that.
Scenario:
A table called tblUsers has a field called Access that is a lookup to a table called tblCategory and allows for multiple values to be stored (one to many). In essence this is saying which category(s) of “issue” the user is allowed to
A simple msgbox test in code shows that this is correctly storing the values selected in the following format "1, 2, 3, 4"
In turn, each issue can only have a single category (one to one) which is stored in a field called Category in table tblGMPIssues and is also populated from a lookup to the tblCategory table.
So far so good ….
I then have a query called qryUserIssues that should show all issues from the table tblGMPIssues that are a) “Open” (status = 1) and that b) match any of the categories that the user is permitted to view.
I can get this to work with a single value i.e. as it stands query prompts for input and if you enter a single valid integer it returns expected results
But I can’t work out the syntax to get the criteria to accommodate multiple values. For example, in above scenario our user should be allowed to see 4 different category or calls “1, 2, 3, 4”
Tried using INNER joins, tried assigning to variables and using a LIKE criteria but can’t seem to get the syntax right.
If anyone could let me know if this can be done and if so how as it’s driving me nuts.
All help and suggestions gratefully received.
Updated relationship diagram --> 1
For precisely the reason that you've asked this question I would recommend never using the multi-select lookup option for columns in MS Access tables. Instead create an intersection table which tells you the combinations of values from the two main tables that are allowed. So instead of having the multi-select Access column in tblUsers, you should have a separate table called tblUserAccess with two columns (UserID and CategoryID). The two columns together will form a composite Primary Key for this table, and individually they will be Foreign Keys to tblUsers and tblCategory respectively. (You should do the same kind of thing with tblType - remove the Categories column and set up a separate table called tblTypeCategories).
Coming to your query, are you expecting this to show you all the relevant Issues for a particular user? At the moment, it is not doing this. The reason it is prompting you for input is because it doesn't understand ([tblUsers].[Access]) - tblUsers is not referenced in your query, and the query has no way of knowing which particular user you're interested in.
With your new table in place (and populated with the relevant data) you should add tblUserAccess to the query, joining tblGMPIssues.Category to tblUserAccess.CategoryID. Take the ([tblUsers].[Access]) condition off the Category column. Add the UserID column to the grid and set the criteria to [Input UserID]. Now when you run the query it will ask you for a user ID, and it should hopefully show you all the Issues that the given user can access.
Good luck!
First, I suggest you normalize your data a bit:
You have a number of tables that are reference data (e.g. tables tblStatus, tblSeverity, tblLocation). You have a s a primary key a (system generated) ID. That is wrong! The primary key of these should be their data, i.e. status, severity, location.
I can't see what the relationships are between the data. It should be one-to-many, mandatory (i.e. one Status can occur in many tblGMPIssues and a status is mandatory).
Your table tblType is unclear to me but it contains the categories. I am not familiar with the '-' before Categories followed by a Categories.Value but I assume an occurrence of tblType can contain exactly one Categories.Value. If not, then you must decompose this table.
If a User has access to a number of Categories, then there must be a many-to-many relationship betwen Users and Categories. From this relationship you do your select query, but I don't see this relationship.
Use following query to get any of the Category IDs 1, 2, 3 or 4
Select * from tblGMPIssues where tblGMPIssues.Category in (Select UserAccess from tblUserAccess)
I still have many problems with your relational design, or actually the lack of a proper relational design. As an example, below is a diagram from my Access 2007 showing a part of your database with a proper design. Access automatically shows that "one" and "many" symbols (which I don't see in your diagrams). I also show the relationship dialog with the proper fields checked. Note that none of the keys of any table, except tblIssue, has a system generated primary key. They are all plain text whch allows better understanding when inspecting the data and, as said, the database automaticlly updates child tables when the primary key value of a parent table changes.
Note table tblCategoryType: it implements a many-to-many relation between categories and types, meaning a category can be of zero or more types and a type can be in zero or more categories. In addition to "update cascades", this table has the "delete cascades" checkbox checked so if a category is deleted, all its relations with types are deleted (not the types).
I have 4 tables, "Player", "Crafting", "Battling", "Gathering".
I made a relationship rule for Crafting, Battling and Gathering to share information to the Player table.
The problem is that when I go to the player table it makes me choose which other table's information to display instead of showing all 3.
How can I make a relationship so that I can view all three other tables from the player table?
It's impossible and you don't need this. You already have all relationships you need. Just create a form based on Player table with 3 subforms and link them on form, no additional code required in simple case.
Also I would recommend do not use username as primary key, use Autonumber data type instead.
I had one single table that had lots of problems. I was saving data separated by commas in some fields, and afterwards I wasn't able to search them. Then, after search the web and find a lot of solutions, I decided to separate some tables.
That one table I had, became 5 tables.
First table is called agendamentos_diarios, this is the table that I'm gonna be storing the schedules.
Second Table is the table is called tecnicos, and I'm storing the technicians names. Two fields, id (primary key) and the name (varchar).
Third table is called agendamento_tecnico. This is the table (link) I'm goona store the id of the first and the second table. Thats because there are some schedules that are gonna be attended by one or more technicians.
Forth table is called veiculos (vehicles). The id and the name of the vehicle (two fields).
Fith table is the link between the first and the vehicles table. Same thing. I'm gonna store the schedule id and the vehicle id.
I had an image that can explain better than I'm trying to say.
Am I doing it correctly? Is there a better way of storing data to MySQL?
I agree with #Strawberry about the ids, but normally it is the Hibernate mapping type that do this. If you are not using Hibernate to design your tables you should take the ID out from agendamento_tecnico and agendamento_veiculos. That way you garantee the unicity. If you don't wanna do that create a unique key on the FK fields on thoose tables.
I notice that you separate the vehicles table from your technicians. On your model the same vehicle can be in two different schedules at the same time (which doesn't make sense). It will be better if the vehicle was linked on agendamento_tecnico table which will turn to be agendamento_tecnico_veiculo.
Looking to your table I note (i'm brazilian) that you have a column called "servico" which, means service. Your schedule table is designed to only one service. What about on the same schedule you have more than one service? To solve this you can create a table services and create a m-n relationship with schedule. It will be easier to create some reports and have the services well separated on your database.
There is also a nome_cliente field which means the client for that schedule. It would be better if you have a cliente (client) table and link the schedule with an FK.
As said before, there is no right answer. You have to think about your problem and on the possible growing of it. Model a database properly will avoid lot of headache later.
Better is subjective, there's no right answer.
My natural instinct would be to break that schedule table up even more.
Looks like data about the technician and the client is duplicated.
There again you might have made a decisions to de-normalise for perfectly valid reasons.
Doubt you'll find anyone on here who disagrees with you not having comma separated fields though.
Where you call a halt to the changes is dependant on your circumstances now. Comma separated fields caused you an issue, you got rid of them. So what bit of where you are is causing you an issue now?
looks ok, especially if a first try
one comment: I would name PK/FK (ids) the same in all tables and not using 'id' as name (additionaly we use '#' or '_' as end char of primary / foreighn keys: example technicos.technico_ and agendamento_tecnico has fields agend_tech_ and technico_. But this is not common sense. It makes queries a bit more coplex (because you must fully qualify the fields), but make the databse schema mor readable (you know in the moment wich PK belong to wich FK)
other comment: the two assotiative (i never wrote that word before!) tables, joining technos and agendamento_tecnico have an own ID field, but they do not need that, because the two (primary/unique) keys of the two tables they join, are unique them selfes, so you can use them as PK for this tables like:
CREATE TABLE agendamento_tecnico (
technico_ int not null,
agend_tech_ int not null,
primary key(technico_,agend_tech_)
)
I've seen various posts here about not using lookup within a table. If you don't, how do you enforce referential integrity between a field and the allowable values from a lookup table? I can't create a relationship between the table field and the field in the lookup table because I can't create a unique (no duplicates) index on the field - the particular value needs to appear multiple times across the records in the table. But if I use the field properties to set a lookup on it and specify the field from the lookup table that it must contain, then this ensures that data can't be entered into this field that isn't in the lookup table.
Or have I got completely the wrong end of the stick here?
I recommend that you always create forms for editing records. And in those forms you can create combo boxes that perform the lookups in the correct table and field. There are options there so that you can limit the data entry to only those values which are stored in the table. This option is called Limit To List (you'll see it in the combo properties).
Another important way to enforce that data exists in your lookup table is through your Relationships.
tblProducts
ProductID (primary key)
CategoryID (foreign key)
ProductDescription
tblCategories
CategoryID (primary key)
Category
In the relationships window you would define a relationship between the two tables above on the CategoryID field. You are accomplishing several things here. It's more efficient to store only the CategoryID in your Products Table since you will be storing less data. Also, this way if you change the name on the category all records will reflect that change immediately. Every place that you display a product with its category you will need to create a combo box so that you display the Category Description as opposed to displaying the CategoryID.
As a side note, I recommend that you rarely use the Value List option as the Row Source Type in a combo. Using the Table/Query option and then creating an appropriate lookup table is a much more robust and flexible design.
So imagine you have multiple tables in your database each with it's own structure and each with a PRIMARY KEY of it's own.
Now you want to have a Favorites table so that users can add items as favorites. Since there are multiple tables the first thing that comes in mind is to create one Favorites table per table:
Say you have a table called Posts with PRIMARY KEY (post_id) and you create a Post_Favorites with PRIMARY KEY (user_id, post_id)
This would probably be the simplest solution, but could it be possible to have one Favorites table joining across multiple tables?
I've though of the following as a possible solution:
Create a new table called Master with primary key (master_id). Add triggers on all tables in your database on insert, to generate a new master_id and write it along the row in your table. Also let's consider that we also write in the Master table, where the master_id has been used (on which table)
Now you can have one Favorites table with PRIMARY KEY (user_id, master_id)
You can select the Favorites table and join with each individual table on the master_id and get the the favorites per table. But would it be possible to get all the favorites with one query (maybe not a query, but a stored procedure?)
Do you think that this is a stupid approach? Since you will perform one query per table what are you gaining by having a single table?
What are your thoughts on the matter?
One way wold be to sub-type all possible tables to a generic super-type (Entity) and than link user preferences to that super-type. For example:
I think you're on the right track, but a table-based inheritance approach would be great here:
Create a table master_ids, with just one column: an int-identity primary key field called master_id.
On your other tables, (users as an example), change the user_id column from being an int-identity primary key to being just an int primary key. Next, make user_id a foreign key to master_ids.master_id.
This largely preserves data integrity. The only place you can trip up is if you have a master_id = 1, and with a user_id = 1 and a post_id = 1. For a given master_id, you should have only one entry across all tables. In this scenario you have no way of knowing whether master_id 1 refers to the user or to the post. A way to make sure this doesn't happen is to add a second column to the master_ids table, a type_id column. Type_id 1 can refer to users, type_id 2 can refer to posts, etc.. Then you are pretty much good.
Code "gymnastics" may be a bit necessary for inserts. If you're using a good ORM, it shouldn't be a problem. If not, stored procs for inserts are the way to go. But you're having your cake and eating it too.
I'm not sure I really understand the alternative you propose.
But in general, when given the choice of 1) "more tables" or 2) "a mega-table supported by a bunch of fancy code work" ..your interests are best served by more tables without the code gymnastics.
A Red Flag was "Add triggers on all tables in your database" each trigger fire is a performance hit of it's own.
The database designers have built in all kinds of technology to optimize tables/indexes, much of it behind the scenes without you knowing it. Just sit back and enjoy the ride.
Try these for inspiration Database Answers ..no affiliation to me.
An alternative to your approach might be to have the favorites table as user_id, object_id, object_type. When inserting in the favorites table just insert the type of the favorite. However i dont see a simple query being able to work with your approach or mine. One way to go about it might be to use UNION and get one combined resultset and then identify what type of record it is based on the type. Another thing you can do is, turn the UNION query into a MySQL VIEW and simply query that VIEW.
The benefit of using a single table for favorites is a simplicity, which some might consider as against the database normalization rules. But on the upside, you dont have to create so many favorites table and you can add anything to favorites easily by just coming up with a new object_type identifier.
It sounds like you have an is-a type relationship that needs to be modeled. All of the items that can be favourited are a type of "item". It sounds like you are on the right track, but I wouldn't use triggers. What could be the right answer if I have understood correctly, is to pull all the common fields into a single table called items (master is a poor name, master of what?), this should include all the common data that would be needed when you need a users favourite items, I'd expect this to include fields like item_id (primary key), item_type and human_readable_name and maybe some metadata about when the item was created, modified etc. Each of your specific item types would have its own table containing data specific to that item type with an item_id field that has a foreign key relationship to the item table. Then you'd wrap each item type in its own insertion, update and selection SPs (i.e. InsertItemCheese, UpdateItemMonkey, SelectItemCarKeys). The favourites table would then work as you describe, but you only need to select from the item table. If your app needs the specific data for each item type, it would have to be queried for each item (caching is your friend here).
If MySQL supports SPs with multiple result sets you could write one that outputs all the items as a result set, then a result set for each item type if you need all the specific item data in one go. For most cases I would not expect you to need all the data all the time.
Keep in mind that not EVERY use of a PK column needs a constraint. For example a logging table. Even though a logging table has a copy of the PK column from the table being logged, you can't build a constraint.
What would be the worst possible case. You insert a record for Oprah's TV show into the favorites table and then next year you delete the Oprah Show from the list of TV shows but don't delete that ID from the Favorites table? Will that break anything? Probably not. When you join favorites to TV shows that record will fall out of the result set.
There are a couple of ways to share values for PK's. Oracle has the advantage of sequences. If you don't have those you can add a "Step" to your Autonumber fields. There's always a risk though.
Say you think you'll never have more than 10 tables of "things which could be favored" Then start your PK's at 0 for the first table increment by 10, 1 for the second table increment by 10, 2 for the third... and so on. That will guarantee that all the values will be unique across those 10 tables. The risk is that a future requirement will add table 11. You can always 'pad' your guestimate