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?
Related
I see others have asked about this error, but being such a novice, I'm still not able to figure out why it's happening in this project. Hoping someone can take a look and tell me what I'm doing wrong...
In 'formEmployeeFile', the data in combobox 'cboPosition' cannot be modified. I receive the error, "Control cannot be edited; it's bound to AutoNumber field 'PositionCID'."
Upon opening the employee file in formEmployeeFile, the combobox 'cboPosition' should display the 'PositionName' assigned to that employee. The drop-down list should contain all of the possible positions, which are contained in 'tablePositionCatalog'. I've just barely figured out a way to do both, but I'm still stuck with the error I described above.
This project is far from finished, and this is literally my first attempt at a database, so please forgive its rough shape! Oh, and though it may look real, the data (e.g. employee names, phone numbers) currently inside this file is fake.
Employee Database
With current structure of complex RecordSource, cboPosition should just be a textbox bound to PositionName field. This textbox properties should be Locked Yes and TabStop No to prevent editing.
This is peril of having exact same field name in multiple tables. Your queries carry PositionCID autonumber field forward and that is field you try to bind to and edit. Instead you need PositionCID foreign key field from tableEmployeePositions. Have to modify queries.
If tableEmployees and tableEmployeePositions have a 1-to-1 relationship, should just be 1 table. A 1-to-1 relationship is an exception to 1 form for 1 table editing but this relationship is rarely needed. You could just simplify and combine the tables - unless you need to track history of employee positions. In which case you could not include tableEmployeePositions in form RecordSource since there could be multiple records for each employee and this would be a many-to-many relationship.
I have learned more, and was compelled to find the solutions, mind changed.
PS dear experts, your help is appreciated in the time-saving nature of having forums and discussion in the first place, and also is mined for usefulness, not street cred. get helping or get off. The time I wasted reading posts where the answer was "I don't understand what you are trying to do..." and then questioning the OP with animus or incredulity, or suggesting some unrelated answer further confusing issues, is seemingly the problem with the world these days, if you want to help, help
Original Post:
Ok so as per the comments, thanks to ANYONE who volunteers any help with this problem.
I have a table and relationship design problem.
I have a table with a pk auto and I want to have a related table with a related column incrementally numbered that updates every time new data is entered in the form that is bound to it. It needs to update the related rows in the autonumbered table's key.
---the answer was to join the table on the autonumbered field.
The autonumber of the first table (main recordsource) is just an ID. I think I need two Primary Keys as I need to update the related record with that number in the entry form and move to NextRec but update the pk in the main table and move to NewRec , how do I join (see jpg image)?
I want enter results and update that existing record but update the adjoining pk so that a new record is created in the main table.
Tourney
more in depth:
From yours
My desired form
note that the calculation table feeds the upcoming games table, where a query shows the players recent results. I would like to split the upcoming results to show the players' recent game history, the second tab I would like to enter either one result or many results at a time. I hope I am clearer. You can see why I have had a challenge. See my form though. The recordsource is the upcominggames table and the data entry form is for input (ENTER GAME DATA)
-----the answer to this was an update query (a separate form) and then requery the statistics form to show the new matchups that were entered.
As from the comments, this is what I'm thinking of when I read your description:
Since the UpcomingGames will be entered first and exactly one GameResult can be entered per UpcomingGame, this will be a 1:1 relationship. As the name Upcoming says: The Upcoming data has to be entered before the Result can make sense. Unless an UpcomingGame can be cancelled, there will indeed be a Result for the Game, so there is no need to separate the information into 2 tables. I'd say, a user interface could look like this:
As you can see, the T_NUM column is an autovalue. Before entering any data, I initialized that column using a query like this (and deleted that record afterwards):
INSERT INTO Games ( T_NUM )
VALUES (1004);
This way, the numbering started with number 1005.
You won't be able to to avoid gaps in the numbering, as long as the users can remove existing records or cancel the insertion of a new record. If you want at least to avoid the latter, you will need some VBA code in the form.
I have a question on databases and how information is displayed in regards to Primary and Foreign keys.
For example, there are three tables; Employees, Employee_tickets and Employee_comments.
Each employeecan have multiple tickets and also multiple comments. A foreign key is placed in the Employee tickets and Employee Comments table. My application is built in vb.net with Visual Studio and it is a desktop application. How can I query say.. Employee Name ('Jon Doe') and display all of his tickets in a grid as well as all of the comments people have made on him over time? I have created a View on the sql database which returns all of the information I require but for each ticket listed under ('Jon Doe') the View displays and Employee Name for every single ticket. Is there a way to display the employee name only once and then every ticket listed under that particular individual without displaying the Employee Name again or do I have to make Separate windows to segregate all of this?
This seems like a really dumb question and I cannot for the life of me figure out how to correctly display what is required in this situation.
Here is an example of what I am trying to explain:
So for troy there is one employee name entered in the Employee Names table, There is one CWB ticket entered in the CWB table but there are TWO PQ Cards entered in the PQR Ticket table. How Can I Display only one row for Troy and one Row for his CWB because there are only one of each entered in the tables then the two rows for the PQR Cards under his name?
I have created a view which gathers this information all into the one single view itself then bound the datagridview's to this View.
Your problem has nothing to do with databases. Rather, the issue is that you have an entity (the employee) that has two separate collections associated with it (tickets and comments) and you want to show the contents of both collections.
Doing this in a datagrid is difficult because in its simplest incarnation it's intended to show one collection of like items.
I can think of a number of possibilities:
In your code, convert each collection to a single string value and display that single string value on the row with the employee's name. This conversion could be to comma-separate a stringified version of each item in the collection (as suggested by BS123 in the comments) or could simply be a summary (eg "5 Tickets").
Put the basic employee information in one data grid and then have two additional data grids below it, one bound to the Tickets collection and one to the Comments collection.
Embed data grids directly in the main data grid, one in the Tickets column and one in the Comments column, and bind each one to the appropriate collection in the employee.
Your database structure is correct so don't change that, you simply need to solve the issue of presentation.
What you're missing here is a controller between your view and your model. Your view is presenting exactly what it was given to present - it's up to you to format it.
There are several possible solutions to this, and the correct one partially depends on needs and infrastructure.
If you infrastructure is solid and your needs are near real time, consider dropping separately querying to fill your second and third tables based on what is picked in the first. This will increase the load on the database, but your data will almost always be correct, and the data will come from the database the way you want to see it.
If the database-centered solution is not good for you, LINQ provides some good ways to filter your data into typed collections that would present exactly what you want the user to see.
To get the users:
Dim users = From l In data.lines
Group By FirstName = l.firstName, LastName = l.lastName
Into Tickets = Group, Count()
You can then present this object to your grid. While dynamic typing works here, I think it would be easier to manage view interactions with defined classes. I'll leave that part up to you. Do some searching on LINQ to fill in the rest of the blanks. It's pretty neat stuff.
I hope someone can help me with this:
I have a simple query combining a list of names and basic details with another table containing more specific information. Some names will necessarily appear more than once and arbitrary distinctions like "John Smith 1" and "John Smith 2" are not an option, so I have been using an autonumber to keep the records distinct.
The problem is that my query is creating two records for each name that appears more than once. For example, there are two clients named 'Sophoan', each with a different id number, and the query has picked up each one twice resulting in four records (in total there are 122 records when there should only be 102). 'Unique values' is set to 'yes'.
I've researched as much as I can and am completely stuck. I've tried to tinker with sql but it always comes back with errors, I presume because there are too many fields in the query.
What am I missing? Or is a query the wrong approach and I need to find another way to combine my tables?
Project in detail: I'm building a database for a charity which has two main activities: social work and training. The database is to record their client information and the results of their interactions with clients (issues they asked for help with, results of training workshops etc.). Some clients will cross over between activities which the organisation wants to track, hence all registered clients go into one list and individual tables spin of that to collect data for each specific activity the client takes part in. This query is supposed to be my solution for combining these tables for data entry by the user.
At present I have the following tables:
AllList (master list of client names and basic contact info; 'Social Work Register' and 'Participant Register' join to this table by
'Name')
Social Work Register (list of social work clients with full details
of each case)
Social Work Follow-up Table (used when staff call social work clients
to see how their issue is progressing; the register has too many
columns to hold this as well; joined to Register by 'Client Name')
Participants Register (list of clients for training and details of
which workshops they were attended and why they were absent if they
missed a session)
Individual workshop tables x14 (each workshop includes a test and
these tables records the clients answers and their score for each
individual test; there will be more than 20 of these when the
database is finished; all joined to the 'Participants Register' by
'Participant Name')
Queries:
Participant Overview Query (links the attendance data from the 'Register' with the grading data from each Workshop to present a read-only
overview; this one seems to work perfectly)
Social Work Query (non-functional; intended to link the 'Client
Register' to the 'AllList' for data entry so that when a new client
is registered it creates a new record in both tables, with the
records matched together)
Participant Query (not yet attempted; as above, intended to link the
'Participant Register' to the 'AllList' for data entry)
BUT I realised that queries can't be used for data entry, so this approach seems to be a dead end. I have had some success with using subforms for data entry but I'm not sure if it's the best way.
So, what I'm basically hoping to achieve is a way to input the same data to two tables simultaneously (for new records) and have the resulting records matched together (for new entries to existing records). But it needs to be possible for the same name to appear more than once as a unique record (e.g. three individuals named John Smith).
[N.B. There are more tables that store secondary information but aren't relevant to the issue as they are not and will not be linked to any other tables.]
I realised that queries can't be used for data entry
Actually, non-complex queries are usually editable as long as the table whose data you want to edit remains 'at the core' of the query. Access applies a number of factors to determine if a query is editable or not.
Most of the time, it's fairly easy to figure out why a query has become non-editable.
Ask yourself the question: if I edit that data, how will Access ensure that exactly that data will be updated, without ambiguity?
If your tables have defined primary keys and these are part of your query, and if there are no grouping, calculated fields (fields that use some function to change or test the value of that field), or complex joins, then the query should remain editable.
You can read more about that here:
How to troubleshoot errors that may occur when you update data in Access queries and in Access forms
Dealing with Non-Updateable Microsoft Access Queries and the Use of Temporary Tables.
So, what I'm basically hoping to achieve is a way to input the same data to two tables simultaneously (for new records) and have the resulting records matched together (for new entries to existing records). But it needs to be possible for the same name to appear more than once as a unique record (e.g. three individuals named John Smith).
This remark actually proves that you have design issues in your database.
A basic tenet of Database Design is to remove redundancy as much as possible. One of the reasons is actually to avoid having to update the same data in multiple places.
Another remark: you are using the Client's name as a Natural Key. Frankly, it is not a very good idea. Generally, you want to make sure that what constitutes a Primary key for a table is reliably unique over time.
Using people's names is generally the wrong choice because:
people change name, for instance in many cultures, women change their family name after they get married.
There could also have been a typo when entering the name and now it can be hard to correct it if that data is used as a Foreign Key all in different tables.
as your database grows, you are likely to end up with some people having the same name, creating conflicts, or forcing the user to make changes to that name so it doesn't create a duplicate.
The best way to enforce uniqueness of records in a table is to use the default AutoNumber ID field proposed by Access when you create a new table. This is called a Surrogate key.
It's not mean to be edited, changed or even displayed to the user. It's sole purpose is to allow the primary key of a table to be unique and non-changing over time, so it can reliably be used as a way to reference a record from one table to another (if a table needs to refer to a particular record, it will contain a field that will hold that ID. That field is called a Foreign Key).
The names you have for your tables are not precise enough: think of each table as an Entity holding related data.
The fact that you have a table called AllList means that its purpose isn't that well-thought of; it sounds like a catch-all rather than a carefully crafted entity.
Instead, if this is your list of clients, then simply call it Client. Each record of that table holds the information for a single client (whether to use plural or singular is up to you, just stick to your choice though, being consistent is hugely important).
Instead of using the client's name as a key, create an ID field, an Autonumber, and set it as Primary Key.
Let's also rename the "Social Work Register", which holds the Client's cases, simply as ClientCase. That relationship seems clear from your description of the table but it's not clear in the table name itself (by the way, I know Access allows spaces in table and field names, but it's a really bad idea to use them if you care at least a little bit about the future of your work).
In that, create a ClientID Number field (a Foreign Key) that will hold the related Client's ID in the ClientCase table.
You don't talk about the relationship between a Client and its Cases. This is another area where you must be clear: how many cases can a single Client have?
At most 1 Case ? (0 or 1 Case)
exactly 1 Case?
at least one Case? (1 or more Cases)
any number of Cases? (0 or more Cases)
Knowing this is important for selecting the right type of JOIN in your queries. It's a crucial part of the design assumptions when building your database.
For instance, in the most general case, assuming that a Client can have 0 or more cases, you could have a report that displays the Client's Name and the number of cases related to them like this:
SELECT Client.Name,
Count(ClientCase.ID) AS CountOfCases
FROM Client
LEFT JOIN ClientCase
ON Client.ID = ClienCase.ClientID
GROUP BY Client.Name
You've described your basic design a bit more, but that's not enough. Show us the actual table structures and the SQL of the queries you tried. From the description you give, it's hard to really understand the actual details of the design and to tell you why it fails and how to make it work.
I've been using Access to create simple databases for a while with great success, but have run into a problem I can't find an answer to.
We ship individualized serialized units to various end-users, and occasionally to resellers that stock them for end-users. I must keep track of which serial numbers end up with each end-users.
The first database I created to handle this recorded company information in one table using their account number as primary key, order information in a second table using the order number as the primary key and linked via the company name, and unit information in a third table with the serial number as the primary key and linked via the order number.
This worked very well until I had to account for these stock orders with a reseller. As it was structured, every unit was linked to one company via the sales order. The issue is that I may ship 20 units on one order to Company A, who then sells 5 to Company B and 3 to Company C.
I realized I needed to link the company name directly to the units, not the orders and have fixed that.
My issue now is simplicity in entering information in the form. My previous database involved the employee in our shipping department merely entering the sales order, selecting the customer name from a drop down menu, then scanning the serial numbers in a subform. This was to ensure simplicity and try to eliminate human error. He had only three things to input, and most of the input was done by scanning barcodes.
As it is currently structured now, the employees out in shipping would have to populate the company name for every record in the subform with the serial number and that complicates things in a way that is unacceptable. At the point of shipping, the company name will always be the same for every unit in the subform.
So.
How would I go about creating a form where the company name is entered once in the form, and automatically populates itself for every record in the subform? The caveat here is that I must also be able to go back occasionally and change the company name of individual units in an order without necessarily affecting the rest of the order. I suppose it starts out as a one-to-many relationship that then must be able to change.
I hope that makes sense.
I have looked for answers using various approaches with auto-fill and relationships and not preserving data integrity, but I feel the answer is just beyond my reach.
The only solution I can think of is to create another field in the unit table for the end-user, and perhaps write a formula that sets this default value as the company name from the order that shipped it. This seems unnecessarily complicated and redundant, there has to be a better way.