Using a calculated field at table level - ms-access

After Googling for a while I was wondering about the use of a calculated field at table level. I know its a big No,No but I wanted to use it as a method of preventing duplicates. For Example, I have a Payroll table and I wanted to concatenate the Employee ID field and the Work Day field. So during payroll entry some code can lookup that field to alert if the record exist.
Any advice is greatly appreciated.

Calculated fields cannot be indexed, so any lookup on a calculated field will probably result in a table scan. You'd probably be better off to create a unique index on the two columns to prevent duplicates.

As long as your data entry is through a properly managed form and not a form directly linked to the table you don't need the lookup to be on a single field, you can check for duplicates that match multiple criteria.
Simple example:
If Nz(DLookup("MyTableID","MyTableName","EmployeeID=" & Me.EmployeeID & " AND WorkDay=#" & Me.WorkDay & "#"),0)=0 Then
[Handle Add Record to Table]
Else
[Handle duplicate exists]
End If

Related

Access Query sort of Linked tables

I'm using Access 2007. I have two tables, first one has a PK (primary key), but the second has not.
When using a query linking the two tables on the PK, I need the rows have the same sort as it is in the second table (means as records has been entered), but this doesn't happen by default, I don't know why!
Tables are just a big bucket that holds data. There is no order to them unless you supply it. Therefore, in order for the items in your query/table to appear in the order that they were entered you will have to supply something that allows Access to apply this sorting for you.
You should add an AutoNumber Primary Key to the DataSub table. This will automatically increase every time that you add new data to this table, and so you can then use this in any queries to sort by.
Regards,

MS Access - Complete table with column value from other table

My MainTable contains tasks, one of the colums speciefies the TaskType as a string. The TaskType must be selected from the ValidTasks table, which contains different task types.
The ValidTasks table also contains a column called Priority which is an integer.
Now I want my MainTable to include the priority of the selected task. So that when I select as task from ValidTasks the corresponding Priority is added to another column in MainTable.
In the following step I will create a query showing the highest priority figure for each Person (also in the MainTable), so if it is easier to approach though a query then that would work for me too.
There are two ways you can go about this. The one I would go for unless there are overriding factors would be to use a SELECT query that links the two tables and has the fields I want as my "Main Table".
That is by far the best way. The alternative is to use the trigger of the user making a selection for a TaskType to look up and populate a field in your main table. I would not recommend that as it will come back to bite you as your database gets more complicated.
Also, I would not use a text field for TaskType. Your tables should have an AutoNumber as primary key and that is the field you should always use to link data from one table to another.

How to prevent Re-Import of Existing Records in an Access Saved Import from Excel?

I have a saved Excel Import in an Access Database that appends 'Payment data' each month to the 'Payments' table.
If someone were to run the import twice by mistake I noticed that Access simply appends the data twice to the table, thereby creating duplicate entries.
How can I prevent the Import from importing entries that already exist in the Table?
Fields in the Table include:
Invoice Number
Payment Date
Payment Amount
Customer ID
Customer Name
Payment Type
Thanks
Import the data to temporary table and then copy to main table only new data. Plus unique index, as in #cha answer. But just index is not good solution, it should prevent mistakes, good style - do not generate errors, including key violations
The best way to do this would be by implementing a unique index in your table. Only you know what makes the data unique, sometimes it is a unique transaction reference number, or a combination of columns.
The best candidate for the unique index applicable to your situation is [Invoice Number]. If you allow multiple payments for the same invoice (i.e. split invoice) you may need to use two columns for the index: [Invoice Number] + [Payment Date]. When you use two columns for the index make sure they are in the same unique index, not each in separate indices.

How to track changes to a boolean column in a MySQL database?

