Using change tracking while ignoring an individual column - sql

Presently, I'm tracking changes to all of my tables using SQL Server 2008 Change Tracking. Everything works out of the box just fine. However, an additional complexity is that the application reading these changes needs to make a change to a date column on each table that is being tracked. Changes in my application are like triggers to tell me that I need to send out additional data. This could cause an endless cycle if not managed.
There's a sent date that gets filled in after each change is read.
Is it configurable at a database/table level to ignore an individual column on a table so that versions/changes are not tracked when that column is modified?

Using change tracking, there's two ways but both involve merely filtering the results; there is not a way to limit the change tracking by column.
1) Filter by context
The following link shows how to change the context for when an application changes data. If you change the context specific to what is making the changes, you can then filter it by that when you query. http://msdn.microsoft.com/en-us/library/cc280462(v=sql.105).aspx
2) Filter using the columns updated mask
In addition, I have to admit that I roll my own change tracking still. I have scripts that I execute to autogenerate code triggers. They can be customized to prevent non-changing updates (i.e. a row update that changes no fields you are interested in), plus they allow me to fully control things. I can track which fields I want, plus I can move all of my tracking/default fields (such as suser_sname()) into the tracking table so that the day to day business tables are kept slim. If you are interested in this option, reply as such and I'll post the code to autogenerate the triggers and tracking table for a given table name.

Related

Event sourcing: Tracking each entity field changes in specific interval

I'm trying to figure out what could be the best solution for this use case:
there is a need to track each field changes in agreement entity. So when someone makes update for any field they must set when this is going to be applied (can set date in future or past). And later it should be possible to filter by some field's value in the past for specific date interval. So basically it's needed to have history of each field and apply correct value according to current date.
At first glance, it's possible to use event sourcing when entity is built from events on write side and for read side it could be used snapshots so on each new change for entity would be rebuild in SQL database table for quering operations.
Is there any simpler solution for this case?
Yes, ES could be an appropriate solution for your problem. You track all fields changes as separate events. And it would help if you create various read models according to your requirements.
If you need to store the history of each field change, you probably have a read model for this purpose and another for your last or per version snapshot of your read side entity.
Noice: You create your read models according to your current or future requirements. Maybe you need a new read model after 6 months, So you create another read model. BTW you can achieve this by using event sourcing.

Is there a way to create an virtual table that would be compared to one after editing?

I have a table [contractor c] in which only one field [tin] may be edited. If the user tries to change data in other field it shall not be updated. Was wondering if making a view of the c before editing and then comparing the view with edited table is a good idea. But that would require two scripts- before and after update.
I could also make a validation on every single field except tin, but there is 'a lot' of fields.
Looking for the best and most optimal way to approach this task.
This is too long for a comment. There are many ways to do what you describe. "Views" are not one of them. In SQL, a view is a stored query. It does not store values. That is definitely not going to help, because the view changes with the underlying tables.
If only one column can be updated, then one method is to implement a trigger that checks the before- and after- versions of the record and only allows updates when no other fields change.
You can start learning about triggers in the documentation.
An alternative mechanism is to make the table unupdatable except for update permissions on a single column. You can learn about permissions in the documentation.
If for some reason you wanted to do all the work in the application, then transactions might come into use. You would not commit the transaction until the update meets your requirement. Transactions are explained in the documentation.

Effectively make database records read-only

How can I make sure that specific data in the database isn't altered anymore.
We are working with TSQL. Inside the database we store contract revisions. These have a status: draft / active. When the status has become active, the revision may never be altered anymore. A revision can have 8 active modules (each with its own table), each with their own settings and sub-tables. This creates a whole tree of tables with records that may never change anymore when the contract revision has been set to active.
Ideally I would simply mark those records as read-only. But such thing does not exists as of today. The next thing that comes to mind are triggers. Thus I have to add those triggers to a lot of tables, all which are related to the contract revision.
Now maybe there are other approaches, like a database only for archiving on which the user only has insert rights. Thus when a contract revision has become active, it is moved from one DB to the archive DB (insert is allowed). And can never be altered anymore (DENY UPDATE|DELETE).
But maybe there are other more ingenious options I haven't thought of, and you did. Maybe including the CLR or what not.
So how can I make a tree-structure of records inside our TSQL database effectively readonly that is the most maintenance free, easy to understand, quickly to setup, and can be applied in a most generic way?
What ever you do (triggers, granted rights...) might be overcome by a user with higher rights, this you know for sure...
Is this just to archive this data?
One idea coming into my mind was to create a nested XML with all data within on big structure and put this somewhere into a side table. Create a INSTEAD OF UPDATE,DELETE TRIGGER where you just do nothing. Let these tables be 1:1-related.
You can still work with this data, but not quite as fast as being read from physical tables.
If you want, you even might convert the XML to a string and calculate some Hash-Code, which you store in a different place to check for manipulations.
The whole process might be done in one single Stored Procedure call.

