Is there a single word that means "upsert or delete"? - relational-database

I've written a function that upserts a row in to my database and deletes it if it's blank. I'm struggling to name it. If it only upserted, I'd just call it that. And if it only deleted, I'd just call it that. Like how "upsert" combines "update" and "insert", is there a word that includes "delete" in that grouping?

Related

Referencing Just Added Record When Using Call to VBA in AfterInsert DataMaco

Access 2016, table with a AfterInsert datamacro.
In a comment to a previous question that I can no longer find, Albert D. Kallal (user:10527) noted that if one uses the Set LocalVar approach to call a user-defined function in vba, that vba "session" does not see the newly inserted record.
Even if one passes in the identity of the newly added record, any queries referencing the table where the record was just added won't see the newly inserted record.
Has anyone developed a work around so that for example in building a closure-table, the newly added record is visible or can be used?
This is very similar to the problem Alberta Kallal has nicely shared solutions for of copying over an existing record using the "after update" approach to get around being unable to create a record within a for each loop. However, in this case I would like to use the result of a query as the basis for copying / inserting, not just copying over an existing row or 'hard coding' the business logic for the modifications into the datamacro (hence would be easy to do if vba approach could see the just added row).
Specific use case is trying to create a way of inserting "induced" records in an accounting application. One earns some money that has no tax deducted, so it is nice to have an automatic journal entry created showing a future liability to pay the tax. In other words, the presence of a record in a table should automatically generate additional records - and the business logic of those additional records is defined through queries.
Even more specifically, given a "transactions" table with fields RegisterID, AccountID, Amount, TrDate, and a "Induced Transaction Queries" table that specifies the queries to provide the induced transactions with fields AutoNumberId, QueryThatDefinesAdditionalTransactions (and multiple rows, e.g. "Query That adds self", "Query That Adds Tax Liability", "Query That Computes Sales Tax Portion"),
how can a datamacro create rows in a "Transactions For Analysis" Table based on iterating over the "Induced Transaction Queries" table and inserting the results of the query in each row applied to the newly added row in the original "transactions table"
Thx
Well, while calling VBA from the macro after insert event can’t get the row just inserted, that VBA routine can read + update as many OTHER rows as you please. And if that new row or data you write out in VBA has to include the data from the row just inserted?
Well pass the columns to the VBA routine. So it now can go add up all the other rows, and THEN include the values just passed from the data macro.
So the data macro (after insert) can look like this:
And the VBA code thus can look like this:
Public Function AfterU(vid As Variant, Amount As Variant)
Debug.Print vid, Amount
Dim rst As DAO.Recordset
' open table, sum data
' add Amount passed.
' write out data to some table.
' caution - don't add reocrds to this table that has the trigger
' else you wind up in a endless loop
End Function
The above of course has to be placed in a standard code module (not forms), and has to be defined as public as per above.
So while you find that the record JUST added is not yet committed to the table (it is about to be), you can still run + call some VBA code. You just not get your hands on the record just (about to be) inserted.
However, since you can pass the needed columns such as amount etc. to include in the final total? Then you are free to write as much VBA update and insert code as you wish. So you can pull some records, build a total, and now update some existing record, or even add a new record. Just include the new amount passed also.
As noted, you don’t want to “tangle” up writing to a table that has such a trigger with VBA inserts since you can easy get stuck a endless loop.
However, for adding up, or updating, or inserting to another table, you should be fine to do what you please in the VBA code.

Access, After Insert and the missing ID

I'm have to create an access web database and running into a frustrating problem when inserting a record into a table.
I'm trying to use the After Insert macro to set a problem number field, thusly:
Edit Record
SetField
Name: [Problem Number]
Value =: [ID] (There is no more logic here but even this simplest case fails)
The problem is that ID doesn't have a value so Problem number ends up blank.
This logic works on an After Update which makes sense as it has an ID at that point.
Is there anyway I achieve this without switching to VB code.
A few things. You do not want to use the after update event to modify the current record since it would in theory cause the before update event and the after update event to fire AGAIN. This potentially would cause a circular loop.
And if you think about this it makes little sense RIGHT after you JUST saved the record all nice to the table then you edit the record again! In fact you find by design that the current record in context is read only in that after update event. So you cannot execute an edit record on the current record in context in the after update event and you get a "read only" error if you check the error log.
In the before change event, [id] is not available. However, you can most certainly pick up and use the [id] in the after update event.
However, if you are going to create a NEW record in another table, then the NEXT line outside of the create record block allows you to pick up the just created record with
[LastCreateRecordIdentity]
So the record write occurs on the next line outside of the create record block.
For example here is some code that creates a new record and note VERY careful the "indentation" of the code.
If fact if you click on the create record command in the above then the WHOLE create block of code will highlight. Note how the NEXT line of code is OUTSIDE of the blue code block and that is the code where we can use [LastCreateRecordIdentity].
The blue highlighted code is thus this:
So the NEXT line right outside of the create record is when you can pick up the new id. In the above I actually "return" the new id just created via the returnVars to the calling routine.