My application serves customers which are online stores. One of the tables in my DB is "Product" and it has a column "In_Stock". This is a boolean (bit(1)) column. My customers send data feeds of their product catalog and each customer has their own version of this table. I would like to track changes to this In Stock column, something to the effect of...
11/13/2016 true
12/26/2016 false
01/07/2017 true
Just so that when I do some auditing, I can see for a given time period what was the state of a given product.
How best can I do this?
It seems overkill to create a separate history table and have it updated by a trigger just for one boolean column. Would a history column suffice? I can save the data there in some kind of JSON string.
Sorry, any workable solution will require a second table.
One such solution is Version Normal Form (vnf) which is a special case of 2nf. Consider your table containing the boolean field (assuming it is properly normalized to at least 3nf). Now you want to track the changes made to the boolean field. One way is to turn the rows into versions by adding an EffectiveDate column then, instead of updating the row, write a new row with the current date in the date field (or updating if the boolean field is unchanged).
This allows the tracking of the field, there being a new version for every time the field is changed. But there are severe disadvantages, not least of which is the fact that a row is no longer an entity, but a version of an entity. This makes is impossible to use a foreign key to this table as those want to refer to an entity.
But look carefully at the design. Before the change, you had a good, normalized table with no tracking of changes. After adding the EffectiveDate column, there has been a subtle change. All the fields except the boolean field are, as before, dependent only on the PK. The boolean field is dependent not only on the PK but the new date field as well. It is no longer is 2nf.
Normalizing the table requires moving the boolean field and the date field to a new table:
create table NewTable(
EntityID int not null references OriginalTable( ID ),
EffDate date not null,
TrackedCol boolean,
constraint PK_NewTable primary key( EntityID, EffDate )
);
The first version is inserted when a new row is inserted into the original table. From then on, another version is added only when an update to the original table changes the value of the boolean field.
Here is a previous answer that includes the query to get the current and any past values of the versioned data. I've discussed this design many times here.
Also, there is a way to structure the design so the application code doesn't need to be changed. That is, the redesign will be completely transparent to existing code. The answer linked above contains another link to more documentation to show how that is done.
I would do trigger thing. But don't replicate whole column - take unique column id, log timestamp and boolean value.
Sometimes having good logs is priceless :)
I've written an audit trail module for this purpose, it basically duplicates the table, add some information to each row and keep the original data table untouched except for triggers.

MS Access autonumber problem

A client of mine accidentally deleted about 500 records from an access table that has a primary ID field which was created as "autonumber". By turning off the autonumber column (changing back to a integer), I was able to restore the missing 500 records from a backup, but now of course the autonumber cannot be turned back on...
What are some possible solutions? The ID field is used as a link to other tables, so I can't just renumber everything without also renumbering all of the tables that reference this number (a pain in the neck, but possible).
Is there any "trick" to turning autonumber back on, using the max(id) as the starting point if data already exists in the table?
Make newTable with ID field as AutoNumber (all fields must be same as in original table - except ID). Copy all data from originalTable to newTable:
INSERT INTO newTable SELECT * FROM originalTable
Once data is filled, delete originalTable and rename newTable to originalTable.
This way all "holes" in auto-numbering are preserved and newTable has Auto-Numbering turned on.
P.S. Always try to add foreign keys to your IDs. In that case, even if some data is deleted, you will at least have consistent state.
The ideal solution, although it's now too late, wouuld've been to restore the missing 500 records into a working table. Then do an Append query into the main table. This would've included the Autonumber field.
If I could add to the answers given.
A little known fact about Access autonumber fields is that the counter on them is reset when you compact and repair the database.
I am also pretty sure that if you do an insert it WILL use the numeric that is supplied rather than the next number in the autonumber counter as long as it is > (greater than) the internal counter kept by the auto-number field (does that make sense at all?)
In other words you CAN do something like this in an brand new access table where the counter should be set to 1...
INSERT INTO myTable (myAutoNumber,myOtherField) VALUES (10000,'other data')
The other solutions mentioned here are better because they would do a better job of guaranteering the result so I mention it almost for academic reasons.
Seth
Agree, but may want to add an ORDER BY to ensure that the AutoNumber is in the correct order. Otherwise your other tables will have the wrong ID association.
INSERT INTO newTable SELECT * FROM originalTable ORDER BY ID
You will also have to explicitly name the fields instead of using *
You make a new field and make it auto-number and then delete id field and rename new field to id