Generic Delta load functions for tables with timestamp and id
When loading data from many tables, and when its necessary to do more than the usual store and drop commands. You often end up with a lot of code that does stuff: Like fetching last timestamp for the load or storing the incremental data. And quite a lot traces to make its works correctly.
So I tend to write some functions for this which lets you save many line of code and make maintenance so much easier.
These functions should work generically for any tables that both have a modified date and an auto incrementing id fields.
First we need to set some general variables:
SET __LastExecTime = 0; Let __ExecTime = timestamp(Today(), 'YYYY-MM-DDXhh:mm:ss'); Set __DeltaPath = '..\Data\ERP\Delta\';
I use 2x underscores prefix for variable names that should only be used in the load script. And single underscore prefix for variables I use in functions.
LastExecTime is set to 0, because for each table we load, we need to know its previous value, or if its the first time then its need to be in the beginning of time.
ExecTime we set to now, we use this to discard records that could be created while we are loading data. If we don't do this we risk getting some orphans. Rows that don't have their relations.
DeltaPath is where on the filesystem data should be stored.
The first subroutine we use is GetModifiedData, which is used to figure out what date we can use to define our delta.
Sub GetModifiedDate(_Filepath,_DateField)
Let _CreateTime = QVDCreateTime('$(_Filepath)');
Trace GetModifiedDate: $(_Filepath),
$(_DateField),
$(_CreateTime);
// If a file already exist
if not isnull(QVDCreateTime('$(_Filepath)')) then
Trace QVD Exist at $(_Filepath);
// Then get the highest timestamp from it
LoadTime:
Load Max($(_DateField)) as LastModifiedDate
From $(_Filepath) (qvd);
Let __LastExecTime = timestamp(peek('LastModifiedDate',0,'LoadTime')
,'YYYY-MM-DDXhh:mm:ss');
Drop Table LoadTime;
Else
Trace Nofile at $(_Filepath);
// Reset timestamp
LET __LastExecTime = timestamp(0,'YYYY-MM-DDXhh:mm:ss');
End if
End SubThe second is StoreQVD and this we use to store our Data with. For both routines I have added a lot of Trace's, since I need more information than QlikViews dialogs provide to make sure this works as expected:
Sub StoreQVD (_Filepath,_IdField,_Table)
Let _Rows = QvdNoOfRecords ('$(_Filepath)');
Trace StoreQVD: $(_Filepath),
$(_IdField),
$(_Table),
$(_RowCount);
if Not isnull(QvdCreateTime('$(_Filepath)')) then
Trace Contatenating;
Concatenate ($(_Table))
LOAD *
From $(_Filepath) (qvd)
Where Not Exists ($(_IdField),$(_IdField));
end if
If NoOfRows('$(_Table)') > 0 AND ScriptErrorCount = 0 Then
Store $(_Table) Into $(_Filepath);
Let _RowsFinal = QvdNoOfRecords ('$(_Filepath)');
Trace Stored file before: $(_Rows), after: $(_RowsFinal);
Else
Trace No file stored ($(_Filepath));
End If
Drop Table $(_Table);
End SubFinally you can wrap these two functions around yor regular collect statements like this:
Call GetModifiedDate('$(__DeltaPath)Transaction.qvd'
,'ModifiedDate');
Transaction:
SQL SELECT
Amount,
Id,
ModifiedDate
FROM Transaction__c
WHERE ModifiedDate >=$(__LastExecTime)
and ModifiedDate < $(__ExecTime)
Order by Id;
Call StoreQVD('$(__DeltaPath)Transaction.qvd'
,'Id'
,'Transaction');
Call GetModifiedDate('$(__DeltaPath)TransactionLine.qvd'
,'ModifiedDate');
TransactionLine:
SQL SELECT
LineAmount,
Id,
ModifiedDate
FROM Transaction__c
WHERE ModifiedDate >=$(__LastExecTime)
and ModifiedDate < $(__ExecTime)
Order by Id;
Call StoreQVD('$(__DeltaPath)TransactionLine.qvd'
,'Id'
,'TransactionLine');And so on. The idea is really to write generic code, that dramatically lowers the amount of lines you need and keep the tricky stuff centrally handled. In this example we have saved about 40 lines pr. table we need to fetch!
Hope you can use this :)
Recent comments
1 week 3 days ago
1 week 3 days ago