How should I deal with copies of data in a database?

What should I do if a user has a few hundred records in the database, and would like to make a draft where they can take all the current data and make some changes and save this as a draft potentially for good, keeping the two copies?
Should I duplicate all the data in the same table and mark it as a draft?
or only duplicate the changes? and then use the "non-draft" data if no changes exist?
The user should be able to make their changes and then still go back to the live and make changes there, not affecting the draft?
Just simply introduce a version field in the tables that would be affected.
Content management systems (CMS) do this already. You can create a blog post for example, and it has version 1. Then a change is made and that gets version 2 and on and on.
You will obviously end up storing quite a bit more data. A nice benefit though is that you can easily write queries to load a version (or a snapshot) of data.
As a convention you could always make the highest version number the "active" version.
You can either use BEGIN TRANS, COMMIT and ROLLBACK statements or you can create a stored procedure / piece of code that means that any amendments the user makes are put into temporary tables until they are ready to be put into production.
If you are making a raft of changes it is best to use temporary tables as using COMMIT etc can result in locks on the live data for other uses.
This article might help if the above means nothing to you: http://www.sqlteam.com/article/temporary-tables
EDIT - You could create new tables (ie NOT temporary, but full fledged sql tables) "on the fly" and name them something meaningful. For instance, the users intials, followed by original table name, followed by a timestamp.
You can then programtically create, amend and delete these tables over long periods of time as well as compare against Live tables. You would need to keep track of how many tables are being created in case your database grows to vast sizes.
The only major headache then is putting the changes back into the live data. For instance, if someone takes a cut of data into a new table and then 3 weeks later decides to send it into live after making changes. In this instance there is a likelihood of the live data having changed anyway and possibly superseding the changes the user will submit.
You can get around this with some creative coding though. There are many ways to tackle this, so if you get stuck at the next step you might want to start a new question. Hopefully this at least gives you some inspiration though.

Building a ColdFusion Application with Version Control

We have a CMS built entirely in house. I'm the new web developer guy with literally 4 weeks of ColdFusion Experience. What I want to do is add version control to our dynamic pages. Something like what Wordpress does. When you modify a page in Wordpress it makes some database entires and keeps a copy of each page when you save it. So if you create a page and modifiy it 6 times, all in one day you have 7 different versions to roll back if necessary. Is there a easy way to do something similar in Coldfusion?
Please note I'm not talking about source control or version control of actual CFM files, all pages are done on the backend dynamically using SQL.
sure you can. just stash the page content in another database table. you can do that with ColdFusion or via a trigger in the database.
One way (there are many) to do this is to add a column called "version" and a column called "live" in the table where you're storing all of your cms pages.
The column called live is option but might make it easier for your in some ways when starting out.
The column "version" will tell you what revision number of a document in the CMS you have. By a process of elimination you could say the newest one (highest version #) would be the latest and live one. However, you may need to override this some time and turn an old page live, which is what the "live" setting can be set to.
So when you click "edit" on a page, you would take that version that was clicked, and copy it into a new higher version number. It stays as a draft until you click publish (at which time it's written as 'live')..
I hope that helps. This kind of an approach should work okay with most schema designs but I can't say for sure either without seeing it.
Jas' solution works well if most of the changes are to one field, for example the full text of a page of content.
However, if you have many fields, and people only tend to change one or two at a time, a new entry in to the table for each version can quickly get out of hand, with many almost identical versions in the history.
In this case what i like to do is store the changes on a per field basis in a table ChangeHistory. I include the table name, row ID, field name, previous value, new value, and who made the change and when.
This acts as a complete change history for any field in any table. I'm also able to view changes by record, by user, or by field.
For realtime page generation from the database, your best bet are "live" and "versioned" tables. Reason being keeping all data, live and versioned, in one table will negatively impact performance. So if page generation relies on a single SELECT query from the live table you can easily version the result set using ColdFusion's Web Distributed Data eXchange format (wddx) via the tag <cfwddx>. WDDX is a serialized data format that works particularly well with ColdFusion data (sorta like Python's pickle, albeit without the ability to deal with objects).
The versioned table could be as such:
PageID
Created
Data
Where data is the column storing the WDDX.
Note, you could also use built-in JSON support as well for version serialization (serializeJSON & deserializeJSON), but cfwddx tends to be more stable.