Value uniquess check across several fields of all records? - ms-access

I'm new to MS Access and hopefully my question is simple, but I haven't been able to find a clear answer through googling.
I have a simple database with a table it, and there is a subset of fields that must have unique contents. I understand how to set that up so that a specific field across all the records must be unique, but I need several fields across all records to have unique contents.
For example only one field, in one record, across fields 4 - 10, in all records, can have the number '1' in it. If '1' is in field 5 of record A, it cannot also be in field 8 of record F.
As an analogy, imagine we are building computers, each with 1 or 2 video cards. In the database some of the fields are storing the serial number of the video card installed in that slot. Obviously, serial numbers are unique, and the same card can't be installed in two slots, whether in the same computer, or in two different computers. I need the database to prevent the user from entering duplicate serial numbers. In the example image there are duplicates of the same serial number in different fields of different records. This should NOT be allowed. example
Is there a built-in way to implement this sort of user entry check? If not, how can I implement it?

You want a unique composite index. To make this
Go to design view on the table
Open the Indexes editor window
Go to a new line, enter the name of your new index, select the Field Name
In Index Properties pane change the Unique property to Yes
Go to a new line, do not enter an index name, select another Field Name
Done
Edit:
The real issue is that you need to normalize your data. Slot #1 and Slot #2 are not really columns. You need to set up your table like this
Not that I made all three columns a composite primary key AND I made the VideoCard column indexed to not allow duplicates
Then when you go to enter your bad data you get this message
and it's won't let you commit until you enter good data.
If you need to present your data pivoted like your original example then you can do this in a cross tab query
which will make results like this

Related

Convert Access table to SharePoint list with auto increment ID starting from the same number

I need to move a table from within an ms access database to a SharePoint list. The table I need to move has had old records removed that has ID's auto increment. I need the SharePoint list to start from the same auto increment number as in the table.
I have tried using the ms access export to SharePoint list functionality but when I re-import the table back into access as a linked table to a SharePoint list the ID has started back at 1 (not 81 like in the table I uploaded to SharePoint).
I need the table to upload to the SharePoint list with the auto increment ID starting at 81 as it is in the table initially.
I understand Albert's logic, but somewhat disagree. I worked with one client that had been using an original Auto-numbered field as the Customer's ID in their access database for years, so their work orders, invoices, etc..., all have the Customer's ID there. If you use the newly-created autonumber field, then all customer id's would change to new numbers. Worse yet, if you use a 2nd, non-autonumber field as Albert recommends, then anytime you add a new customer, you would need to use a sql statement (or query) to determine the last used number from this 2nd field and increment it 1 so that it is unique. Kind of a pain.
So, the workaround is still a pain, but for a solution that does what you actually asked, you can do this. Create a new list in SharePoint with an auto-numbered field. link that list in the access database. then, look at the highest ID number (eg highest customer id) from the table with your original data... because you need to create that many rows in the SharePoint list. You can either create code to loop through creating x number of records, or if you're not comfortable with that, create an excel sheet with that many rows. then, import that excel file into the linked table. next, create a delete query which deletes all records in the linked table that doesn't have the matching ID (eg customer ID) in your access table. this leaves you with a linked list with only the IDs you are using, and it's still auto-numbering so new records are automatically assigned new numbers.
Like I said, it's a bit of a work-around. But this actually does what you are asking for, instead of being forced into a different solution.
If the column in question is a autonumber column, then during a upload or migration then those autonumbers can change. Since such numbers have NO meaning, then this should not matter. If you have several related tables then you MUST ensure that your relations are setup correctly before you move the data to sharepoint (because SharePooint will re-number these values, then the child tables and FK keys ALSO will be correctly updated). However, if you don't set the relationships, then you WILL break the related data since SharePoint does and can and will re-number the PK's used.
You are limited to ONLY using autonumber PK's if you wish to keep related tables intact. You cannot control this re-numbering, but as noted the number ONE rule in databases is that such numbers do NOT matter anyway.
If you MUST and WANT to stop the re-numbering of that column, then change the data type to a long number, and NOT autonumber type. And then of course simply add another autonumber column. So to STOP or PREVENT the numbers being changed, you have to convert the column from being autonumber to a standard long number column. (edit: you ALSO thus have to ensure that the column is NOT marked as PK).
Keep in mind that any other table as part of the related data will ALSO see those standard long number columns re-numbered and changed if that column is part of a defined relationships to some PK. So Access during a up-size WILL re-number the PK (autonumber) and will ALSO automatic for you re-number the FK columns used in child tables. If you as noted do NOT want such re-numbering to occur, then the PK and FK columns can NOT be part of a defined relationship.
So dropping the autonumber column is the only way to prevent such re-numbering. Since autonumbers don't have any real meaning, then if they are changed during a up-load, then this should not matter.

what is the best practice - a new column or a new table?

