Detect time of last change on a Microsoft Access database table - ms-access

Does anyone know of a way to detect when the last time a Microsoft Access table has been changed (inserted into or updated)? We used OLEDB via ADO COM to communicate with an access database programmatically and were looking for a way of detecting changes to specific tables. We don't need to know what those changes are, just that changes were made.

The only way to detect if data in the table has changed is to perform a query against the table.
You must add a column of type DATETIME to the table e.g. named LastUpdatedDate that indicates the last updated date/time of each row. Make it NOT NULL so that you will have to write an updated DATETIME value to that column for each INSERT or UPDATE. Also, set the column to have a default of DATE() for the current date stamp or NOW() for the current date/time stamp. Then add a Validation Rule or CHECK constraint e.g. CHECK (LastUpdatedDate = NOW()) to ensure the column is actually updated on each UPDATE and INSERT.
Finally, run a MAX(LastUpdatedDate) query and you will get what you need.

There isn't a way without "manually" writing to a column each time you access the table.

As others have indicated there is no way to track changes without coding it yourself.
There's a simple example at
ACC2000: How to Create an Audit Trail of Record Changes in a Form
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q197592
Audit Trail - Log changes at the record level at:
http://allenbrowne.com/AppAudit.html
The article addresses edits, inserts, and deletes for a form and subform.
Modules: Maintain a history of changes
http://www.mvps.org/access/modules/mdl0021.htm
The History Table routine is designed to write history records that track the changes made to fields in one or more tables.

You will need to implement a timestamp column in your table, and update the value during your data changes.

Related

Updating one table in MS Access with data from another

In MS Access 2016 I have a table named Master that periodically needs to gets updated with ‘updated’ data from a table named NewData. Each table has the same fields, except Master has one additional field named OTHER_SOURCES (explained further down). They each have an indexed unique id field named EVENT_ID. I’ve built an update query where the tables are joined one-to-one on the EVENT_ID field. In this query I have the fields in Master getting updated to the new values from the same fields in NewData if the TIMESTAMP field value is different. If the TIMESTAMP values haven’t changed, then those records do not get updated. This part is pretty straightforward and works fine.
However, I have end users that may make occasional changes to the values in the SIZE field of Master that need to be preserved and not overwritten with updated values from NEW_DATA. When a user makes a change in SIZE field, he documents the change with information obtained from other sources, which is stored in the extra field I mentioned earlier: OTHER_SOURCES. Here’s what I need to do, and I just can’t figure it out. Whenever a user has made a change to the SIZE field for a record, I need the update query to not override that value in the SIZE field, but still update the values in all the other fields (again, assuming the TIMESTAMP values are different between the two tables). It seems I need to use an IIF statement, but I’m thinking it needs to be done in VBA where I’m a bit of a hack. See screenshots. I greatly appreciate any help you can offer.
enter image description here
enter image description here
You can still proceed with the update, but update it to the same value as its previous value:
SET SIZE= IIF(nz(OTHER_SOURCES,'')<>'', MASTER.Size, NEW_DATA.Size)
This assumes that anything present in the MASTER.OTHER_SOURCES column indicates that the user has changed MASTER.Size. Note that MASTER.Size will never be updated from NEW_DATA.Size until someone (end user) removes MASTER.OTHER_SOURCES.

How to create a Microsoft Access report with a date range

If this is not the forum to ask this question, please direct me to the correct one.
I am trying to learn Micosoft Access 2013 programming. I am trying to create a report on a form to display the table info based on a user defined range of the creation date. How would I go about doing this? Is the creation date stored automatically, available for retrieval?
No, Access does not automatically store the creation date of a record. However, you can accomplish that by adding a Date/Time field named [RecordCreated] (or whatever) to the table and setting its Default Value to Now(). That won't add a timestamp to existing records, but new records will automatically have their creation date (and time) recorded.

Timestamp is generated for next record, as opposed to current record

I have a slight issue with MS-Access, which is as follows.
I have a table with a Timestamp column (the format of the field is Date/Time, the default value is Now()). The issue is that whenever I create a new record, the timestamp is set for the next record I am going to create, as opposed to the record I am creating.
This means that I create record 50, and the Timestamp is set for record 51. If I come back a week later, and create record 51, the Timestamp for record 51 will be a week out, and the timestamp will be set for record 52, which I will be creating at some point in the future.
You can re-create the problem by firing up MS-Access, creating a new table with a couple of fields, one of which is Date/Time and setting the Default Value of this field to Now().
Is this by design, or am I doing something dumb? If it is by design, how can I implement the type of Timestamp that I want (one where the Date/Time is set as the record is created) in MS-Access? If I am doing something dumb, what exactly am I doing?
Edit: Below is a screenshot of a newly created Access table:
I add some text to record one, the Timestamp gets set for record two:
I allow some time to pass, put some data into record two, and the timestamp doesn't change, and now record three has a timestamp:
If I close and open the table, the Timestamp for the (New) record gets updated to whenever I opened the table:
I allow some time to pass, update the record and the Timestamp stays at the time I opened the table:
As is already revealed in the comments, this problem comes from editing in the table with Now() set as the Default for your TimeStamp field.
I suggest you create a form instead of editing in the table. If you want it to look similar just use a datasheet form. Then on the Form's BeforeUpdate event put code in like this:
Me!TimeStamp = Now()
As a side note, I wouldn't use TimeStamp as a field name. Some RDBMS such as SQL Server have a data type called TimeStamp. It's best to avoid using field names that are data types or reserved words. Moving an Access database to SQL Server is extremely common and you could have problems when you try to do it.
Instead, I would create two fields. One called DateTimeEntered and another called DateTimeModified. I consider these two fields to be necessary in pretty much every table I make. If you ever want to do any kind of synchronization of records you'll wish you had at least a DateTimeModified field.

