Audit table design suggestions - ms-access

Is it the correct approach? Any suggestions to make it better?
Below is screenshot of employee table and its shadow table where the tl_name and dept fields may change and currently using shadow table to track all changes.
Records are inserted/updated in Main table and it gets copied to shadow table with help of data macro.
all the records in the shadow table have to be approved/rejected by superuser
Main table will have updated alignment and shadow table will have entire history of changes for any employee.
When a record is added/updated in Main table via userform, a copy of record will be created in shadow table which has to be approved by admin.
When a record is added/updated in Main table via userform, is_active field will be set as false and once it is approved by admin this will be updated to true.

As I understand your requirements:
Changed/inserted data should be immediately visible to everyone, with a visible flag for un-approved data.
This is reasonable, if you work under the assumption that the majority of changes are correct and will be approved (hopefully true ;) ).
I think you are missing:
If a change is rejected, the data in Main table should be automatically reverted to the most recent approved state.
Otherwise the Main table stays in a (sort of) undefined state forever, with is_active = False and (apparently) wrong data.
This can be done with your audit table design. Find the latest approved entry for this emp PK, and use its data.
But if the number of columns that are audited may change in the future, you might consider an approach with two tables, as in this project: https://autoaudit.codeplex.com/documentation
AuditHeader Table
This table is inserted with one row everytime one record is inserted,
updated or deleted in a table that has been setup to use the AutoAudit
system.
AuditDetail Table
This table is related to AuditHeader and is inserted with one row for
each column that is changed during an insert or update operation and
for each column during a delete operation.
If you save old + new values with every change, you can revert to "old" state just from the current Audit entry.
And a structure change of Main table (or if you decide that e.g. users can edit emp_name too) doesn't need a structure change of the Audit table, because every audited column in Main is mapped to a row in AuditDetails instead of a column.
Edit: Additional advantage:
In your sample data you have marked the changed values in red. Obviously an Access table doesn't work like that. If you want to keep this information ("which column(s) exactly was edited?"), you would need an additional column in the Audit table.
This would be covered by AuditDetail, since it contains each change with old + new value.

Related

Multiple table update design in Access

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.

Database design: Managing old and new data in database table

I have a table Student with field as followed,
Student table (one record per student)
student_id
Name
Parent_Name
Address_line1, Address_line2, Addess_line
Photo_path
Signature_file_path
Preferred_examcity_choice1,Preferred_examcity_choice1, Preferred_examcity_choice3
Gender
Nationality
.
.
.
I am inserting into this table on Registration form completion through the web interface.
Now there is one more module in a web interface for updating the student data, on every update request I am updating the student table records and inserting the new entry in student_data_change_request. student can change records any number of times.
student_data_change_request
request_id(auto_incr PK)
old_name
new_name
old_photo_path
new_photo_path
old_signature_file_path
new_signature_file_path
Now coming to problem, earlier students were allowed to change very few fields, now client want to allow the candidate to update more number of fields(around 20 fields) and adding old and new columns for the corresponding column isn't elegant and preferred(I guess), I will end up creating 40 columns to keep track of 20 columns. So how should I redesign my table? suggestions are welcomed.
One approach is to have a shadow table named (table)_xx that has the same columns, the time, date, update/insert/delete flag, user or whatever and no referential integrity. Set a trigger to update that table from the source whenever anything happens.
If you've got genuine business requirements that need history then do those properly but this pattern is great as a general audit, debugging and forensic tool.
It's also really easy to automate/script as you just generate it from the DB metadata.
Usually historical table looks like:
request_id
column_name
old_value
new_value
dt
request_id and column_name are primary key. When you update student table you insert new entry in student_data_change_request for each updating column.
Edited:
Another way:
request_id
value_type
name
photo_path
signature_file_path
...
and insert first entry with old values and second entry with new values. Colum value_type is mark old or new.
I would rather have just one table, with an additional column for effective date. Then a view that picks up just the most recent row for each student_id becomes your first "table". If for some reason you must show "current" and "most recently changed" values side-by-side, that is another view.
As usual, it all depends on how you intend to use the data.
My strong preference in these cases is the solution #mathguy suggests - embedding the concept of time in the main table design. This allows you to ask the question "what was this student's address on 1 Jan?", or "who had signature x on 12 Feb?".
If you have to report or execute business logic that reflects the status at any point in time, this design works really well. For instance, if you have to report on how many students lived in a particular address for a given term, you want to know when the records were valid.
But not all applications care about "time" - sometimes, you just want to have an audit table, so you can trace what happened over time in case of anomalies.
In that case, #loztinspace's solution is useful - but in my experience, this rapidly escalates into more work, because those who want to inspect the audit records can or should not get access to a SQL prompt on your production environment.