I have a users table, that contains many attributes like email, username, password, phone, etc.
I would like to save a new type of data (integer), let's call it "superpower", but only very few users will have it. the users table contains 10K+ records, while fewer than 10 users will have a superpower (for all others it will be null).
So my question is which of the following options is more correct and better in terms of performance:
add another column in the users table called "superpower", which will be null for almost all users
have a new table calles users_superpower, which will at most contains 10 records and will map users to superpowers.
some things i have thought about:
a. the first option seems wasteful of space, but it really just an ingeger...
b. the second option will require a left join every time i query the users...
c. will the answer change if "superpower" data was 5 columns, for example?
note: i'm using hibenate and mysql, if it changes the answer
This might be a matter of opinion. My viewpoint on this follows:
If superpower is an attribute of users and you are not in the habit of adding attributes, then you should add it as a column. 10,000*4 additional bytes is not very much overhead.
If superpower is just one attribute and you might add others, then I would suggest using JSON or another EAV table to store the value.
If superpower is really a new type of user with other attributes and dates and so on, then create another table. In this table, the primary key can be the user_id, making the joins between the tables even more efficient.
I would go with just adding a new boolean field in your user entity which keeps track of whether or not that user has superpowers.
Appreciate that adding a new table and linking it requires the creation of a foreign key in your current users table, and this key will be another column taking up space. So it doesn't really get around avoiding storage. If you just want a really small column to store whether a user has superpowers, you can use a boolean variable, which would map to a MySQL BIT(1) column. Because this is a fixed width column, NULL values would still take up a single bit of space, but this not a big storage concern most likely as compared to the rest of your table.

MS Access 2013 query query criteria can't assess if value A is contained in value B string

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).

Data type to store non-numeric registration number in a table

I'm very new to databases and creating a table to store details of some students.
Their student registration numbers are like this : 12/AS/CI/99
So, what's the best data type to store this value in the table ?
The first thing to understand is that 12/AS/CI/99 is not a datum (even though the user perceives it as one RegistrationNo), therefore it should not be placed in a single column.
First Normal Form requires data to be Atomic.
Determine what each of those four items are, and implement four columns. Probably RegistrationYear, HomeState, Fish, BirthYear.
That will allow full capability (look-ups, searches, aggregation, etc) on each of the component columns.
Yes, that means the Key will be four columns. Compound Keys are normal in relational databases.
Yes, that means you will have to concatenate the four columns with "/" in-between, wherever you display it to the user, as a single field (note the distinction between column and field) labelled RegistrationNo. That too, is normal.
If you do not do that, if you store it as a alpha-numeric column, you won't have a database, or any of the facilities people expect from databases. Eg. if you search for students who have AS in their RegistrationNo, the query will tablescan (Peanut's advice is incorrect), whereas if the components were separated columns, it will be blindingly fast, because the Key (in any number of component columns) is indexed. The student Key should be indexed in whatever table it occurs in.
Use CHAR(length) if the length of your ID is known (and fix).

MySQL - Insert Row Without Disrupting AUTO_INCREMENT

Quick question:
I have a sports league database with a list of games (let's say 40 or so). Each game is auto-assigned an ID number as the primary key when importing the entire schedule from a spreadsheet. The games are then displayed on the web page in descending order thanks to this invisible (to the user) primary key. Here's an example: League Schedule
Works great. The only problem is that sometimes the games are rescheduled and moved to a later date or a new game is added and has to be inserted into an already existing schedule. To this point, I've had to manually edit each affected row's ID (using PhpMyAdmin) to account for the changes and this can be quite tedious and time consuming.
What I'd really like to do is set the table to readjust primary key values on the fly. Meaning, if I inserted a brand new game into the fifth row of the table, all games thereafter would automatically be readjusted (ID 5 would become 6, ID 6 would become 7, and so on).
Is there a way to set-up the table to do this, or a particular SQL command I can use to accomplish it just the same? Apologies if this has already been asked many times in different ways. Any and all feedback is appreciated.
You should not use your PRIMARY KEY for that. Add a special column like sort with a regular INDEX, not UNIQUE. It does not have to be INT either, you can use real numbers. This way you will always be able to insert new row between any two rows of your schedule.
No, auto-increment is required to be unique, but it is not required to be in any particular order or even contiguous. The fact that auto-increment is monotonically increasing is only by coincidence of its implementation. Don't rely on the values being in chronological order.
Trying to adjust the values is not only manual and awkward, but it risks race conditions, or else would require locking a lot of rows. What if you insert a row with id 5, but your table has 1 billion rows greater than id 5?
There's also a risk of renumbering primary key columns, because any user who got an email telling them that they need to go to game 42 may end up going to the wrong game.
If you have need to view the rows in a particular order (e.g. chronological), then use a DATE column for that, not an auto-increment column.