MS Access trigger?

I have two tables named [Insert_Record] and [Delete_Record] in MS Access. Both tables have the same fields but one table has records whereas another table has no record.
Question: I want, whenever I delete any record from the table [Insert_Record] that entire record should automatically insert into another table, i.e: [Delete Record].
How can I accomplish this?
Access 2010 introduced event-driven Data Macros that are similar to triggers. The process described in the question can easily be done with an After Delete data macro on the [Insert_Record] table:
As I understand it, Access doesn't have triggers.
The best you can probably do is put this sort of logic into the forms that edit the table. In other words, handle the deleted event at the form level and put your insert logic there.
If you want triggers, you'll want to use a proper RDMS that supports them (MySQL, MS SQL, Oracle, many others).
EDIT: Another way to do this (which may or may not work for you) would be to add a boolean column 'IsDeleted'. That way, you can just logically delete a record instead of moving it to another table. The downside of this approach is the deleted records stay in the main table which could cause performance woes if there are lots of deletes.
Create an append query, to add records into the second table, that is executed in the On Delete Confirm event of the form you are using to delete the record from the first table.
I imagine this 'Delete' is button driven...
So program the button to first Insert the record into one table before deleting it.
Just add the VBA for the insert above the delete.
Another method which nullifies your need for another table entirely is just one column that is a boolean... Active Yes/No (Default to yes.)
If Active then it is not actually deleted when they hit delete, just set the flag to False then nothing is actually deleted, no SQL code is required and there is no risk, you can even have a column with the user who updated it print in another column
Me.Active = False
Me.UserName = 'CurrentUser Location here
Me.RecordSet.Requery
Then there is no risk of actually losing anything is there and you have a record of who flagged it last.
In the continuous form just add the Where flag Active = True then no false flags will show and it looks to the user base as if it was deleted.

what happens to a change-data-capture instance when the underlying table is altered?

If I enable change-data-capture for a table, and then somebody else adds a column to the table, will my capture be affected? Will I still get updates for the original columns? For the new column?
What if a column is deleted?
(This answer from my colleague Steve, but he doesn't have a SO account so I'll post it...)
If you ADD a column, the CDC does not change ... you continue to receive updates on the same column set as before.
If you DELETE a column, the CDC continues to capture changes, but the deleted column will always have the value NULL.
If you ALTER a column, the CDC continues to capture changes, but values in the altered column will have the new column type.
From MSDN's About Change Data Capture (SQL Server)
"Handling Changes to Source Tables
To accommodate column changes in the source tables that are being tracked is a difficult issue for downstream consumers. Although enabling change data capture on a source table does not prevent such DDL changes from occurring, change data capture helps to mitigate the effect on consumers by allowing the delivered result sets that are returned through the API to remain unchanged even as the column structure of the underlying source table changes. This fixed column structure is also reflected in the underlying change table that the defined query functions access.
To accommodate a fixed column structure change table, the capture process responsible for populating the change table will ignore any new columns that are not identified for capture when the source table was enabled for change data capture. If a tracked column is dropped, null values will be supplied for the column in the subsequent change entries. However, if an existing column undergoes a change in its data type, the change is propagated to the change table to ensure that the capture mechanism does not introduce data loss to tracked columns. The capture process also posts any detected changes to the column structure of tracked tables to the cdc.ddl_history table. Consumers wishing to be alerted of adjustments that might have to be made in downstream applications, use the stored procedure sys.sp_cdc_get_ddl_history.
Typically, the current capture instance will continue to retain its shape when DDL changes are applied to its associated source table. However, it is possible to create a second capture instance for the table that reflects the new column structure. This allows the capture process to make changes to the same source table into two distinct change tables having two different column structures. Thus, while one change table can continue to feed current operational programs, the second one can drive a development environment that is trying to incorporate the new column data. Allowing the capture mechanism to populate both change tables in tandem means that a transition from one to the other can be accomplished without loss of change data. This can happen any time the two change data capture timelines overlap. When the transition is effected, the obsolete capture instance can be removed.
Note Note
The maximum number of capture instances that can be concurrently associated with a single source table is two."