MS Access "record changes" log

Whenever a record is deleted or updated on a form, I want to save its old values in a history table (let's call it Revised). I guess I have to do the following:
For record changes:
use the BeforeUpdate event to save the data somewhere (collection ? array ? or to a recordset -the Revised table- without saving-yet ?)
use the AfterUpdate event to add/save that data to the Revised table
For Deletions:
use the OnDelete event to save the data - but again how ? several records could be deleted at once since the form (a subform in fact) is in datasheet view
use the AfterDelConfirm to add that data to the Revised table.
Do you have any clues, comments or links for this ?
This is all in a "pure Access" (no SQL Server) at the moment.
Many thanks !
Edit: as usual, properly asking the question gaves me ideas:
option 1
use the BeforeUpdate or the OnDelete to build the SQL statement, and use the AfterUpdate or the AfterDelConfirm to Execute the SQL statement. But that won't work for multiple deletions ?
option 2
have the Revised recordset defined at form level, insert the record "Before" but only Update "After". Again, problem with multiple deletes.
I've successfully used a variation of Allen Browne's approach in a couple of different projects. Check out his website for more details:
Creating an Audit Log
His solution uses temp tables and four generic function calls to handle the issue with multiple deletes.
Another approach I have considered more recently, but have not had an opportunity to actually implement, would be to use transactions to perform the change tracking. The basic algorithm would be:
use BeginTrans on the workspace prior to making any changes
in the OnDelete event
perform the deletions in code executing Delete queries against the workspace from step 1
add a record to your change auditing table
in the BeforeDelConfirm event
set Cancel = True
display your own Confirmation dialog
if user confirms then CommitTrans on workspace
otherwise Rollback the transaction on the workspace
Similar approach for Updates/Inserts. This would avoid the need for temporary tables/arrays/collections, etc. but I haven't fully thought through everything. The devil may be in the details.
An "easy" and generic solution, which could be implemented for multiple tables, would be to have a tracking table, made of the following:
Track_Table
==================================================
id_track as primary key
id_table as name of the table which has been updated
id_primaryKey as the record identifier (the PK of the updated record)
changeType, being either DEL or UPDATE
changeDate, as dateTime value
fieldName, as text
oldValue, as text or memo
newValue, as text or memo
if you have to identify the user who did the update, just add
userId
in your table ...
You could then create some generic "before update" and "after update functions" to be called on selected form's beforeUpdate and afterUpdate events. The beforeUpdate fonction will store the old value in a variable, while the afterUpdate function will populate the missing data and insert a new record in the track table.
You will have to find a way to find out the right\corresponding table name and field name. This could be difficult if you are using views or field aliases to display your data in forms.
Of course, all tables to be followed must have a primary key so you can follow changes at the record level. PKs set on multiple fields will surely be problematic ....
oldValues and newValues will have to be converted as text so you can store them in a text or memo 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.

A little Access VBA help? Validating against duplication of a non key field?

I am adding a part name to the database using a form, What code do I put behind the Add part button to validate against duplicate part names? (part number is the primary key) I think I need another recordset to search and compare the table but i'm a bit lost, any help would be great.
Private Sub btn_add_Click()
rs_parts.AddNew
With rs_parts
!partrno = lbl_partno.Caption
!Name = txt_name
rs_parts.update
end with
I've discussed my approach to this before, and given an example form for adding a new record.
I use an unbound form to collect the information needed to create the new record, and have it check for duplicates, and present a list of them to the user so the user can decide what to do.
In this case, it sounds like a unique index is in order, so you won't really need to worry about close matches. I would probably still use an unbound form to capture the new value and run the check before even attempting to add it. In that case, I'd just notify the user that it's a dupe.
Should you add a unique index to the part name field?
If you want, you can create a query on your part table with one column for the name and a parameter for the criteria they've entered in txt_name. Then pass the value they entered as a parameter to the query and see if you get any results.