restoring data in a specific table

One of our tables has been maligned
/*edit as per commented request
On doing an update to a specific column I accidentally neglected to specify for which row I wish to make this change and set the offending value for every row in the table.
*/end edit
but we have a very recent backup, however not so recent that other tables won't lose data if we do a total database restore.
I'm wondering what the procedure is (assuming there is one) of copying the contents of a given table from one database to another.
The largest problem is that I can't just drop the offending table and replace it as it has rows that are indexed by id into other tables. This won't be a problem if we just take the values from the identical rows in the back-up and bring them over (since the row ids wouldn't change).
It's unclear what exactly has gone wrong with your data. But I'm thinking maybe just a column or two has got messed up. As you said, you just want to copy over the data from the old table, based on the id column.
Assuming you've imported the backup database as "olddb" and the current one is named "newdb":
UPDATE newdb.yourtable newtable, olddb.yourtable oldtable
SET newtable.somecolumn = oldtable.somecolumn
WHERE newtable.id = oldtable.id
Use mysqldatadump for that particular table, and then feed that into the other database.
You can edit the dump file prior to redaing it in to the target table.
See: https://dba.stackexchange.com/questions/9306/how-do-you-mysqldump-specific-tables

Generic trigger on update / delete to backup current row

My situation is this:
I have a table, call it x.
Every time a row is updated or deleted, a copy of the old row should be inserted into x_history.
Additionally x_history will have its' own auto-incrementing id column, call that histid.
It is very important to have its' own id column as this will give us the flexibility to build version restore functionality.
I have 100+ tables to apply this to so I'm looking for a generic trigger that can be used for any table to backup one row into a history table. Only the 2 table names should vary from trigger to trigger. Specifying all column names is really not what I'm looking for.
I need to do this in MySQL but have added MSSQL too - I know both so can convert between one and the other easy enough.
Usually, Triggers are not the optimal solution for such purposes.
If possible, you might want to consider changing your database design.
Normally, a better way to handle such things are keeping the hole history in the source table, And have a status column that tells you for each row if it's deleted, updated, or current.
I have little to no experience with MySql, but I have been working with Sql server for the past 7 or 8 years, so what I'm about to say is true for sql server, but may be different for MySql.
If you choose to go with the triggers approach, keep in mind that after update triggers will execute even if the update does not change the row data (e.g update tableName set col1 = 1 where idCol = 4, the update trigger will be executed even if the col1 value before the update was 1, so no data was changed.)
For SqlServer, you might want to consider a common history table, that has only 6 columns:
1. Identity column
2. Table name column
3. Row Id column (original id from the original table)
4. Row Status column (e.g updated, deleted)
5. Action date (the date the row was copied to the history table)
6. Row content column (this should be an XML datatype (not sure if MySql has such dataType))
and then all you have to do is to use "SELECT * FROM deleted/inserted FOR XML AUTO" to create the content for the 6th. column.

sync records of two tables in the same database in MYSQL

I have two tables with some same fields like:
Table A: fname, lname, address, age, email, mobile, website, blog
Table B: fname, lname, address, age, email
Both these tables are used by different modules on my website. I want to sync the first five fields of both tables in such a way that whenever a new row is added or an existing row is modified in Table A, the Table B is updated automatically and vice versa.
For Example.
A user created a new record in Table A. Now the Table B should also be updated with this new information. and vice versa if a user creates a new record in Table B, the Table A should also be updated with this new information.
A user modified a record in Table A. Now the Table B should also be updated with this modified information. and vice versa if a user modifies a new record in Table B, the Table A should also be updated with this modified information.
How can I achieve this. I thought of using triggers but would it not create an inifinite loop resulting is server error!
Is any field among those 5 guaranteed to be unique? You could add a conditional to the trigger to check to see if that field exists before inserting the record in the table.
You might want to rethink the design also. Storing duplicate records in 2 places seems a little scaring. You're going to have to have triggers for updates, inserts, and deletes.
If u just need to update one table in case the other table gets updated, Instead of creating a table (as a part of some other table), create a View which is also like a table but virtual (not real).
but since u've asked for both sides update.
What I believe is that you should go back little back of this problem....and tell us why u need to update both the tables according to the other table,,,
Because you are just keeping duplicate data at two places that is of no need.
So, try to think whether it can be done without creating two tables, or something like create one table and one view for partial columns requirement.
It is not an answer to your problem, but I am trying to solve your problem in an optimized way which is good for everyone's health....
Hope you understood what i tried to tell. :)