Академический Документы
Профессиональный Документы
Культура Документы
AL & DBMS
This guide includes the following three documents which have previously
been released as individual manuals:
AL Programmers Guide
AL Reference Guide
The NAVISION DBMS
This publication is subject to change without notice and does not represent any
commitment on the part of Navision Software a/s.
Navision Software a/s assumes no responsibility for any faults or shortcomings in
this publication.
The software described is supplied under license and must be used and copied in
accordance with the enclosed license terms and conditions.
According to existing Danish copyright legislation, it is against the law to
reproduce any part of this publication in any form or by any means, without the
permission of Navision Software a/s.
Table of Contents
Part 1, AL Programmers Guide 1
Examples and Notes 2
Notation for Datatypes in Expressions 2
Typographical Conventions 2
Compilation vs. Run Time Errors 3
Important Terms 3
Expressions in AL 4
AL Data Types 5
Constants 8
Elements in AL Expressions 8
Variables 9
Operators 13
Operator Hierarchy 14
Function Calls 15
Compound Statements 16
Conditional Statements 16
The AL Control Language 16
Repetitive Statements 18
EXIT Statements 20
WITH Statements 21
Comments in Programs 22
Type Conversion in Expressions 23
Type Conversion Mechanisms 24
Relational Operators 24
Yes/No (Logical) Operators 27
Introduction to Arithmetic Operators 27
Part
1 AL Programmers Guide
This document provides detailed information about the Application Language
(AL). The aim is that this document should serve as a guide for the novice, and
also as a handbook and refresher for the pro. The aim of this document is neither
to teach the reader how to program, nor to introduce specific programming
techniques. This means that a certain amount of knowledge about programming
in other languages, for instance Pascal or C, is assumed.
Because AL, unlike most other 4GLs is very similar to commonly used
programming languages, youll find the many Pascal books and other training
aids a valuable resource as you create your own applications.
The following list outlines some of the most powerful properties of AL. The AL
language:
Performs automatic type conversion between related types (not only between
numbers
This will also be the proper place to notify the reader of the following
delimitations compared to languages such as standard Pascal:
New data types cannot be defined
AL Programmers Guide 1
Typographical Conventions
Typographical
Conventions
This AL manual uses special typefaces to help you distinguish different types of
text. Table 1 illustrates these conventions:
Table 1: Conventions
Convention
Applies to
Examples
Monospaced Font
AL code examples
Number:= 6;
Times Font
Normal text
This is a sentence
Helvetica Font
Table bodies
ALL CAPS
AL keywords when
used in normal text and
in AL code examples
This notation will only be used when the focus is on the datatypes rather than on
specific values. It is stressed that this notation is not a real AL notation, but
rather a notation which is intended to be used for descriptional purposes
AL Programmers Guide
Important Terms
Important
Terms
The aim of this section is to briefly discuss the following important terms:
Compilation vs. run time errors
This individual code line is also called a statement. Table 2 illustrates how the
statement can be can broken into smaller elements.
Description
34 + Total
:=
Amount
This is called a variable (or sometimes an identifier). Is used as a memory in order to stores values.
AL Programmers Guide
Expressions in AL
Expressions
in AL
This function takes three simple expressions as arguments, that is 31, 12 and
1996.
An AL expression is a group of characters that can include data values, variables,
arrays, operators, and functions (which can be evaluated into a value). All valid
AL expressions can be evaluated into a specific value which has an associated
data type.
All expressions in AL are built from:
Constants
Variables
Operators
Functions
Depending on the expression the evaluation will lead to a value from one of the
AL data types: Yes/No, Option, Integer, Long Integer, Decimal No., Date, Time,
Text or Code.
Table 3 shows some typical expressions.
Evaluates to...
'Welcome to Hawaii';
43.234;
ABS(-7234)
AL Programmers Guide
Expressions in AL
AL Data Types
This section describes the data types used in AL. The data types are divided into
three main categories, named: Simple Data Types, Composite Data Types and
Descriptional Data Types.
Results in...
t := 'AbC';
t := '123456abx';
AL Programmers Guide
Expressions in AL
Code. Denotes a special type of text string. When a given text is assigned to a
code type variable, the text is transformed to uppercase, and furthermore any
leading and trailing spaces are removed. The maximum length of a code type
variable ranges from 1 to 132 characters. The length of a code type variable
always corresponds to the number of characters in the text without leading and
trailing spaces. Table 5 shows some typical examples of Code string assignments.
In the examples it is assumed that the variable c has the type Code, and the
maximum length 4.
Results in...
c := 'AbC';
c := '1';
c := '';
c := ' 2 ';
c := '1 2';
Assume that D is an array variable of type Date with the dimensions 2x3x4. Then
D has 24 elements.
In order to index the first element, use D[1,1,1].
AL Programmers Guide
Expressions in AL
Option
Integer
Long Integer
Decimal No.
Strings
Text
Code
AL Programmers Guide
Elements in AL Expressions
Elements in AL
Expressions
The previous chapter has introduced you to the notion of expressions and
futhermore the data types used in AL was described. The aim of this chapter is to
present the basic elements of AL expressions. In short the following sections
will discuss the topics below:
Constants
Variables
Operators.
Functions
Constants
A constant is the simplest type of operand used in AL. The value of a constant
cannot be changed during the execution of the code. Constants can be defined for
each of the simple data types in AL.
Note: Before we define the valid ranges for the constants below,
we have to warn the reader: the numbers 32,767; 2,147,483,647
and 999,999,999,999,999.99 below cannot be entered in the AL
system using commas. The commas are only used to increase the
legibility in this document. If numbers are entered in the AL editor
using commas, a compilation error will occur.
Yes/No (Boolean) Constant. A Yes/No constant may either have the value
TRUE or FALSE.
Integer Constant. An Integer constant may have a value between -32,767 and
32,767.
Long Integer Constant. A Long Integer constant has a value in one of the
following intervals:
From -2,147,483,647 to -32,768 and
From 32,768 to 2,147,483,647
If the number is between -32,767 and 32,767, it is, as mentioned above, an
integer.
Decimal No. Constant. A Decimal No. constant must contain a decimal point
'.' and have at least one digit to the right of the decimal point (for example the
digit '0'). A constant of type Decimal No. can be used to represent decimal
numbers between -999,999,999,999,999.99 and 999,999,999,999,999.99 with 18
significant digits.
Date Constant. A Date constant is written as six digits followed by the letter
'D' (the date constant expressing 'undefined date' is, however, entered as '0D').
The six digits specify the date in the format MMDDYY.
Time Constant. A Time constant is written as nine digits followed by the letter
'T' (the 'undefined time' constant is, however, entered as '0T'). The nine digits
specify the time in the format HHMMSS[.XXX], that is a 24 hour format with an
optional part specifying thousandths.
Text Constant. A Text constant is a character string that is placed in
apostrophes ('). '' indicates the empty text string.
Examples
AL Programmers Guide
Elements in AL Expressions
Description
TRUE
231
Integer constant
50000
-23.7
122196D
141230T
'ABC
String constant
Variables
There are two types of variables in the AL system: User-defined variables and
Implicit variables.
Variables are defined by the user when new AL code is implemented. These userdefined variables are local to the AL module for which they have been defined.
These variables can be used to store information at run time, and the values can
be changed as desired.
Furthermore, a number of predefined variables are provided by the system. These
variables are automatically maintained by the system and are called Implicit
variables
The implicit variables can in many respects be used just like normal user defined
variables, but as the values of the implicit variables are maintained automatically
by the system, some restrictions should be observed.
The running system will sometimes enter a code module, for example entryprocessing code for a table. Before the module is entered, the system has
automatically assigned values to the associated implicit variables, and in the
module (in the AL triggers and the local functions) the values of these variables
can be used.
During the execution of AL triggers and local functions, the implicit variables
can be used just like normal variables (new values can be assigned to them) that
is, the values of the implicit variables are not updated by the system while the AL
code is being executed, but only before the module is entered. Some other
important properties are best explained using an example:
Example
A typical implicit variable is CursorPos, which describes the position of the
cursor. This implicit variable will be available in the AL triggers and the local
functions in some code modules, and can be read and changed as desired by the
user. But although the value of the implicit variable can be changed by the AL
code, the old value of CursorPos will be lost the next time the module is entered,
AL Programmers Guide
Elements in AL Expressions
Variable Names
Variable names must be unique, that is, two user defined variables with the same
name are not allowed in an AL module. Furthermore you cannot have user
defined and implicit variables with the same name. Uppercase and lowercase
letters are interpreted in the same way, that is Smith and SMITH are taken to be
referring to the same variable. In standard Pascal notation a variable name (an
identifier) can only be written as an unbroken word. This notation is extended in
AL; here it is also possible to use special characters (for example spaces) in a
variable name.
Observe the following basic restrictions:
The maximum length of a variable name is 20 characters.
All ASCII characters are valid in variable names, except the following:
Control characters (ASCII 0-31, 255)
10
Customer
StockGroup1
AL Programmers Guide
Elements in AL Expressions
"1st AddressLine"
"Purchase/Sales"
"Sales In GBP"
23"Tubes
Stock Group4
"Sale"s in GBP"
@-Names
END
Initialization
Internal variables are automatically initialized before an AL module is executed.
A Yes/No variable is set to FALSE, Number type variables are set to the default
value zero, while strings (Text and Code) are initialized to the value (the empty
string). Date and Time variables are set to respectively the undefined time 0T and
the undefined date 0D.
As previously mentioned the system automatically handles the implicit variables.
This also includes the necessary initialization. This means that no actions are
required by the user before the implicit variables can be used.
The automatic type conversion in assignments can also take freely place between
AL Programmers Guide
11
Elements in AL Expressions
Code Text
All the above has been based on simple variables. Nevertheless the same
assignment rules apply for arrays in AL. Furthermore, if the left operand in an
assignment (the variable) is an array, the dimension(s) of the right-hand side
expression must correspond to the dimension(s) of the variable.
Note: The type conversion that takes place in assignments can
cause run-time errors even though the types are convertable. A runtime error can occur in an assignment if the converted value is
outside the valid range for the left hand side variable.
Correspondingly a run time error can occur if the converted value is
outside the valid range for a parameter in a function call.
The following shows some examples of assignments:
Example
Let the variable A be defined as a one-dimensional array with 4 elements of the
type Text with the maximum length 10. A value could be assigned to the second
element in the array as shown below:
A[2]:= '0123456789';
Example
Let the variables Result, Amount and Total be defined as:
Result has the type Option.
The above code can always be compiled, but a run-time error will occur if the
result of the right-hand side expression 'Amount + Total' exceeds the valid range
of the datatype of the left-hand side variable (outside the range of 0 to 255).
Valid Assignments
Table 8, Valid assignments in AL, on page 13 provides an overview of whether
it is possible to assign the value of an expression of a given type to a variable of a
given type. The rows describe the type of the variable, and the columns describe
the type of the expression. The following signs are used in the table:
12
Yes
(Yes)
AL Programmers Guide
Elements in AL Expressions
Variable
Type
Valid?
YesNo
Option
Integer
Long
Integer
Decimal
No.
Date
Time
Text
Code
YesNo
Yes
Option
Yes
(Yes)
(Yes)
(Yes)
Integer
Yes
Yes
(Yes)
(Yes)
Long Integer
Yes
Yes
Yes
(Yes)
Decimal No.
Yes
Yes
Yes
Yes
Date
Yes
Time
Yes
Text
(Yes)
(Yes)
Code
(Yes)
(Yes)
Operators
Operators can be used in expressions in order to combine, investigate and
manipulate values and data elements. In the following the function of the
operators in AL are described.
Table 9 shows the valid operators in AL.
Table 9: Operators in AL
AL Operator
Meaning
Fields in records
()
Parentheses
[]
Indexing
Addition
Subtraction or negation
Multiplication
Division
DIV
Integer division
AL Programmers Guide
13
Elements in AL Expressions
Table 9: Operators in AL
MOD
Modulus
>
Greater than
>=
<
Less than
<=
Equal to
<>
Not equal to
AND
Logical Conjunction
OR
Logical Disjunction
NOT
Logical negation
The '+' and the '-' operators can be used both as unary and binary operators, the
'NOT' operator only as an unary operator, while all other operators are binary.
Most of the above operators can be used on different datatypes. The action of
these operators may depend upon the datatype of expression they are used on. A
typical example:
Example:
The '+' operator can be used as a binary operator in for example:
Number + Number, which returns the sum of the numbers, that is a result of
the type Number.
String + String, which returns the concatenation of the strings, that is a result
of the type String.
Furthermore the '+' operator can be used as an unary operator to indicate sign, for
instance:
+ 34545
One of the following chapters Type Conversion in Expressions on page 23 will
show how the function of the operators vary according to the data types of the
applied arguments.
Operator Hierarchy
The operators just discussed, are organized in a hierarchy which decides the
order of evaluation of the operands in a given expression. The list below shows
the precedence order of the AL operators:
1. .(fields in records), [] (indexing), () (parentheses)
2. NOT, - (unary), + (unary)
3. *, /, DIV, MOD, AND
4. +, -, OR
5. >, <, >=, <=, =, <>
Example
This example illustrates the effect of the operator hierarchy. The expressions
14
AL Programmers Guide
Elements in AL Expressions
below, which apparently are the same, will produce different results.
The expression
2+3 *4
is evaluated to
14, whereas
the expression
(2 + 3) * 4
is evaluated to
20.
Function Calls
AL covers a number of functions for different purposes, such as string handling,
text formatting, database handling and so on. Some of these functions differ from
standard Pascal, as it is possible to use a variable number of parameters. In a
function call, the parameters are separated by commas, and the optional
parameters may be omitted from the right.
This means that if the function has, for instance, 3 optional parameters, then it is
not possible to omit the second without omitting the third:
Example
The fictitious function:
FUNCTION([Optional1] [, Optional2] [, Optional3])
Example
A typical example of a normal Pascal-like function is ABS.
Value := -1033;
PositiveValue := ABS(Value);
AL Programmers Guide
15
The AL
Control
Language
This section describes the basic constructs in the control language in AL and how
to use them. All the AL programs you create consist of one or more statements.
The statements are executed sequentially in top-down order. However, you will
often need to control the direct top-down flow of the execution. You might
desire, for one reason or another, to repeat the execution of one or more
statements a number of times, or in other situations you might desire to make the
execution of a certain statement conditional and so on.
Various control constructs are available in AL, just like in Pascal. These control
constructs can be used to design very complex control structures, in order to take
different actions according to the current state of the execution.
The control constructs in AL are divided into the following main groups:
Compound Statements
Conditional Statements
Repetitive Statements
WITH Statements
Compound Statements
In some cases the AL syntax will only allow use of a single statement. If you
desire to execute more than one simple statement in such a case, the statements
can be turned into a compound statement, by 'encapsulating' the statements
between the keywords BEGIN and END. The syntax is:
BEGIN
<Statement 1>;
<Statement 2>;
.
.
<Statement n>;
END
Conditional Statements
By using a conditional statement, you can specify a condition and one or more
commands to be executed according to if the condition is evaluated to TRUE or
FALSE. There are two types of conditional statements in AL:
1. IF THEN [ELSE], when there are a maximum of 2 selections.
2. CASE, when there are multiple selections.
IF THEN ELSE
16
AL Programmers Guide
Which means:
If <Condition> is true, <Statement1> is executed. If <Condition> is false,
<Statement2> is executed. As defined earlier, the square brackets around ELSE
<Statement2> means that this part of the statement is optional.
This statement is used when different actions are to be executed, depending on
the evaluation of the <Condition>
It is possible to build even more complex control structures by nesting IF THEN
ELSE statements. A typical example is:
IF <Condition1> THEN IF <Condition2> THEN <Statement1> ELSE
<Statement2>
Example
(1).
(2) IF Amount < 1000
(3) THEN BEGIN
(4)
IF I > J THEN Max := I
(5)
ELSE Max := J;
(6)
Amount := Amount * Max;
(6)
END
(7) ELSE
(8).
A common error for the AL novice, is to put an extraneous semicolon at the end
of a line before an ELSE (line 4). As mentioned above this is not valid according
to the syntax of AL, as the semicolon is used as a statement separator. (The end
of line 4 is inside the inner IF statement).
CASE
The syntax for the CASE statement is:
CASE <Expression> OF
<Value set 1> : <Statement 1>;
AL Programmers Guide
17
In the above definition the <Expression> cannot be a record, and the <Value set>
must be an expression.
CASE statements are also called multi-option statements and are typically used
when a selection between more than two different actions are to be made. The
function of the CASE statement is as follows:
The Expression is evaluated, and the first value set matching, causes an
associated statement to be executed.
If none of the value sets matches the value of the expression and the ELSE part
has been omitted, no action will be taken; but if the optional ELSE part is used,
then the associated statement will be executed.
The type of the value sets must be the same as the type of <Expression> or at
least convertable to the same type.
Note: The datatype of the value sets will be converted to the same
datatype as the evaluated <expression>, if necessary. Due to this
type conversion, an overflow may occur at run-time, if the resulting
datatype cannot hold the values of the value sets.
Example
This AL code sample will print various messages depending on the value of
Number. If the value of Number does not match any of the entries in the CASE
structure, the ELSE entry will be used as default.
CASE Number OF
1,2,9: MESSAGE('1, 2 or 9');
3,89,17: MESSAGE('3, 89 or 17');
ELSE MESSAGE('Neither 1, 2, 3, 9, 17 nor
89');
END
Repetitive Statements
A repetitive construct is also known as a loop. The looping constructs in AL are:
FOR, which repeats the inner statements until a counter variable equals the
maximum or minimum value specified.
WHILE, which repeats the inner statements while the specified condition is
TRUE. The statements in a loop of this type is repeated 0 or more times.
REPEAT, which repeats the inner statements until the specified conditions
evaluates to FALSE . The statements in a loop of this type is always executed
at least one time.
FOR TO/DOWNTO
The syntax for the FOR TO (and FOR DOWNTO) statement is:
18
AL Programmers Guide
When the above statement is executed, a run-time error will occur, because the
system tries to convert the start and end values to the same type as the control
variable; but as Count has been declared as an Integer variable, an error will
occur when 1000000 is to be converted, because this end value is outside the
valid range for Integers.
Example
This example illustrates nesting of FOR statements:
FOR I := 1 TO 5 DO
FOR J := 1 TO 7 DO
A[I,J] := 23;
The two FOR statements above could be used to initialize all elements in a 5 x 7
array with the value 23;
WHILE DO
The WHILE DO statement has the following syntax:
AL Programmers Guide
19
REPEAT UNTIL
The syntax for the REPEAT UNTIL statement is:
REPEAT <Statement> UNTIL <Condition>
EXIT Statements
The EXIT statement is yet another construct you can use to control the flow of
the execution. The syntax of an EXIT statement is:
EXIT([<Value>])
20
AL Programmers Guide
string).
A compile-time error will occur if EXIT is called with a return parameter from:
1. System defined triggers
2. Local functions, which is not supposed to return a value
Example
The following illustates the use of the EXIT statement in an arbitrary local
function. Assume that the IF statement is used to detect an error. If the errorcondition is met, the execution is stopped and the local function returns the errorcode 1.
FOR I := 1 TO 1000 DO
BEGIN
IF Amount[I] < Total[I] THEN EXIT(1);
A[I] := Amount[I] + Total[I];
END;
WITH Statements
The syntax for the WITH statement is:
WITH <Record> DO <Statement>
When working with records, addressing is carried out as the record name, a dot
and the field name: <Record>.<Field>
If you continuously work with the same record, then you can use WITH
statements. When you use a WITH statement it will not be necessary to specify
the record name more than once.
Within the scope of <Statement>, fields in <Record> may be addressed without
specification of the record name.
Several nested WITH statements may be used. In case of identical names, the
inner WITH will overrule the outer WITH-statements. The only restriction on the
use of nested WITH statements, is that WITH cannot be used on an element in
an array of records.
Example
This example shows two ways of writing the same code:
CustomerRec.No:= '1234';
CustomerRec.Company:= 'Windy City Solutions';
CustomerRec.Manager:= 'Joe Blow';
CustomerRec.Address:= '1241 East Druid Avenue';
CustomerRec."State and Zip":= 'Chicago, IL 60079';
AL Programmers Guide
21
'Chicago, IL
60079';
Comments in Programs
You can insert comments about the code, or 'outcomment' parts of your code
temporarily to prevent its execution.
A comment starts with '{' or and ends with '}' or ''. Any number of nested
comments may occur. In such cases, the comment runs from the first comment
start to the last comment end.
The system does not distinguish between the '{ '- and ''- type comments, that is,
it is possible to start a comment using a '{' and end it with a ''. The user should
be aware of this when using lines to draw figures inside a comment.
Example:
{
This is a sample comment which is ignored by the AL compiler
}
Example:
{ This comment { is partly inside } another comment }
Example:
The last example illustrates how you should not do when you a apply a box
comment:
A
B
C
D
:=
:=
:=
:=
34;
56;
345;
781;
By placing the box comment to the right of the AL statements, the third and
fourth lines are assumed by the system to be part of the comment, that is, only A
and B are assigned values, while C and D are not. The solution is to separate the
box comment from the AL statements, like:
A := 34;
B := 56;
This is a box comment
C := 345;
D := 781;
22
AL Programmers Guide
Type Conversion
in Expressions
A statement of this type involves one or two type conversions. The right-hand
side of the statement involves the evaluation of the expression 1556 + 56000 (in
other words Integer + Long Integer). In order to evaluate this expression, the first
operand (1556) will have to be converted from Integer to Long Integer. The
addition operator will then return a Long Integer result. But if the type of the lefthand side variable has been declared as for instance Decimal No., a type
conversion from Long Integer to Decimal No. has to take place before the value
can be assigned to Sum. The latter category of conversion has already been
discussed. See Assignment and Type Conversion on page 11.
In this section we will consider the type conversion that (might) take place when
expressions are evaluated.
Initially some general rules can be outlined:
When asked to evaluate an expression of mixed datatypes, the system will (if
possible) always convert, a least one of the operands to a more general
datatype.
The datatypes in the two main groups Numbers and Strings, can be ranked
from 'most general' to 'least general', as defined below.
Numbers
Most General
Decimal No
Long Integer
Integer
Least General
Option
Strings
Text
Code
The most general datatypes include all possible values from the less general
datatypes. The above should be interpreted as follows: a Decimal No. is
more general than a Long Integer, which again is more general than an
Integer and so on.
Type conversion can take place in some cases although two operands have the
same type. A typical example is an expression like:
Integer + Integer
In this case the system will convert both the operands to Long Integers, and
the resulting datatype will be Long Integer.
AL Programmers Guide
23
When the left-hand side sub-expression has been converted, the expression can
be evaluated, and the resulting data type will be Decimal No.:
Decimal No. + Decimal No. Decimal No.
Example:
Evaluation of a String expression:
Text + Code
When the right-hand side argument has been converted, the expression can be
evaluated, and the resulting datatype will be Text.
Text + Text Text.
Logical operators
Arithmetic operators
The following sections aim at discussing the properties of the operators in AL.
For each category of operators the valid datatypes for the arguments are
discussed, and furthermore we define the resulting data types when evaluating
expressions.
We will start with a discussion of the so-called relational operators, as these are
common to most of the AL datatypes.
Relational Operators
The relational operators are used to compare expressions. Table 10 defines the
evaluation rules for relational operators. The rules assume that the expressions
evaluates to comparable types. Please refer to Table 11, Valid uses of relational
operators, on page 26 for an overview of which datatypes are comparable.
24
AL Programmers Guide
Name
Expression
Resulting
Datatype
>
Greater than
Yes/No
<
Less than
Yes/No
<=
Yes/No
<>
Not equal to
Yes/No
Equal to
Expr = Expr
Yes/No
1. All relational operators are binary infix operators, in other words, takes a left
and a right argument and are placed between the arguments.
AL Programmers Guide
25
Left
Argument
26
Relational
Operators
Yes/No
Option
Integer
Long
Integer
Decimal No.
Date
Time
Text
Code
Yes/No
Yes/No
Option
Yes/No
Yes/No
Yes/No
Yes/No
Integer
Yes/No
Yes/No
Yes/No
Yes/No
Long Integer
Yes/No
Yes/No
Yes/No
Yes/No
Decimal No.
Yes/No
Yes/No
Yes/No
Yes/No
Date
Yes/No
Time
Yes/No
Text
Yes/No
Yes/No
Code
Yes/No
Yes/No
AL Programmers Guide
Name:
Expression:
Resulting
Datatype:
NOT
Logical negation
NOT Yes/No
Yes /No
AND
Logical and
Yes/No
OR
Logical or
Yes/No OR Yes/No
Yes/No
As table 12 shows, the NOT operator is a unary prefix operator, that is, takes only
one argument and is placed in front of the argument, while the AND and OR
operators are binary infix operators, that is takes two arguments and are placed
between the corresponding arguments.
Name:
Expression:
Resulting
Datatype
Addition
Option + Integer
Integer
Addition
Integer + Option
Integer
Subtraction
Option - Integer
Integer
Subtraction
Integer - Option
Integer
AL Programmers Guide
27
Name:
Expression:
Resulting
Datatype
Unary plus
+ Integer
Integer
Unary minus
- Integer
Integer
Addition
Integer + Integer
Long Integer
Subtraction
Integer - Integer
Long Integer
Multiplication
Integer * Integer
Long Integer
Division
Integer / Integer
Decimal No.
DIV
Integer division
Integer
MOD
Modulus
Integer
Name:
Expression:
Resulting
Datatype
Unary plus
+ Long Integer
Long Integer
Unary minus
-Long Integer
Long Integer
Addition
Long Integer
Subtraction
Long Integer
Multiplication
Long Integer
Division
Decimal No.
DIV
Integer division
Long Integer
MOD
Modulus
Long Integer
28
AL Programmers Guide
Name:
Expression:
Resulting
Datatype
Unary plus
+ Decimal No.
Decimal No.
Unary minus
- Decimal No.
Decimal No.
Addition
Decimal No.
Subtraction
Decimal No.
Multiplication
Decimal No.
Division
Decimal No.
DIV
Integer Division
Decimal No.
MOD
Modulus
Decimal No.
Name
Expression:
Resulting
Datatype
Date addition
Date + Number
Date
Date subtraction
Date - Number
Date
Date difference
Date - Date
Integer
In the 'Date addition' and 'Date subtraction' examples above, a run-time error will
occur if Date is a closing date. If date is undefined (0D), a run-time error will
occur.
Examples: Time Operators
Name:
Expression:
Resulting
Datatype
Time addition
Time + Integer
Time
Time addition
Time
AL Programmers Guide
29
Name:
Expression:
Resulting
Datatype
Time subtraction
Time
Time difference
Time - Time
Long Integer
The time unit is milliseconds. If time is undefined (0T), a run-time error will
occur.
Examples: Text and Code (String) Operators
Name:
Expression:
Resulting
Datatype
Concatenation
Text + Text
Text
Concatenation
Text + Code
Text
Concatenation
Code + Text
Text
Concatenation
Code + Code
Code
This ends the examples of the arithmetic operators. At this point you should feel
quite comfortable with the basic uses of the arithmetic operators in AL.
Nevertheless the above examples do not cover all the possible uses of the
operators. The following tables provide a full description of uses of the
arithmetic operators and the resulting datatypes.
30
AL Programmers Guide
Integer
Long Integer
Decimal No.
Integer
Long Integer
Decimal No.
Integer
Long Integer
Decimal No.
Defined?
Yes/No
Option
Integer
Long
Integer
Decimal
No.
Date
Time
Text
Code
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
Yes
DIV
Yes
Yes
Yes
MOD
Yes
Yes
Yes
Each of the following tables define the valid uses of the binary arithmetic
operators, and the resulting datatypes.
AL Programmers Guide
31
Option
Integer
Long
Integer
Decimal
No.
Date
Time
Text
Code
Yes/No
Option
Long
Integer
Long
Integer(C)
Decimal
No. (C)
Integer
Long
Integer
Long
Integer
Long
Integer(C)
Decimal
No. (C)
Long Integer
Long
Integer(C)
Long
Integer
Long
Integer(C)
Decimal
No. (C)
Decimal
No.
Decimal
No.(C)
Decimal
No. (C)
Decimal
No. (C)
Decimal
No. (C)
Date
Date(A)
Date(A)
Date(A) (C)
(C)
(C)
(D)
Time
Time(B)
Time(B)
Time(B) (C)
(D)
Text
Text
Text
Code
Text
Code
Left
Argument
(C)
(C)
(C)
(A) in the above table means that the operation is not defined for the date 0D.
(B) in the above table means that the operation is not defined for the time 0T.
(C) in the above table indicates that overflow may occur.
(D) in the above table indicates that the operation is not defined if Decimal No.
has a fractional part.
32
AL Programmers Guide
Yes/No
Option
Integer
Long
Integer
Decimal
No.
Date
Time
Text
Code
Yes/No
Option
Long
Integer
Decimal
No. (C)
Decimal
No. (C)
Decimal
No. (C)
Decimal
No. (C)
Decimal
No. (C)
Decimal
No. (C)
Decimal
No. (C)
Date(A)
Date(A)
Date(A) (C)
(C)
(C)
(D)
Integer(A)
Time(B)
Time(B)
Time(B) (C)
Integer
Left
Argument
Long Integer
Long
Integer
Decimal No.
Decimal
No. (C)
Date
Long
Integer
Long
Integer
(C)
Time
Text
Code
(C)
Long
Integer
(C)
Long
Integer
(C)
(C)
(D)
Long
Integer(B)
(C)
(A) in the above table means that the operation is not defined for the date 0D.
(B) in the above table means that the operation is not defined for the time 0T.
(C) in the above table means that overflow may occur.
(D) in the above table indicates that the operation is not defined if Decimal No.
has a fractional part.
AL Programmers Guide
33
The * Operator
.
Left
Argument
Integer
Long Integer
Decimal
No.
Decimal
No. (C)
Integer
Long Integer
Long Integer
(C)
(C)
Long
Integer
Long Integer
Long Integer
(C)
(C)
Decimal
No. (C)
Decimal
No.
Decimal
No. (C)
Decimal
No. (C)
Decimal
No. (C)
The / Operator
Integer
Long
Integer
Decimal
No.
Integer
Decimal
No.
Decimal
No.
Decimal
No.
Long Integer
Decimal
No.
Decimal
No.
Decimal
No.
Decimal
No.
Decimal
No.
Decimal
No.
Decimal
No.
Left
Argument
A run-time error will occur if the right operand is equal to zero (0).
34
AL Programmers Guide
Left
Argument
Integer
Long Integer
Decimal No.
Integer
Integer
Long Integer
Decimal No.
Long Integer
Long Integer
Long Integer
Decimal No.
Decimal No.
Decimal No.
Decimal No.
Decimal No.
A run-time error will occur if the right operand is equal to zero (0).
AL Programmers Guide
35
36
AL Programmers Guide
Part
2 AL Reference Guide
The heading to the left
describes the name of the
function
A description of the argument(s) used in the function.
For each argument the Flow
is described. The Flow can
be either in (i), out (o) or io
(in/out), describing whether
the argument is used as
input, output or both. Furthermore the valid data
types are defined
callBATCH
Use this function to load and run a batch job. For example, you can
use this function to call a batch job that adjusts inventory
callBATCH(BatchName [, Request])
To...
Enter...
FALSE
Note: If the batch job does not exist, the system displays a
message when it executes this function
If you display the request panel, please note that the user has to
press ESC after the batch job runs to exit the request panel and start
the next AL function.
These examples show how to call a batch job. The first example
shows the request panel. The second example skips the request
panel and starts the batch job immediately.
AL Reference Guide
37
Typographical Conventions
Typographical
Conventions
38
Convention
Applies to
Examples
Monospaced Font
AL code examples
Number:= 6;
Times Font
Normal text
This is a sentence
Helvetica Font
Table bodies
ALL CAPS
AL keywords when
used in normal text and
in AL code examples
ALReference Guide
AL Functions
grouped by
category
Some of the above groups are divided further into sub-groups. The
functions are described in alphabetical order from page 44.
String Functions
Maintenance
INSSTR
DELSTR
DELCHR
COPYSTR
SETSTRLEN
STRSUBSTNO
INCSTR
SELECTSTR
Information
STRLEN
MAXSTRLEN
STRPOS
Transformation
UPPERCASE
LOWERCASE
AL Reference Guide
39
CONVERTSTR
STRCHECKSUM
TODAY
WORKDATE
Transformation
NORMALDATE
CLOSINGDATE
CALCDATE
Evaluates a date-expression.
DATE2DMY
DATE2DWY
DMY2DATE
DWY2DATE
Number Functions
ABS
ROUND
POWER
Calculates xy
Database Functions
Maintenance
dbINSREC
Inserts a record.
dbDELREC
Deletes a record.
dbDELALL
dbMODIFYREC
Edits a record.
dbMODIFYALL
dbRECMARK
Marks a record.
Searching
40
ALReference Guide
dbGETREC
dbFINDREC
dbNEXTREC
dbSETCURREC
dbGETCURREC
dbRECCOUNT
Transactions
dbLOCKTABLE
dbCONSISTENT
dbCOMMIT
dbSETRANGE
dbSETFILTER
dbMINRANGE
dbMAXRANGE
dbCOPYFILTER
dbCOPYALLFILTERS
dbGETFILTER
dbGETALLFILTERS
dbMARKEDONLY
dbRESETTABLE
dbGLOBALFILTER
dbSELECTCOMPANY
Fields
dbFIELDNO
AL Reference Guide
41
dbFIELDNAME
dbFIELDACTIVE
dbCALLFIELDCODE
dbFIELDERROR
dbTESTFIELD
dbTRANSFERFIELDS
dbSUM
dbCALCFIELDS
dbINITREC
Dialogue Functions
OPENWINDOW
Opens a window.
CLOSEWINDOW
Closes a window.
UPDATEWINDOW
WINDOWINPUT
ERROR
MESSAGE
CONFIRM
STRMENU
WAITKEYPRESS
Accounting Functions
COMPANYNAME
USERID
Array Functions
42
COPYARRAY
ARRAYLEN
COMPRESSARRAY
ALReference Guide
Miscellaneous Functions
EVALUATE
FORMAT
CLEAR
CLEARALL
SERIALNO
SYSTEMVERSION
Call Functions
callWINDOW
callFUNCTION
callMENU
callREPORT
callBATCH
callIMPORT
callSYSTEM
AL Reference Guide
43
ABS
ABS
Calculates the absolute value of a Number, that is, ABS always returns a
positive numeric value or zero.
NewNumber := ABS(Number)
Number
NewNumber 0.
For Example...
This example shows how to remove the sign from a negative numeric
value.
x := -10.235; {x is assigned a negative value}
y := ABS(x); {y is assigned the value of x without sign}
MESSAGE('x = %1, y = %2', x, y);
44
ALReference Guide
ARRAYLEN
ARRAYLEN
Returns the total number of elements in an Array, or the number of elements in a specific Dimension.
Dimension
If this optional argument is not used, the function will return the total
number of elements in the Array. In order to get the number of elements
in a specific dimension use Dimension with a valid value.
The valid values for Dimension are determined by the number of dimensions of the input array, for example the valid values for a three- dimensional array would be 1, 2 and 3.
Length
The number of elements in the array, or the number of elements in a specific dimension.
For Example...
The following AL code sample shows how to use the optional arguments.
{Array1 is a one-dimensional integer array with size 2}
{Array2 is a two-dimensional integer array with size 2x2}
MESSAGE('Array1, Total number of elements %1', ARRAYLEN(Array1));
MESSAGE('Array2, Dimension no. 1: Size %1', ARRAYLEN(Array2,1));
MESSAGE('Array2, Dimension no. 2: Size %1', ARRAYLEN(Array2,2));
MESSAGE('Array2, Total number of elements: %1', ARRAYLEN(Array2));
AL Reference Guide
45
CALCDATE
CALCDATE
The date expression can be of any length. The system interprets the string
from left to right, one sub-expression at the time. The following rules
describes the valid syntax for a date expression:
DateExpression = <SubExpression>*
<SubExpression> = [<Sign>] <Term>
<Term> = <Number><Unit> | <Unit><Number>| <Prefix><Unit>
<Sign> = + | <Number> = Positive integer
<Unit> = D | WD | W | M | Q | Y
(D=day, WD=Weekday, W=Week, M=Month, Q=Quarter, Y=Year)
<Prefix> = C(C=Current)
Date
The resulting date computed from the reference date and the date expression.
For Example...
The first example shows how to use the production rules above.
Prefix Unit Sign Number Unit Sign Number Unit
C
Q
+
1
M
10
D
46
ALReference Guide
CALCDATE
Expr2 := '-WD2';
{The previous Weekday no. 2, (last Tuesday)}
Expr3 := 'CM+30D';
{Current month + 30 days}
RefDate := 052196D;
Date1 := CALCDATE(Expr1, RefDate);
Date2 := CALCDATE(Expr2, RefDate);
Date3 := CALCDATE(Expr3, RefDate);
MESSAGE('The reference date is: %1 \' +
'The expression: %2 returns %3\' +
'The expression: %4 returns %5\' +
'The expression: %6 returns %7', RefDate, Expr1, Date1,
Expr2, Date2, Expr3, Date3);
AL Reference Guide
47
callBATCH
callBATCH
callBATCH(BatchName [, Request])
BatchName
The name of the desired batch object. The string must contain an exact
match of the name of the report object (case sensitive). To choose from
the list of batch objects, press F5 while in the AL editor. The system displays the Symbols survey. Highlight the callBATCH keyword and press
F6.
Note: If the batch object BatchName does not exist, a run
time error will occur.
Request
Determines whether the request window will be shown before the batch
object is executed.
To...
Enter...
For Example...
FALSE
These examples show how to call a batch job. The first example shows
the request window. The second example skips the request window and
starts the batch job immediately.
With a request panel
48
ALReference Guide
callFUNCTION
callFUNCTION
Record
Ok
If the optional return value is not used, the system will terminate the execution of the AL code calling the function if an error occurs during the
execution of the function object.
If the return value is used, the system will continue the execution of the
calling AL code, although the function object detected an error, in other
words the programmer is supposed to take care of the error handling. The
possible values are described in the table below.
OK
Means that...
TRUE
No errors occured.
FALSE
If the return value is used, the system will automatically clear the variables used in the function object, before the function object is executed.
If you use the return value in an IF statement, inside a write transaction, a
run time error will occur, unless your data updates are committed, before
you call callFUNCTION.
AL Reference Guide
49
callFUNCTION
General Comments...
AL code module
...
callFUNCTION(1002);
callFUNCTION(1003);
dbCOMMIT();
callFUNCTION(1005);
...
For Example...
The Al code in this example uses a function numbered 1002, which calculates a unit price.
Function 1002 (Invoice Line)
Unit Price := Amount / Quantity;
50
ALReference Guide
callFUNCTION
If we assume that the value of count initially is zero, this loop will cause
count to be increased to 100. If the return value is used in a IF construct,
like:
FOR i := 1 TO 100 DO
IF callFUNCTION(1003) THEN
MESSAGE(Function 1003 called %1 times,i);
then Count will be cleared each time function 1003 is activated. This will
cause Count to take the values: 0->1, 0->1, 0->1 ...
Example 4:
The call to the function 1004, does not change current key and filters. The
changes made in the function are local to the function.
Example 5:
The above call to function 1005 results in a run time error, as the write
transaction has not been committed. In order to call the function, the data
update must be explicitly committed:
...
dbINSREC(Customer);
dbCOMMIT();
IF callFUNCTION(1005) THEN
...
AL Reference Guide
51
callIMPORT
callIMPORT
callIMPORT(ImportName [, Request])
ImportName
The name of the desired import object. The string must contain an exact
match of the name of the report object (case sensitive). To choose from
the list of import objects, press F5 while in the AL editor. The system displays the Symbols survey. Highlight the callIMPORT keyword and press
F6.
Note: If the function is called with the name of a nonexisting import object, a run time error will occur.
Request
Determines whether the request window will be shown before the importtransaction is started.
To...
Enter...
For Example...
These examples show how to start an import transaction. The first example shows the request window. The second example skips the request window and starts the import transaction immediately.
With a request window
52
ALReference Guide
callMENU
callMENU
callMENU(MenuNo)
MenuNo
A number which identifies the menu object. To choose from the list of
menu objects, press F5 while in the AL editor. The system displays the
Symbols survey. Highlight the callMENU keyword and press F6.
Note: If MenuNo does not exist, a run time error will occur.
AL Reference Guide
53
callREPORT
callREPORT
callREPORT(ReportName [, Request])
ReportName
The name of the desired report object. The string must contain an exact
match of the name of the report object (case sensitive). To choose from
the list of report objects, press F5 while in the AL editor. The system displays the Symbols survey. Highlight the callREPORT keyword and press
F6
Note: If the report object identified by ReportName does not
exist, a run time error will occur.
Request
Determines whether the request window will be shown before the report
is started.
To...
Enter...
For Example...
FALSE
These example show how to execute a report. The first example displays
the request window. The second example skips the request window and
starts the report immediately. Please note that the name string is case sensitive, and must contain an exact match of the report object name.
With a request window
54
ALReference Guide
callSYSTEM
callSYSTEM
One or more optional argument(s) to be sent to the operating system command. Each parameter is treated as a substring, that is all parameters are
concatenated into one string which forms the argument to the operating
system command. This means that if more than one parameter is to be
passed to the operating system command, the parameters can be supplied
either as individual arguments, or as a string in which the arguments are
separated by spaces. The total length of the string(s) cannot exceed 128
characters.
ReturnCode
This is a return code from the external program or the operating system
command.
External programs can return different codes in order to reflect whether
one or more error(s) occured during the execution of the external program. The possible value of the ReturnCode will depend on the external
program.
When using the callSYSTEM command to activate operating system
command, the following simple rules apply. DOS commands (DIR,
COPY, ...), OS/2 commands (DIR, COPY, ...) and UNIX commands (ls,
cd, ...) will always return the value 0 (zero).
General Comments...
For Example...
AL Reference Guide
55
callSYSTEM
56
ALReference Guide
callWINDOW
callWINDOW
Loads and executes a window object identified by a WindowNo. All window objects are associated with a specific table and when a window
object is executed, one or more records (depending on the type of the window) from this table will be displayed .
Record
The callWINDOW function will as default show the record which was
displayed the last time the window was open. For each window object the
system stores information about the most recently shown record and the
attached key and filters.
This optional parameter is used to select a specific record to be shown in
the window. The record must be of the same type as the table associated
to the window. When showing the record, the window will use the key
and filters attached to the record.
Record.Field
Ok
For the window objects: List, Tabular, Chart and Card this return code
reflects whether the ENTER or ESC was used to quit the window.
AL Reference Guide
57
callWINDOW
.
Ok
Means that...
TRUE
ENTER was used to quit the window. This also selects the
record pointed out by the cursor.
FALSE
The only way to quit the other window objects (Worksheet, Matrix, Statistics and Periodic) is by using ESC, that is, they will always return the
value FALSE.
For Example...
{A window object}
{Activate the window object
with default values for Record
and Record.Field}
Example 2:
The window will show customers with no. greater than or equal to
2000, sorted by Name. The current key and filters on Customer are never
changed when using callWINDOW, as the user operates on a copy of the
filters and the current key.
Example 3:
The following construct can be used to detect whether the user pressed
ESC or ENTER in the window.
IF callWINDOW(1002,Customer) THEN
MESSAGE(ENTER was pressed - Customer has changed)
ELSE
MESSAGE(ESC was pressed - Customer is unchanged);
will show the same list of customers, use the same sorting sequence, and
show the same current customer as last time the window was open. All
filters and the current key are fetched from a setup-file.
58
ALReference Guide
CLEAR
CLEAR
CLEAR(Variable)
Variable
For a composite data type, such as a record or an array all elements will
be cleared.
For Example...
AL Reference Guide
59
CLEARALL
CLEARALL
Clears all internal variables, keys and filters in the object (function,
report, ...) containing the AL code.
CLEARALL()
General Comments...
When a function is called repeatedly within the same transaction, all values for variables and filters are retained in memory between the calls
(This is for example used to enumerate entry numbers when booking) .
When you do not need the values retained in memory, you can use the
CLEARALL() function in order to ensure that all variable are cleared.
Refer to the description of the CLEAR function for a description of initial
values in cleared variables.
For Example...
60
ALReference Guide
CLOSEWINDOW
CLOSEWINDOW
Use this function to close a dialog window which has been opened by
OPENWINDOW.
CLOSEWINDOW()
General Comments...
For Example...
When you press ESC or ENTER the window will be removed by the
CLOSEWINDOW function.
AL Reference Guide
61
CLOSINGDATE
CLOSINGDATE
ClosingDate := CLOSINGDATE(Date)
Date
The figure below illustrates how the system sorts the closing dates
between the normal dates for an arbitrary month..
April 1994
040194D 040194C
040294D
...
ClosingDate
For Example...
If Date is a...
Normal date
Closing date
Closing date
Closing date
Date1 := 040496D;
CloDate := CLOSINGDATE(Date1);
MESSAGE('The closing date for %1 is %2', Date1, CloDate);
Date1 := CLOSINGDATE(040496D);
Clodate := CLOSINGDATE(Date1);
MESSAGE('The closing date for %1 is %2', Date1, CloDate);
62
ALReference Guide
COMPANYNAME
COMPANYNAME
Name := COMPANYNAME()
Name
The company name, or the empty string if a company has not been
selected.
General Comments...
For Example...
When you enter your application, you will be prompted to select a company. The COMPANYNAME function reflects this selection
This example shows how to use the COMPANYNAME function to
retrieve the name of the current company.
Name := COMPANYNAME();
{Get the name of the current company}
MESSAGE('The company name is: %1', Name);
{Print the companyname}
AL Reference Guide
63
COMPRESSARRAY
COMPRESSARRAY(StringArray)
StringArray
General Comments...
For Example...
COMPRESSARRAY
Input
Output
Joe Blow
Joe Blow
Chicago
Chicago
The figure illustrates that all non-empty entries have been moved to the
top of the array.
The following AL code sample illustrates how to perform the above compression of an array of strings.
Name[1] := ; {Empty String}
Name[2] := 'Joe Blow';
Name[3] := '1241 East Druid Avenue';
Name[4] := ' '; {A string containing blanks}
Name[5] := 'Chicago';
Name[6] := ;
MESSAGE('The address before compression, is written as:\' +
'%1\' +
'%2\' +
64
ALReference Guide
COMPRESSARRAY
'%3\' +
'%4\' +
%5\ +
%6, Name[1], Name[2], Name[3], Name[4], Name[5], Name[6]);
COMPRESSARRAY(Name); {The empty lines (strings) are removed}
MESSAGE('The address after compression, is written as:\' +
'%1\' +
'%2\' +
'%3\' +
'%4\' +
%5\ +
%6, Name[1], Name[2], Name[3], Name[4], Name[5], Name[6]);
The empty and blank strings which caused blank lines, has been moved to
the end of the array, and the other elements has been moved up.
Note that an empty string is not printed when it occurs as the last (or the
first) line in a message box.
AL Reference Guide
65
CONFIRM
CONFIRM
Creates a dialog box which prompts for a Yes/No answer. The dialog box
is centered at the middle of the screen.
Ok := CONFIRM(String [, Default])
String
This string is displayed in the dialog box. Use the '\'character to indicate a
new line. The height of the dialog box corresponds to the number of lines,
and the width of the dialog box corresponds to the length of the longest
substring. A Yes/No prompt field must be inserted in the string by using
'#'-characters. Normally 3 '#'-characters are used, as this length matches
both 'Yes' and 'No'.
Note: A run time error will occur if String does not contain a
'#'-field.
Default
Describes what the computer should use as default in the Yes/No field. If
the variable Default is not specified, the value 'No' will be used.
Ok
For Example...
Ok will be...
If you entered...
TRUE
Yes
FALSE
No
66
ALReference Guide
CONVERTSTR
CONVERTSTR
String
A string describing the new characters to be inserted. The CONVERTSTR function is case sensitive. The length of this string must correspond
to the length of FromCharacters. If the length of the FromCharacters and
ToCharacters strings both are 0, (empty strings) no changes are made.
Note: If the lengths of the FromCharacters and ToCharacters
strings are not equal, a run time error will occur.
NewString
For Example...
AL Reference Guide
67
COPYARRAY
COPYARRAY
The array to be copied from. Copying can only take place from onedimensional arrays. Two- and three-dimensional arrays can be copied by
repeated use of the COPYARRAY function.
Position
The number of array elements to be copied. Valid values for Length are:
1 Length MAXLEN(Array) - Position + 1
If Length is not specified, all array elements from Position to the last element will be copied.
NewArray
For Example...
The following two examples show how to use the COPYARRAY function. The first example shows how to copy three elements from a one
dimensional array. The second example shows how to copy two and three
dimensional arrays.
How to copy from a one-dimensional array.
68
ALReference Guide
COPYARRAY
... while the second message box will show the following:
The contents of the copied array is:
lives
in
Chicago
How to copy from a two or three dimensional array.
(12)
(22)
AL Reference Guide
69
COPYSTR
COPYSTR
For Example...
70
ALReference Guide
DATE2DMY
DATE2DMY
Specifies what the function should return. The valid values are 1, 2 and 3:
What
Number
Corresponds to...
Day (1-31).
Month (1-12).
For Example...
date}
month no.}
year}
to:\' +
Month, Year);
AL Reference Guide
71
DATE2DWY
DATE2DWY
Returns the day of the week, week number and year based on the input
Date.
Specifies what the function should return. The valid values are 1, 2 and 3:
What
Number
Corresponds to...
General Comments...
For Example...
The example illustrates that the system regards the date 01/01/94 as day
no. 6 (Saturday) in week no. 52 in the year 1993!
72
ALReference Guide
dbCALCFIELDS
dbCALCFIELDS
General Comments...
The first line sets up a delimitation for the field Date Filter in the record
Customer. This field is a Calculation Filter field which is used in the
computation of some of the Calculated fields in Customer. The computation of the Calculated fields is then carried out using dbCALCFIELDS in
the second line.
AL Reference Guide
73
dbCALLFIELDCODE
dbCALLFIELDCODE
dbCALLFIELDCODE(Record.Field [, Value])
Record.Field
Flow: i; Datatypes:-
The optional parameter Value is used to assign a value to the field before
the entry processing takes place. The type of Value must match the type of
Record.Field.
The following AL code sample illustrates the use of the dbCALLFIELDCODE function.
When an account no. is entered in a ledger, some entry processing code
must be activated in order to, for example, transfer the name of the
account from the chart of accounts.
If an account no. is entered in a batch, the code which transfers the name
of the account will not automatically be executed. The following causes
the appropriate code to be executed:
dbCALLFIELDCODE(GeneralLedgerLine.AccountNo, 100);
74
ALReference Guide
dbCOMMIT
dbCOMMIT
dbCOMMIT()
General Comments...
BeginWriteTransaction
AL Module
AL Statements
dbCommit(...)
AL Statements
}
}
1. Trans.
2. Trans.
EndWriteTransaction
AL Reference Guide
75
dbCONSISTENT
dbCONSISTENT
dbCONSISTENT(Record, Consistent)
Record
General Comments...
To...
Enter...
TRUE
FALSE
For Example...
76
ALReference Guide
dbCONSISTENT
or more amounts which sum up to +$100, the Balance variable will equal
zero, and the table will be marked as consistent. This means that if an
attempt is made to put in an amount and end the write transaction (commit the change) without withdrawing a corresponding amount within the
same transaction, an error will occur, and the write transaction will be
aborted.
AL Reference Guide
77
dbCOPYALLFILTERS
dbCOPYALLFILTERS
dbCOPYALLFILTERS(FromRecord, ToRecord)
FromRecord
General Comments...
For Example...
This function is used to apply filters defined for another record, as basis
for a counting, a search, calculation or similar operations.
This AL code sample shows how to use the dbCOPYALLFILTERS function.
dbSETFILTER(CustomerRec1.No., <1000);
{Set various}
dbSETRANGE(CustomerRec1.Group, 1);
{filters on fields}
dbMARKEDONLY(CustomerRec1, TRUE);
{in a Customer record}
dbCOPYALLFILTERS(CustomerRec1, CustomerRec2);{Apply the same}
.
{filters to another}
.
{record}
Count := dbRECCOUNT(CustomerRec2);
78
ALReference Guide
dbCOPYFILTER
dbCOPYFILTER
Copies the filter set for one field and applies it to another field.
dbCOPYFILTER(FromRecord.FromField, ToRecord.ToField)
FromRecord.FromField
General Comments...
For Example...
The FromFields and Tofields must be of the same data type, but does not
need to belong to the same table.
This AL code sample illustrates how to use the dbCOPYFILTER function
dbSETFILTER(Customer.No., <1000);
dbCOPYFILTER(Customer.No., Vendor.No.);
.
.
Count := dbRECCOUNT(Vendor);
AL Reference Guide
79
dbDELALL
dbDELALL
dbDELALL(Record)
Record
Identifies the table in which the deletion will take place. Only records
within the range specified by the filters set for Record will be deleted.
For Example...
But the dbDELALL function is much faster, as only one access to the
server is needed, while the first method requires multiple accesses to be
performed.
80
ALReference Guide
dbDELREC
dbDELREC
The return value. If the record does not exist, the function will terminate
with a run time error, if this optional return value is not used.
General Comments...
If Ok is...
It means that...
True
False
This function deletes a record from a table. The current key and any filters
bound to the record have no effect on this operation. The record to be
deleted is identified only by the values in its primary key.
In a multi-user environment, another application can delete the record
from the table in the interval between your reading of the record, and your
attempt to delete it. The NAVISION DBMS automatically detects if such
a situation occurs, which causes dbDELREC to fail with a run time error .
To prevent this situation, you can explicitly lock the table by using
dbLOCKTABLE. This causes the table to be locked the entire time during
your operation on the table, preventing other users to acces the table.
Refer to the NAVISION DBMS for further information about table
locking.
For Example...
Customer.No. := 100:
dbDELREC(Customer);
Using the return value:
Customer.No. := 100;
IF dbDELREC(Customer) THEN
MESSAGE(The customer has been deleted)
ELSE
ERROR(The customer could not be found);
AL Reference Guide
81
dbFIELDACTIVE
dbFIELDACTIVE
Checks whether a field is active or not, that is, whether the field can be
used or not.
Ok := dbFIELDACTIVE(Record.Field)
Record.Field
This return value reflects whether the field was marked as active or inactive.
If Ok is...
It means that...
TRUE
FALSE
General Comments...
Each field in a record can be set as active or inactive in the table description for the table in question. An inactive field cannot contain data.
For Example...
causes a run time error, if the field Address 2 has not been marked as
active. This run time error could be avoided by performing the following
test:
IF dbFIELDACTIVE(Customer.Address 2) THEN
Customer.Address := Atlanta
ELSE
MESSAGE(The field is not marked as active);
82
ALReference Guide
dbFIELDERROR
dbFIELDERROR
Creates an error message for a field, and stops the execution of the code.
dbFIELDERROR(Record.Field [, Text])
Record.Field
General comments...
Like with any other run time error, this function will cause any transaction
to be aborted automatically.
For Example...
The following three AL code samples illustrate how to use the dbFIELDERROR function.
Without using the Text parameter:
Customer.No. := ;
dbFIELDERROR(Customer.No.);
AL Reference Guide
83
dbFIELDNAME
dbFIELDNAME
String := dbFIELDNAME(Record.Field)
Record.Field
A field in a record.
String
For Example...
84
ALReference Guide
dbFIELDNO
dbFIELDNO
FieldNo := dbFIELDNO(Record.Field)
Record.Field
For Example...
The following AL code sample shows how to use the dbFIELDNO function. The statement:
Number := dbFIELDNO(Customer.No.);
AL Reference Guide
85
dbFINDREC
dbFINDREC
Finds a record in a table based on the values in key fields in the records.
On input Rec points out the record to be found. On output there are two
possibilities:
Was the record found? Then...
Which
Yes
No
'='
'>'
'<'
'+'
'-'
Ok
If this optional return value is not used, a run time error occurs if the
record could not be found. When the return value is used, it is assumed
that the programmer takes care of the error handling. The return value can
take the following values:
General Comments...
86
Ok
Means that...
TRUE
FALSE
dbFINDREC retrieves the first record that meets the conditions set by
SearchStr and the s filters associated with Rec. The search path corre-
ALReference Guide
dbFINDREC
sponds to the sorting defined by the current key. If the current key is not
the primary key, there is a chance that several values have the same values
in the current key fields. In this case the sorting order defined by the primary key is used as search path.
For Example...
First the system prompts you to enter a customer number to search for:
Search for a customer number:
____________________________
If you enter a customer number that does not exist, for example
NOBODY, the system will display the following message:
Sorry, the record could not be found...
If you enter a customer number that exists in the Customer table, for
example AAA 1050, the system will display the following message:
The record was found!
Customer number AAA 1050 corresponds to:
AAA Furniture Manufacturing
AL Reference Guide
87
dbGETALLFILTERS
dbGETALLFILTERS
String := dbGETALLFILTERS(Record)
Record
dbFINDREC
For Example...
The following Al code sample illustrates the use of the dbGETALLFILTERS function.
dbSETRANGE("Cust. Ledger Entry".Amount, -100, 100);
dbSETRANGE("Cust. Ledger Entry".Date, 010194D, 123194D);
Str := dbGETALLFILTERS("Cust. Ledger Entry");
MESSAGE(The filters are:\ +
%1, Str);
88
ALReference Guide
dbGETCURREC
dbGETCURREC
Enter...
Ok
If this optional return value is not used, a run time error occurs if a record
marked as current could not be found. When the return value is used, it is
assumed that the programmer takes care of the error handling. The return
value can take the following values.
General Comments...
If Ok is...
It means that...
TRUE
FALSE
AL Reference Guide
89
dbGETCURREC
Object Stack
Automatically
marked as current
Vendor2
Customer1
Vendor1
Search direction
Function
Window
Vendor1
Vendor2
Function
Customer1
Customer2
x Customer3
Allocation
order
Report
Customer1
Window
(Bottom of Object Stack)
For Example...
This will cause the system to search the Object Stack from top to bottom.
Figure 3 illustrates an Object Stack holding information about four arbitrary objects, named A, B, C and D.
The search for a Customer record marked as current, will return
Customer1 from object A, while the search for a Vendor record marked as
current, will return Vendor2 from object B.
90
ALReference Guide
dbGETCURREC
Figure 3. An
object Stack holding record values
for four arbitrary
objects.
Object Stack
(x) Customer1
Vendor2
Area for object B
Area for object C
Area for object D
(x) Customer2
(x) Vendor2
Search order
Customer3
(x) Vendor1
(x) Customer1
Another example:
Assume that Window no. 1 (W1) is related to Table no. 1 (T1), and that
Window no. 2 (W2) is related to Table no. 2 (T2). Records in T1 and T2
are called R1 and R2.
Furthermore we assume that W2 is called from W1; thus the active window will be W2. Text is being typed into W2 which causes the connected
Entry processing code to be activated.
Entry processing code for T2:
dbGETCURREC(R2,TRUE)
dbGETCURREC(R2,FALSE)
dbGETCURREC(R1,FALSE)
dbGETCURREC(R1,TRUE)
OK:=dbGETCURREC(R1,TRUE)
AL Reference Guide
91
dbGETFILTER
dbGETFILTER
String := dbGETFILTER(Record.Field)
Record.Field
General Comments...
For Example...
92
ALReference Guide
dbGETREC
dbGETREC
- Flow: i; Domain: -
Denotes the value(s) in the primary key fields . The type of Value(s) must
match the type of the corresponding primary key field(s). Unspecified
fields are assigned the value 0 or an empty string.
Ok
If this optional return value is not used, a run time error occurs if the
record could not be found. When the return value is used, it is assumed
that the programmer takes care of the errror handling. The return value
can take the following values
General Comments...
For Example...
If Ok is...
It means that...
TRUE
FALSE
The function always uses the primary key for the table and ignores filters,
if any. After the function call, the current key and filters are not changed.
The following AL code sample shows how to use the dbGETREC function. The following statement:
dbGETREC(Customer, '1120');
will cause a run time error if the customer with the number 1120 cannot
be found. In order to avoid this, use the following construct:
IF dbGETREC(Customer, 1120) THEN
MESSAGE(The record was found)
ELSE
MESSAGE(Sorry, the record could not be found...);
AL Reference Guide
93
dbGLOBALFILTER
dbGLOBALFILTER
dbGLOBALFILTER(Record)
Record
A record from the table to which filters already are assigned. Any filters
assigned to the fields in the record are made global.
General Comments...
For Example...
Now the user will not be able to see G/L entries outside the specified
range in the chart of accounts, reports, batch jobs and so on.
94
ALReference Guide
dbINITREC
dbINITREC
Initializes a record.
dbINITREC(Record)
Record
The record to be initialized. The dbINITREC function assigns default values to each field in the record. The values correspond to those defined
when the table was created . Fields for which no values were defined, are
assigned the following default values:
Data type...
Default value...
Yes/No
No
Option
Integer
Long Integer
Decimal No.
0.0
Date
0D (Undefined date)
Time
0T (Undefined time)
Code
Text
General Comments...
For Example...
After this operation, you are free to change the values in any or all of the
fields before calling dbINSREC to enter the record in the table. Be sure
that the field(s) comprising the primary key contain values that make the
total primary key unique. If the primary key is not unique (record already
exists), the DBMS will reject the record.
These AL code samples shows how to use the dbINITREC function.
Assume that the primary key includes the No. field. Consider the following situations:
Situation 1:
dbINITREC(Customer);
Customer.No. := 1120;
dbINSREC(Customer);
Situation 2:
Customer.No. := 1120;
dbINITREC(Customer);
dbINSREC(Customer);
As dbINITREC does not initialize the primary key fields, the sequence of
the statements in situation 1 and 2 is not important. Situation 1 causes the
same result as situation 2.
AL Reference Guide
95
dbINSREC
dbINSREC
If this optional return value is not used, a run time error occurs if the
record could not be inserted. When the return value is used, it is assumed
that the programmer takes care of the errror handling. The return value
can take the following values
If Ok is...
It means that...
TRUE
FALSE
General Comments...
For Example...
The following AL code samples show how to use the dbINSREC function.
Without using the return value:
dbINITREC(Customer);
Customer.No. := 1120;
dbINSREC(Customer);
If for example the customer number 1120 already exists, a run time error
will occur. In order to avoid this, use the following construct:
Using the return value:
dbINITREC(Customer);
Customer.No. := 1120;
IF dbINSREC(Customer) THEN
MESSAGE(Customer no.: %1 inserted, Customer.No.)
ELSE
MESSAGE(Sorry, an error occured...);
96
ALReference Guide
dbLOCKTABLE
dbLOCKTABLE
The Wait parameter specifies what action to take in case the table already
is locked:
To...
Enter...
VersionCheck
Enter...
TRUE
General comments
Because all write operations automatically lock the table in use, the
dbLOCKTABLE would seem unnecessary. Imagine however a transaction in which an application wants to inspect data and then only possibly
change it, with a guarantee that the data being changed has not been modified by other applications since the read. The solution is to explicitly lock
the table before the read operation, thereby ensuring that no other application makes changes between the read and the possible write.
Refer to The NAVISION DBMS for an explantion of table locking.
For Example...
AL Reference Guide
97
dbLOCKTABLE
locks are active until the system exits the AL code module (5).
.
Table Locking
.
.
Table B locked
Table A locked
Figure 4. The
scope of write
locks
(1)
(2)
dbINSERTREC(TableA, ...);
(3)
dbINSERTREC(TableB, ...);
(4)
.
.
.
.
.
(5)
.
.
When the VersionCheck parameter is TRUE, dbMODIFYREC will compare the time-stamp on the record you modify within a transaction, with
the time-stamp made the last time you read the record before the transaction started. If these time-stamps are different, the record has been
changed in the period from you read and until you locked the table, and a
run time error will occur.
98
ALReference Guide
dbMARKEDONLY
dbMARKEDONLY
Causes a special filter to be activated: your view of the table will only
include records marked by dbRECMARK.
OK := dbMARKEDONLY(Record [, MarkedOnly])
Record
A record from the table for which you want to activate the special
markfilter.
MarkedOnly
Ok
To...
Enter...
TRUE
FALSE
For Example...
It means that...
TRUE
FALSE
{Mark a record}
No1 := dbRECCOUNT(Customer);
dbMARKEDONLY(Customer, TRUE);
No2 := dbRECCOUNT(Customer);
MESSAGE(Number of records before dbMARKEDONLY: %1\ +
Number of records after dbMARKEDONLY: %2, No1, No2);
AL Reference Guide
99
dbMAXRANGE
dbMAXRANGE
Value := dbMAXRANGE(Record.Field)
Record.Field
The input field. The current filter on Record.Field must be a single range,
otherwise a run time error occurs.
Value
- Flow: o; Datatypes: -
A return value containing the maximum value of the range set for
Record.Field. The type of value must match the type of Record.Field.
For Example...
dbSETFILTER(Customer."No.",'100..200');
Val := dbMAXRANGE(Customer."No.");
MESSAGE(The maximum value is: %1, Val);
dbSETFILTER(Customer."No.",'100');
Val := dbMAXRANGE(Customer."No.");
MESSAGE(The maximum value is: %1, Val);
dbSETFILTER(Customer."No.",'200|300');
Val := dbMAXRANGE(Customer."No.");
100
ALReference Guide
dbMINRANGE
dbMINRANGE
Value := dbMINRANGE(Record.Field)
Record.Field
The input field. The current filter on Record.Field must be a single range,
otherwise a run time error occurs.
Value
A return value containing the minimum value of the range set for
Record.Field. The type of Value must match the type of Record.Field.
For Example...
dbSETFILTER(Customer."No.",'100..200');
Val := dbMINRANGE(Customer."No.");
MESSAGE(The minimum value is: %1, Val);
dbSETFILTER(Customer."No.",'100');
Val :=dbMINRANGE(Customer."No.");
MESSAGE(The minimum value is: %1, Val);
dbSETFILTER(Customer."No.",'200|300');
Val := dbMINRANGE(Customer."No.");
AL Reference Guide
101
dbMODIFYALL
dbMODIFYALL
dbMODIFYALL(Record.Field, Value)
Record.Field
Flow: i; Datatypes: -
The value to be assigned to the field Record.Field in all records. The type
of Value must match the type of Record.Field.
General Comments...
If no filter is set, the field is modified in all records in the table. Otherwise dbMODIFYALL will only change the fields in the records within the
range(s) specified by the filter.
For Example...
But the use of dbMODIFYALL is much faster, as only one server access
is needed. The second method requires several server accesses.
102
ALReference Guide
dbMODIFYREC
dbMODIFYREC
If this optional return value is not used, a run-time error occurs if the
record does not exist. Using the value, it is possible for the programmer to
take care of the error handling. The possible values are: .
General Comments...
If Ok is...
It means that...
TRUE
FALSE
The record to be replaced is identified by the primary key fields. The current key and filters on the record does not affect this operation.
In multi user environments, another application can modify the record in
the table in the interval between your reading the record and your attempt
to modify it. The NAVISION DBMS automatically detects this, which
causes the dbMODIFYREC function to terminate with a run time error.
For Example...
The following AL code sample illustrates how to use the dbMODIFYREC function.
Customer."No." := AAA 1050;
dbFINDREC(Customer, =);
{Find customer}
MESSAGE(The customer no. %1 corresponds to:\ +
%2, Customer."No.", Customer.Name);{Display name}
WAITKEYPRESS;
Customer.Name := Joe Blow;
dbMODIFYREC(Customer);
{Modify customer name}
MESSAGE(Now customer no. %1 corresponds to:\ +
%2, Customer."No.", Customer.Name);{Display modified
name}
When a specific customer has been located, the message box shows:
The customer no. AAA 1050 corresponds to:
AAA Furniture Manufacturing
After the information has been modified, the second message box shows:
Now customer no. AAA 1050 corresponds to:
Joe Blow
AL Reference Guide
103
dbNEXTREC
dbNEXTREC
The record from which the search shall begin. Return the retrieved record.
Steps
Effect...
>0
<0
=0
No effect
The function returns the number of records traversed which meet the criteria of any filters and the current key. This value can be closer to zero
than Steps, depending upon the number of records in the table. If the
table is empty, zero is returned and Record remains unchanged
General Comments..
For Example...
dbNEXTREC locates a record positioned a given number of steps forward or backward from Record. Movement through the table is governed
by the filters and the current key associated with the records. The fields in
Record which will be compared with the current key fields, must contain
appropriate values before the function is called.
The following AL code sample illustrates how to use the dbNEXTREC
function.
Count := 0;
IF dbFINDREC(Customer, -) THEN
REPEAT
Count := Count + 1;
UNTIL dbNEXTREC(Customer) = 0;
The above code uses a REPEAT UNTIL loop to count the number of
entries in the Customer table. The dbFINDREC function is used to find
the first entry in the table. Each time dbNEXTREC is called, it steps one
record forward. When dbNEXTREC = 0 there are no more entries in the
table and the system exits the loop.
104
ALReference Guide
dbRECCOUNT
dbRECCOUNT
Number := dbRECCOUNT(Record)
Record
General Comments...
The dbRECCOUNT function returns the number of records that meet the
conditions of any filters associated to the records. If no filters are set, the
function returns the total number of records in the table.
The number of filters applied to the records affects the speed of the
dbRECCOUNT function. The operation is fastest when no filters are
applied.
For Example...
assigns the number of records in the Customer table to the Number variable. This statement equals:
Count := 0;
IF dbFINDREC(Customer, -) THEN
REPEAT
Count := Count + 1;
UNTIL dbNEXTREC(Customer) = 0;
However, the first example is much faster, as only one command to the
DBMS is needed. The second example requires that several command
are send to the DBMS.
AL Reference Guide
105
dbRECMARK
dbRECMARK
Marks a record.
Ok := dbRECMARK(Record [, Mark])
Record
Ok
Enter...
TRUE
FALSE
It means that...
TRUE
FALSE
For Example...
{Mark a record}
dbFINDREC(Customer, -);
{Find first record}
REPEAT
{Iterate through records}
Marked := dbRECMARK(Customer);
{Test if marked?}
MESSAGE(Customer.No.:%1, Marked?: %2, Customer."No.", Marked);
UNTIL dbNEXTREC(Customer) = 0;
106
ALReference Guide
dbRECMARK
The next example shows how to used the dbRECMARK together with
dbMARKEDONLY. Assume that initially none of the records are marked.
dbSELECTKEY(Customer."No.");
Customer."No." := NEW 3500;
dbFINDREC(Customer, =);
dbRECMARK(Customer, TRUE);
{Mark a record}
No1 := dbRECCOUNT(Customer);
dbMARKEDONLY(Customer, TRUE);
No2 := dbRECCOUNT(Customer);
MESSAGE(Number of records before dbMARKEDONLY: %1\ +
Number of records after dbMARKEDONLY: %2, No1, No2);
AL Reference Guide
107
dbRESETTABLE
dbRESETTABLE
dbRESETTABLE(Record [, GlobalFilters])
Record
General Comments...
For Example...
To...
Enter...
TRUE
The example illustrates that all filters have been removed by the call of
dbRESETTABLE.
108
ALReference Guide
dbSELECTCOMPANY
dbSELECTCOMPANY
The name of the company to be accessed. If CompanyName is not specified, the initial company is used.
Ok
If this optional return value is not used, a run-time error occurs if the company does not exist. Using the value, it is possible for the programmer to
take care of the error handling. The possible values are:
General Comments...
If Ok is...
It means that...
TRUE
FALSE
This function respects the users authorization. Thus, a user cannot access
data in CompanyName, unless the user already have the necessary authorization assigned by a super user.
The dbSELECTCOMPANY function is not affected by dbRESETTABLE. The only way to deselect a company, is by a new call to dbSELECTCOMPANY.
Global filters always belong to a specific company. If you use dbSELECTCOMPANY(Record, 'NewCompany') to select the company named
'NewCompany', any filters assigned to Record will be transferred to
Record in the new company; but if any of the filters have status as a global filter, this status will be removed.
When you return to the initial company, the global filters are automatically reestablished for Record. If the filters for Record have been
removed, the global filters can be restablished by calling dbRESETTABLE (Record,FALSE).
For Example...
The following AL code sample illustrates how to use the dbSELECTCOMPANY function.
dbSELECTCOMPANY(G/L Account,'New Company');
dbGETREC(G/L Account,'1000');
dbCALCFIELDS(G/L Account.Balance); {Calculates the balance for
account no. 1000 in the Company named 'New Company'}
dbSELECTCOMPANY(G/L Entry,'New Company');
dbSELECTKEY(G/L Entry.No.,FinanceEntry.Date);
dbSETRANGE(G/L Entry.No.,'1000');
AL Reference Guide
109
dbSELECTCOMPANY
dbSETRANGE(G/L Entry.Date,010194D,013194D);
dbSUM(G/L Entry.NettAmount);
{Sums NettAmount from all G/L
entries on account no. 1000
within the specified range,
for the company 'New Company'}
dbRESETTABLE(G/L Entry);
dbFINDREC(G/L Entry,'+');
{Finds the largest No. in
table G/L Entry in the Company
'New Company'}
dbDELREC(G/L Entry);
{Deletes this entry in the
company 'New Company'}
110
ALReference Guide
dbSELECTKEY
dbSELECTKEY
If this optional return value is not used, a run-time error occurs if the key
does not exist. Using the value, it is possible for the programmer to take
care of the error handling. The possible values are:
General Comments...
If Ok is...
It means that...
TRUE
FALSE
For Example...
dbSELECTKEY(Customer.Name);
The above statement selects the Name key for the Customer table. If the
system cannot find the desired key a run time error occurs.
Using the return value:
By using the return value, a run time error can be avoided, if the system
cannot find the desired key.
IF dbSELECTKEY(Customer.Name) THEN
MESSAGE(The key was successfully selected!)
ELSE
MESSAGE(Sorry, the key could not be found...);
AL Reference Guide
111
dbSETCURREC
dbSETCURREC
dbSETCURREC(Record)
Record
General Comments...
In each object containing AL code, only one record per table can be
marked as current record. Attempts to mark two different records from
the same table as current in the same object will cause a run time error.
In Window objects, the record selected by the cursor will automatically be
marked as current record, when calling sub-objects.
A mark will be valid until the system exits the AL code module in which
dbSETCURREC was used.
Please observe that it is not the contents of the record, but the address of
the record which is stored as current record. If the contents of the record is
changed after dbSETCURREC has been called, then it is possible to get
hold of the contents of the record, using dbGETCURREC.
For Example...
In the report, the report element InvoiceHeader must have the option field
Current Record set to Yes.
The result is that only one invoice will be printed, corresponding to
InvoiceHeader, as set by dbSETCURREC(InvoiceHeader).
112
ALReference Guide
dbSETFILTER
dbSETFILTER
The filter expression. A valid expression consists of alphanumeric characters and one or more of the following operators: <, >, ?, &, | and
=. Furthermore replacement fields (%1, %2, ...) can be used to insert
values at run time.
Value
- Flow: i; Datatypes: -
General Comments...
If the function is called with a field for which a filter already exists, this
filter will be removed before the new one is set.
Filters can be constructed, using the following operators
Operator...
Explanation...
..
Range
&
And
Or
<
Less than
<=
>
Greater than
>=
<>
Different from
Explanation...
Current period
Px..Py
Period x to y
Current year
For Example...
Explanation...
A..Z
range from A to Z
A|G
A or G
AL Reference Guide
113
dbSETFILTER
Example...
Explanation...
<>B
all except B
<>''
<=200 | >500
Selects all accounts in the range from 100 to 200 and account no. 300
Using a filter entered directly in a string:
Selects all accounts in the range from 100 to 200 and account no. 300.
114
ALReference Guide
dbSETRANGE
dbSETRANGE
- Flow: i; Datatypes: -
The lower limit of the range. The type of FromValue must match
Record.Field.
ToValue
- Flow: i; Datatypes: .
General Comments...
For Example...
The above statement is a quick way to set the same filter as:
dbSETFILTER(Customer.No., >=100&<=200);
AL Reference Guide
115
dbSUM
dbSUM
One or more fields which are defined as sum fields in the current key. All
the fields specified must be defined as sum fields in the current key, otherwise a run time error will occur.
General Comments...
For Example...
The first line selects a key. The second and third lines sets filters for the
fields Customer No and Date in the record Cust. Ledger Entry so that
the sum is only calculated within the specified range. dbSUM is then used
to find the movement in the account 'AAA 1050' for 1994, and the result
is placed in the Amount field.
116
ALReference Guide
dbTESTFIELD
dbTESTFIELD
dbTESTFIELD(Record.Field [, Value])
Record.Field
- Flow: i; Datatypes: -
For Example...
Customer.No. := ;
dbTESTFIELD(Customer.No.)
If No. is different from 1000, the following error message will be shown:
No. must be 1000
in the below Customer
AAA 1050
An analogy:
AL Reference Guide
117
dbTRANSFERFIELDS
dbTRANSFERFIELDS
Enter...
TRUE
General Comments...
General
For
Comments...
Example...
The following Al code sample shows how to use the dbTRANSFERFIELDS function.
dbTRANSFERFIELDS can be used to automatically fill in an Invoice
Header, based on a Customer no.
{Assume that the user has entered a Customer no.}
{in Invoice Header.CustomerNo.}
dbGETREC(Customer, Invoice Header.CustomerNo.);
{Finds a customer in the Customer table}
dbTRANSFERFIELDS(Customer, Invoice Header);
118
ALReference Guide
DELCHR
DELCHR
Which
Where
Effect
<
>
For Example...
AL Reference Guide
119
DELSTR
DELSTR
Length
For Example...
120
ALReference Guide
DMY2DATE
DMY2DATE
The number of the month (1..12). If this optional parameter is not used,
the system will use the current month as default.
Year
Ranges from 1980 to 2059. If this optional parameter is not used, the system will use the current year as default.
Date
For Example...
AL Reference Guide
121
DWY2DATE
DWY2DATE
The number of the week. If this optional parameter is not used, the default
is the current week.
Year
Ranges from 1980 to 2059. If this optional parameter is not used, the
default is the current year
Date
General Comments...
For Example...
The following AL code sample shows how to use the DWY2DATE function. Please note that the input week in this example overlaps two years.
DayOfWeek := 7;
Week := 52;
Year := 1993;
aDate := DWY2DATE(DayOfWeek, Week, Year);
MESSAGE('The %1. day of the week \' +
'in the %2. week\' +
'in the year %3,\' +
'corresponds to the date: %4', DayOfWeek, Week, Year, aDate);
The example illustrates that the system regards the 7. day of the week in
the 52. week in the year as the date 01/02/94.
122
ALReference Guide
ERROR
ERROR
Prints an error message on the screen and ends the execution of the AL
code.
A string containing text to be shown in the error box. The special character '\' divides String into sub-strings, and causes the printing to start on a
new line.
In order to insert variable values in the string, '%'- or '#'-fields can be
inserted at the position(s) where the value(s) are to be substituted.
The size of the resulting error box is determined as follows: the width corresponds to the longest sub-string in String, and the height corresponds to
the number of sub-strings (lines). The system truncates any sub-string
longer than 64 characters.
Value1,...
For Example...
The following AL code sample illustrates how to use the ERROR function.
AccountNo := 1230;
{The execution will be halted when the error statement is executed,}
{and the following statements will never be executed.}
ERROR('Finance Account #1####\' +
'must not be blocked', AccountNo);
MESSAGE('Dummy message!');
{This line is never executed}
AL Reference Guide
123
EVALUATE
EVALUATE
Any type of variable. The value of the evaluated string is assigned to the
variable.
String
A return code which reflects whether an error occurred during the evaluation of the string.
Ok
Indicates that...
TRUE
FALSE
If this optional return value is not used, an error during the evaluation of
the string will cause a run-time error. Otherwise it is assumed that the programmer takes care of the error-handling.
For Example...
The following AL code sample illustrates the behavior of the EVALUATE function when called with variables of three different types.
Value := '010196';
Ok1 := EVALUATE(VarInteger, Value);
Ok2 := EVALUATE(VarDate, Value);
Ok3 := EVALUATE(VarYesNo, Value);
MESSAGE('VarInteger = #1######, and the return code is: %2\' +
'VarDate
= #3######, and the return code is: %4\'+
'VarYesNo
= #5######, and the return code is: %6', VarInteger, Ok1, VarDate, Ok2,
VarYesNo, Ok3);
124
ALReference Guide
FORMAT
FORMAT
FormatNo
Length = 0
Length > 0
Length < 0
This optional argument determines the format to be used during the formatting process. There are three or more formats for each simple AL data
type:
Format No.
Explanation
3, 4, ...
Other formats
In the following four subsections we describe all possible formats for any
simple AL data type. The subsections describe formats for:
1. Numbers: Yes/No, Option, Integer, Long Integer, Decimal No.
2. Dates.
3. Times.
4. Strings: Text and Code.
AL Reference Guide
125
FORMAT
Formatting of Numbers
Table 28 shows match characters for Numbers formats. These match characters are used (in column 3) in table 29, which shows the possible formats for Numbers.
Explanation...
Yes/No
-/_
#,###
.d
Example
Yes/No
0, 1
Yes
No
Option1
Option2
2
Option
0, 1
2
Integer
0, 2
1
Long Integer 0
1
2
126
ALReference Guide
Yes/No
#
t
#
-#
-#
-#,###
-#
-#
Left
Left
Left
Left
Right
Left
Right
Left
Right
12345
-12345
12345
-12345
12,345
-12,345
12345
-12345
12345
-12345
FORMAT
Example
Decimal No.
12,345.12
-12,345.12
1
2
3
4
-#,###.d
-#.d
-#.d
#,###.d-/_
#.d-/_
Right
Left
Right
Right
Right
12345.12
-12345.12
12345.12
-12345.12
12,345.12
12,345.12-
12345.12
12345.12-
Formatting of Dates
Table 30 shows match characters for Dates. These match characters are
used (in column 3) in table 31, which shows the possible formats for
Dates
Explanation
dd
mm
mmmm
yy
yyyy
D/C
Display an uppercase D with any normal date; display an uppercase C with any closing date.
AL Reference Guide
127
FORMAT
Cmm/dd/yy
Right
Cmm/dd/yy
Left
06/01/94
06/01/94
mmddyyD/C
Right
060194D
Cyy/mm/dd
Right
94/06/01
June 1, 1994
Cmmddyy
Right
060194
Cyymmdd
Right
940601
Formatting of Times
Table 32 shows match characters for Times. These match characters are
used (in column 3) in table 33, which shows the possible formats for
Times.
Explanation
hh
hh24
mm
ss
.s
AM/PM
128
ALReference Guide
Alignment Example
3:04:05.06 PM
h:mm:ss.s AM/PM
Left
3:04:05.06 PM
hh24mmss.sT
Left
15:04:05.06T
FORMAT
Formatting of Strings
Table 34 shows match characters for Strings. These match characters are
used (in column 3) in table 35, which shows the possible formats for
Strings.
Explanation
Display as text.
0, 1, 2
Code
0, 2
String
Left
ABC
Left
ABC
Right
Left
ABC
100
100
For Example...
123,456.78-<
AL Reference Guide
129
INCSTR
INCSTR
NewString := INCSTR(String)
String
NewString
General Comments
For Example...
Notice that when the input string contains a number like 99 (which is
increased to 100), the length of the output string will be: LEN(String) + 1.
The following AL code sample illustrates the properties of the INCSTR
function.
Account := 'Account no. 99 does not balance';
NegAccount := 'Account no. 2342 shows a total of -452 $';
MyAccount := 'My bank account shows a total of 0 $';
MESSAGE('The test-strings before INCSTR is called:\' +
'%1\' +
'%2\' +
'%3\', Account, NegAccount, MyAccount);
ResAccou := INCSTR(Account);
ResNegAc := INCSTR(NegAccount);
ResMyAcc := INCSTR(MyAccount);
MESSAGE('The test-strings when INCSTR has been called:\' +
'%1\' +
'%2\' +
'%3', ResAccou, ResNegAc, ResMyAcc);
130
ALReference Guide
INCSTR
The example shows that if the string contains more than one number then
only the last number will be changed. Furthermore it is seen, that positive
numbers (and zero) are increased, while negative numbers are decreased.
AL Reference Guide
131
INSSTR
INSSTR
NewString
For Example...
The following AL code sample illustrates how to insert one string into
another.
Str := 'Press ENTER to continue';
SubString := 'or ESC ';
MESSAGE('The test-string before INSSTR is called:\' +
'>%1<', Str);
NewStr := INSSTR(Str, SubString, 12);
MESSAGE('The resulting string after INSSTR has been called:\' +
'>%1<', NewStr);
132
ALReference Guide
LOWERCASE
LOWERCASE
NewString := LOWERCASE(String)
String
The string to be converted. Only letters in the range A..Z (and special
national characters) are affected.
NewString
For Example...
AL Reference Guide
133
MAXSTRLEN
MAXSTRLEN
Returns the maximum length, that is the defined length, for a String variable.
Length := MAXSTRLEN(String)
String
For Example...
In this example we assume that City has been defined as a Text type variable, with the maximum length 30.
City := 'Atlanta';
MaxLength :=MAXSTRLEN(City);
Length := STRLEN(City);
MESSAGE('The MAXSTRLEN function returns: %1,\' +
'while the STRLEN function returns: %2',MaxLength, Length);
134
ALReference Guide
MESSAGE
MESSAGE
General Comments...
For Example...
When the system executes a message statement in the AL code it will not
display the message box immediately, but wait until the execution of the AL
code is finished or until the system temporarily stops to wait for user
interaction.
Only a limited amount of messages can be held in memory. The exact number
of messages depends on the sizes of the individual messages. The execution
of the code will be interrupted if the total size of the messages exceeds the
available memory.
AL Reference Guide
135
MESSAGE
Note the way the fixed format truncates the number in the last line above.
136
ALReference Guide
NORMALDATE
NORMALDATE
Returns the normal date (not closing) for the argument Date.
NewDate := NORMALDATE(Date)
Date
The input date which can be either a closing date or a normal date. If the
value of Date is set to the undefined date (0D), a run time error will occur.
Note: All dates have a corresponding closing date. A closing date is
regarded by the system as a period following the given date, but before
the next normal date, thus closing dates are sorted immediately after the
corresponding normal date, but before the next normal date.
The figure below illustrates how the system sorts the closing dates
between the normal dates for an arbitrary month..
April 1994
040194D 040194C
040294D
...
NewDate
For Example
Normal date
Normal date
Closing date
Normal date
The following AL code samples illustrates how to use the NORMALDATE function. In the first example a normal date is given as input, and
in the second example a closing date is given as input.
A normal date as input.
OldDate := 040494D;
NorDate := NORMALDATE(OldDate);
MESSAGE('The normal date for %1 is %2, OldDate, NorDate);
OldDate := CLOSINGDATE(040494D);
NorDate := NORMALDATE(OldDate);
MESSAGE(The normal date for %1 is %2,OldDate, NorDate);
AL Reference Guide
137
OPENWINDOW
OPENWINDOW
These optional parameters are used to specify the position of the upper
left corner of the window. Line and Pos must be greater than or equal to 1.
If Line and Pos are not specified the window will be centered at the middle of the screen.
General Comments...
For Example...
Each object (function-, report-, ...) can only have one dialog window open at
a time. The system will automatically close an existing dialog window before
it opens a new dialog window.
The system will also close the dialog window automatically when an object
is terminated.
The system will open the dialog window and display the following text:
Account no. 5634
shows a total of 1000 $
This shows that the values of the variables AccNo and TotSum has been
inserted in the '#'-fields.
138
ALReference Guide
POWER
POWER
For Example...
First we will present some typical uses of the POWER function, and second we will show an AL code saple illustrting how to use the POWER
function.
Compound Amount
A = P ( 1 + r) n
Example: A man deposits $2800 in a bank which pays 5% compounded
quarterly. What will the deposit amount to in 8 years?
Answer: There are n = 8x4 = 32 payment periods at interest rate
r = 0.05/4 = 0.0125 per period. Then the amount is:
A = $2800(1 + 0.0125)32 =$2800(1.4881) = $4166.68
The Amount of an Annuity
( 1 + r) n 1
A = P ----------------------------r
This is often called an annuity.
Example: An investor has an annuity in which a payment of $500 is made
at the end of each year. If interest is 4% compounded annually, what is the
amount of the annuity after 20 years?
Answer: Here r = 0.04, n = 20 and the amount will be:
A = $500((1 + 0.04)20 - 1)/0.04 = $14,889.05
AL Reference Guide
139
POWER
An AL Code Sample
Number1 := 2;
Power1 := 8;
Number2 := 100; Power2 := 0;
Number3 := 5;
Power3 := -0.5;
Res1 := POWER(Number1, Power1);
Res2 := POWER(Number2, Power2);
Res3 := POWER(Number3, Power3);
MESSAGE('%1 raised to the power of %2 = %3', Number1, Power1, Res1);
MESSAGE('%1 raised to the power of %2 = %3', Number2, Power2, Res2);
MESSAGE('%1 raised to the power of %2 = %3', Number3, Power3, Res3);
The last message box shows that raising a number to the power of -0.5
corresponds to the squareroot of the number.
140
ALReference Guide
ROUND
ROUND
This optional parameter determines the precision used when rounding off.
The default value is 0.01 for the US version. (In some european countries
other default values may be used).
Direction
NewNumber
'='
'>'
round up.
'<'
round down.
For Example...
AL Reference Guide
141
ROUND
Number
1234.56789
-1234.56789
142
ALReference Guide
Precision
Direction
NewNumber
100
1200
0.1
1234.6
0.001
1234.568
0.001
<
1234.567
0.001
>
1234.568
100
-1200
0.1
-1234.6
0.001
-1234.568
0.001
<
-1234.567
0.001
>
-1234.568
SELECTSTR
SELECTSTR
CommaString
For Example...
The following AL code sample shows how to use the SELECTSTR function.
CommaStr := 'This,is a comma,separated,string';
SubStr1 := SELECTSTR(2, CommaStr); {Pick out the 2nd substring}
SubStr2 := SELECTSTR(4, CommaStr); {Pick out the 4th substring}
MESSAGE('The two calls to SELECTSTR returns:\' +
'>%1<\' +
'>%2<', SubStr1, SubStr2);
AL Reference Guide
143
SERIALNO
SERIALNO
Returns a string, which contain the serial-number for the licence file for
your program.
String := SERIALNO()
String
For Example...
The following AL code sample shows how to use the SERIALNO function.
Sn := SERIALNUMBER();
MESSAGE('The serial number for this\' +
'software package, is: %1', Sn);
144
ALReference Guide
SETSTRLEN
SETSTRLEN
String
This is a string of the length 1. The character in this string is used to 'fill
out' empty space at the end of the output string.
If not specified, blanks are used as default.
NewString
For Example...
AL Reference Guide
145
SETSTRLEN
146
ALReference Guide
STRCHECKSUM
STRCHECKSUM
String
WeightString
Modulus
M o d u l u s Stri ng [ i ] W e i g h t S t r i n g [ i ] MOD
Mo dulu s MOD
Mo dulu s
where n = STRLEN(String).
For Example...
StrNumber := '4378';
Weight := '1234';
Modulus := 7;
CheckSum := STRCHECKSUM(StrNumber, Weight, Modulus);
MESSAGE('The number: %1\' +
'has the checksum: %2', StrNumber, CheckSum);
AL Reference Guide
147
STRCHECKSUM
12
7
11
7
10
6
Country code
9
2
8
2
7
1
6
3
5
5
4
7
3
4
2
6
1
3
Checksum
Method:
1. The 12 digits in position 13 to 2 are used to calculate the checksum at position
1.
2. Starting from position 2 all values at even positions are summed. The result is
multiplied by three. We call this value Even.
3. Starting from position 3 all values at odd positions are summed. We call this
value Odd.
4. Total = Even + Odd.
5. The modulus 10 checksum is then: (10 - Total MOD 10) MOD 10.
148
ALReference Guide
STRLEN
STRLEN
Length := STRLEN(String)
String
General Comments...
For Example...
AL Reference Guide
149
STRMENU
STRMENU
Creates a menu box. The menu box is placed at the middle of the screen.
The selected menu option. If the user used ESC to quit the menu box, the
value 0 (zero) will be returned.
For Example...
...and the cursor will be placed on option no. 3 ('Exit to OS'). The selected
option will be stored in the variable Selected, and shown by the message
box as, for example:
You selected option no.: 2
150
ALReference Guide
STRPOS
STRPOS
Position
General Comments...
The STRPOS function only returns the position of the first occurrence of
the sub-string.
For Example...
The following AL code sample illustrates how to use the STRPOS function.
String := 'ABC abc abc xy';
SubStr := 'abc';
Pos := STRPOS(String, SubStr);
MESSAGE('The search for the substring: >%1<\' +
'in the string: >%2<,\' +
'returns the position: %3', SubStr, String, Pos);
{The STRPOS function is case sensitive. Furthermore it only}
{returns the position of the first occurrence of the substring.}
AL Reference Guide
151
STRSUBSTNO
STRSUBSTNO
Replaces %1, %2,... and #1, #2, ... fields in a String with the value(s)
given as optional parameter(s).
NewString
An output string in which the '#' and '%' fields have been substituted with
the corresponding values.
For Example...
152
ALReference Guide
SYSTEMVERSION
SYSTEMVERSION
Returns a String, which contain the name and version of the operating
system.
String := SYSTEMVERSION()
String
A string describing the type and version of the operating system. Some
typical examples of the format of the returned string are:
For Example...
Operating System
String
DOS_6.0
AIX_3.2
HP UX version 8.02
HP-UX_8.02
OS/2_2.1
A typical result:
The operating system is: DOS_6.0
AL Reference Guide
153
TIME
TIME
Time := TIME()
Time
General Comments...
For Example...
The TIME function can only be used to retrieve the time from the operating system, that is, you cannot use the TIME function to set the time in
the operating system.
The following AL code sample shows how to use the TIME function.
CurrentTime := TIME(); {Get the current time
from the operating system.}
MESSAGE('The current system time is: %1', CurrentTime);
A typical result:
The current system time is: 4:15:46.84 PM
154
ALReference Guide
TODAY
TODAY
Date := TODAY()
Date
General Comments...
For Example...
The TODAY function can only be used to retrieve the current date from
the operating system, that is, you cannot use the TODAY function to set
the date in the operating system.
The following AL code illustrates how to use the TODAY function.
CurrentDate := TODAY();
MESSAGE('The current date is: %1', CurrentDate);
A typical result:
The current date is: 05/27/94
AL Reference Guide
155
UPDATEWINDOW
UPDATEWINDOW
UPDATEWINDOW(Number, Value)
Number
For Example...
The values of the variables AccNo and TotSum has been inserted in the
'#'-fields.
156
ALReference Guide
UPPERCASE
UPPERCASE
NewString := UPPERCASE(String)
String
For Example...
AL Reference Guide
157
USERID
USERID
String := USERID()
String
General Comments...
When you enter your application you will be prompted for your user-ID.
The USERID function reflects this input.
For Example...
The following AL code sample illustrates how to use the USERID function.
User := USERID();
MESSAGE('The system was started by %1', User);
A typical result:
The system was started by: JOE
158
ALReference Guide
WAITKEYPRESS
WAITKEYPRESS
WAITKEYPRESS()
General Comments...
For Example...
The system will ignore if you press any other key than Enter or ESC.
This AL code sample illustrates how to use the WAITKEYPRESS function.
Str:= 'An arbitrary message to the user\' +
'Press ENTER or ESC to continue';
OPENWINDOW(Str);
WAITKEYPRESS(); {Pauses until ENTER or ESC is pressed}
CLOSEWINDOW();
AL Reference Guide
159
WINDOWINPUT
WINDOWINPUT
A variable that may be edited in the dialog window. All AL datatypes are
valid.
NewNumber
The number of the next field in the window. Please observe that if the
ESC key is used to leave the window, a 0 will be returned instead.
For Example...
160
ALReference Guide
WORKDATE
WORKDATE
WorkDate := WORKDATE()
WorkDate
General Comments...
For Example...
This function returns the work date chosen using the Work Date option on
the General pull-down menu. If the user has not specified a work date,
then this function returns the current system date.
The following AL code sample illustrates how to use the WORKDATE
function.
WorkDate := WORKDATE();
MESSAGE('The work date is: %1', WorkDate);
AL Reference Guide
161
WORKDATE
162
ALReference Guide
Part
163
MYPROG.EXE
via C-library
NAVISION
via AL code
Database
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Interface
Database Management System
DBMS
Database
c:
d:
f:
The following sections will discuss the following topics, based on figure 1:
The first section introduces you to the terms Physical and Logical
database. The main concern in this section is the structure of the Logical
database.
The second section describes the facilities provided by the Database
Management System (DBMS) to ensure the integrity of the data and
restrict access to the database.
The third section introduces the NAVISION program interface. This
interface enables you to access any subset of records in a NAVISION
database, in a specific sorting.
The fourth section presents special features designed in order to increase
the run time performance of NAVISION.
164
The Structure
of the Database
If you are new to the NAVISION database system, this section will introduce
you to some of the most important concepts you need to understand in order
to work with data in a NAVISION database. The word database is in such
common use that we must begin by defining what a database is.
We normally consider a database as a collection of related information, or
data. By data we mean some known facts that can be stored and that have an
implicit meaning. A typical example is a list which describe the names,
addresses and telephone numbers of your customers. These data can be
recorded in an indexed address book, or in a disk file using appropriate
software. This is a simple example of a collection of related information and
hence it is a database.
In this document we will consider a database as a collection of related data
which is stored in a computer in a way that enables you to retrive the
information you need very quickly.
165
the other category of objects, that is, the tables. A typical example of the use
of a service provided by the first category of objects, is when we use a
window object to show a detailed view of the fields in a record. Another
typical use of the first category of objects, is when we use a report object to
print, for example, a survey of a budget.
In the rest of this chapter our main concern will be the table objects, that is,
we will discuss the logical structures of a NAVISION database.
Figure 2. The physical
database vs. the logical database
d:\database
e:\database
f:\database
Logical Organization
Access to the data is made possible by a well-defined logical organization
composed of:
1. Fields. This is the smallest logical structure used in the NAVISION database. A field is used to hold a single bit of information, for example a
name Joe or an amount 2,352.00. A field can only hold information of
a specific type. The NAVISION database system distinguishes between 9
different types of information. Fields are assembled into a structure called
a Record.
2. Records. This is a logical structure used to store a single entry in the
database. A record consists of a number of fields which are used to store
information about important properties of the entry. Records are organised
in tables.
3. Tables. A table can be thought of as a n times m matrix. Each of the n
rows describe a Record and each of the m columns describe a Field in the
record. Tables are organized in Companies.
4. Companies. This is the largest logical structure used in a NAVISION
database. A Company may be considered as a sub-database, and its primary use is to separate and group large portions of data in a database. A
Company can contain both private tables, and tables shared with other
companies.
These logical units will be discussed in the following sections in the same
order as in the above list.
166
The Option field "Color" is defined with the option string "Red,Green,Blue".
Valid values of the field are then 0, 1 and 2, with 0 representing "Red", etc.
When the "Color" field is formatted, 0 is converted into the string "Red", 1
into "Green", and 2 into "Blue".
Integer. Denotes integers between -32,767 and 32,767 and fills two bytes.
Long Integer. Denotes an integer between -2,147,483,647 and
2,147,483,647 and fills four bytes.
Decimal No. A decimal number between -1063 and 1063. The exponent
ranges from -63 to +63. Decimal numbers are held in memory with 18
significant digits. The representation of a decimal number is a Binary Coded
Decimal (BCD). A field of the type Decimal No. fills 10 bytes.
Date. Contains a date value in the range from January 1,1980 to December
31, 2059. An undefined date is expressed as 0. A field of the type Date is
stored as an Integer, that is, fills two bytes.
Note: All dates have a corresponding closing date. The closing
date for a given date is regarded by the system as a period
following the given date, but before the next normal date; that is,
a closing date is sorted immediately after the corresponding
normal date, but before the next normal date.
167
Date
Undefined
January 1, 1980
January 2, 1980
January 3, 1980
168
Figure 3. A
record shown as
a single row in a
table
Field
name:
Number
Name
Amount
660203
Jensen
1267.57
Type:
Long
Integer
Text
Decimal
No.
Size:
(bytes)
Max length + 1
4
Modification
date
10/14/96
Date
10
Field and Table design takes place in the NAVISION development system.
Each field and each table created receives two forms of identification:
The developer defines an identification number (Integer). This number is
a unique identification which cannot be changed. This number is used by
developers working with one of the programming interfaces.
The developer also defines a name, which is an alphanumeric string
serving as a label (such as CUSTOMER or CITY). The name appears in
the user interface (on the screen) and should be meaningful and easily
understood. This name serves as secondary information, and can be
changed at any time.
Besides the ordinary fields discussed in this section, the NAVISION database
system also includes 2 special types of fields:
Calculated-fields
Calc-filter fields
How these special fields provide powerful data manipulation mechanisms is
described in the section Special Database Fields on page 177.
169
Tables
The records in the NAVISION database are organized into Tables. A
NAVISION table may be visualized as a two-dimensional matrix, consisting
of columns and rows. A table can hold any number of records with a unique
primary key, each record consisting of up to 255 fields. However, the total
size of a record is limited to 1000 bytes.
Figure 4 shows a table with 6 rows and 5 columns. Each row is a record, and
each column is a field..
Figure 4. The
structure of a
table: Each column denotes a
field, and each
row denotes a
record.
Rows: Records
A Table
Consec.
No.
Account
No.
Date
Text
Amount
Columns: Fields
A table is considered as consisting of two parts: a table description and the
table data. The table data is the part users often think of as comprising the
database, because it contains the actual records with their data fields. The
layout and properties of those fields, however, are specified by the table
description. Figure 5 gives an overview of the major elements in a table
description.
Figure 5. The elements of a table
description.
Table Description
Field
description
- Field Type,
- Name,
- Number,
- Initial Value,
- and other
field properties
Key
description
Other table
properties
170
system to access tables with different structures. When accessing a table the
DBMS can extract the definitions of the table structure from the table
description, and thereby correctly access any table.
An important feature of a table description is that the definition of table
properties can be used by more than one data table. This is discussed in the
section Companies on page 176.
A more detailed description of the contents of the table description is given in
the list below. Each table description contains the following information:
Table number and name. The table number serves as a unique
identification of a specific table, and cannot be changed once it has been
defined. The table name is secondary information, which will be
displayed in the user interface. The name can be changed at any time.
Field Properties. For each field, the following properties are described:
- Type: the nine NAVISION field types described at page 168.
- Number: an integer assigned by the developer during table definition
- Name: an alphanumeric string assigned by the developer during table
definition.
- Initial value: the value assigned to the field upon record initialization
- Formatting properties: how the contents of the field are to be displayed
on screen and when printed.
- Keying limitations: such as, minimum and maximum values, positive
and not blank.
- Entry Procedures: Special tests, adjustments and conversions to be
made to the contents of the fields after keying in.
- Relationships: Another table/other tables with which the field will share
information.
- State: active or inactive. The state is defined upon table creation, and
can be toggled back and forth according to the following simple rule:
An inactive field can always be changed to an active field. But an
active field can only be changed to inactive if the field is unused
(cleared) in all records. This means that if this field contains data in one
or more records, this data will have to be cleared before the field can be
marked as inactive.
A list of Keys:
- Key field numbers.
- Sum fields defined for each key (see appendix A).
AL Code. Special tests, adjustments and conversions to be made when
inserting, modifying or deleting from the table.
The list above shows that the table description includes information about the
key field numbers. At page 170 we have already briefly discussed the notion
of a key; but now that we have introduced you to NAVISION tables, you are
ready to learn more about keys.
Keys
A table description contains a list of keys. A key is a sequence of one or more
field IDs from the table. Up to 20 keys can be associated to a table. The first
171
Secondary keys
We have already mentioned that up to 20 keys can be associated to a table
and that the first is the primary key. All other keys are secondary keys and
optional. Secondary keys are used when you want to view records in an order
different from the order they are sorted according to the primary key fields.
The number of fields in the primary key affects the possible maximum
number of fields in the secondary keys.
Note: The number of fields in the primary key + the number of
fields in a secondary key which do not occur in the primary key,
must always be less than or equal to ten.
This means that if your primary key includes four distinct fields, then your
secondary keys can include these four fields, and at most six others.
Correspondingly, if your primary key consists of ten distinct fields, then your
secondary keys can only consist of combinations of these fields.
A secondary key uses an additional data structure called an index. The idea
behind an index is similar to the idea behind the indexes used in common
textbooks. A textbook index lists important terms at the end of the book in
alphabetical order. Along with each term, a list of page numbers where the
term appears is given. We can search the index to find a list of page numbers
(addresses) and easily locate the term in the textbook by searching the
specified pages. Hence, the index is an exact indication of where each term
occurs in the textbook.
When you define a secondary key and mark this key as active, the system will
automatically maintain an index reflecting the sorting order defined by the
key. Multiple secondary keys may be active at the same time.
A secondary key can be changed into an inactive key. This means that the
DBMS does not maintain its index. An inactive key does not take up time or
database space during table updates.
Inactive keys can be reactivated; this process may consume some time
depending on the size of the table, because the DBMS has to scan the entire
table to rebuild the index.
172
The fields comprising the secondary keys are not guaranteed to contain
unique data; the DBMS does not reject records with duplicate data in
secondary key fields. If two or more records contain identical information in
the secondary key, the DBMS will use the primary key for the table to solve
this conflict. The example below shows how the primary key influences the
sorting order when a secondary key has been activated:
We assume that the Customer table includes four entries (records). The
records in the Customer table have two fields: CustomerNo and
CustomerName. The Keylist for the Customer table is :
Key no. Key type
Definition
Secondary
<CustomerName>
CustomerName
001
PC&C
002
IBM
003
Lotus
004
PC&C
When selecting the secondary key, the CustomerName field is used as basis
for the ordering. As the contents of these fields are not unique, the records
must be subsorted according to the primary key.
CustomerName CustomerNo
IBM
002
Lotus
003
PC&C
001
PC&C
004
The last two records are sorted, reflecting the values in the primary key.
173
to maintain. But now you are not able to retrive your data as easily as before.
In order to retrieve the desired data set from the database, you will often have
to define or reactivate secondary keys in order to obtain appropriate sortings.
Depending on the size of the database, this may consume some time, as the
system builds the new index.
The decision whether to use a few or many keys are not easy to discuss in
general. The choice of appropriate keys and the number of active keys to use,
should be selected as the best compromise between the speed of data retrieval
and the speed of data updates (operations which insert, delete or modify
data). In general it may be worthwile to deactivate complex keys, if such
keys are only used on rare occations.
The overall speed of NAVISION will depend strongly upon a number of
factors:
The size of your database
The number of active keys
The complexity of the keys
The number of records in your tables.
The speed of your hardware, that is, the speed of your computer and its
disksystem.
Key Description
1 (Entry No.)
Primary key
Secondary Key
Secondary Key
174
Secondary Key
Companies
The DBMS can access only one logical database at a time, but this database
can be divided into one or more companies. A company is a "sub-database",
and its primary use is to separate and group data in the same database. As
mentioned at page 170 fields and tables are identified by a number.
Companies are not identified by a number, but by a name. A company
"bundles" one or more data tables together, into a logical superstructure
which is identified by a company name. Other than the shared company
name, the different tables within a company have nothing else in common.
Opening a company is your first step after opening the database or
connecting to a server.
Figure 7 shows a database with four tables. The four table descriptions,
appearing to the left, apply to each of the data tables, which are logically
sorted into three companies. The records in the tables G/L Account,
Customer and Vendor, all have the same structure and the same field
definitions, even though they belong logically in three different companies.
Only the data stored in the fields differ.
Figure 7. This illustrates
sharing of data between
different conpanies
Company
Company
Company
G/L Account
Data
Data
Data
Customer
Data
Data
Data
Vendor
Data
Data
Data
Table Description
Printer Selection
Common Data
175
Calculated Fields
Calculated fields is a powerful feature in the NAVISION database system.
The Calculated field is a fundamental concept which highly influences the
way a NAVISION application is designed.
Calculated fields and the underlying concept of Sum fields have been
designed in order to increase the performance in activities, such as
calculating the balance of your customers, which in traditional database
systems involves a series of accesses and calculations before a result is
available. Why such a result will be immediately available via the use of
Calculated fields will be clear as you read through the rest of this section and
Appendix A, which deals with the underlying concept of Sum fields.
Calculated fields are not stored together with the table data, why a Calculated
field can be thought of as a virtual field, which is an extension to the table
data. When a table is opened, the values in Calculated fields are set to 0
(zero). In order to update a calculated field, the programmer must use the AL
function dbCALCFIELDS or the C-Library function DBL_CalcFields().
There are two types of Calculated fields:
Yes/No. A Calculated field of this type is used to signal if any records
exists within a specified range in another table.
Decimal No. A Calculated field of this type contains the sum of a column
within a specified range in another table.
176
CountryCode
Name
Balance
AnyEntries
(calc. field)
(calc. field)
US
60
Yes
10010
US
90
Yes
10020
FR
210
Yes
10030
Russel Publishing
UK
No
10040
La Cuisine Francais
FR
300
Yes
Date Comment
Virtual part of
the table data
Amount
10000
10
10000
20
10000
30
10010
40
10010
50
10020
60
10020
70
10020
80
10040
90
10040
100
10040
110
177
definition. Sum fields are the basis for the operations and flexibility
provided by the Calculated fields. Sum fields are discussed in
appendix A.
Reverse sign. Makes it possible to shift the sign of the result in the
Calculated field.
The second special database field, the Calculation Filter field, is used in
connection with the above mentioned list of filters.
Table B
Table A
Constants
Ordinary fields
Calculation
Table C
Definition
Calc. fields
Table D
: Path for information used in Calculation Definition
: Path for data used in computation of Calc. Fields
178
Important
Tasks for
the DBMS
In this section we discuss some important tasks for the DBMS. The topics
described in this section cover some of the most powerful features in the
NAVISION database system.
A main task for the DBMS is to protect your data from any kind of damage or
corruption. The data protection mechanisms build into the NAVISION
DBMS are illustrated in figure 10, which gives a structural overview. As the
figure suggests, the data protection mechanisms fall into two main
categories.
Mechanisms to ensure the...
1. Data integrity. We explain how the DBMS manages the integrity of your
data.
2. Data security. We present the techniques used to protect the database
against persons who are not authorized to access the database.
DBMS Tasks
Data Protection:
- Data Integrity
- Data Security
Logical Database
Data Integrity
Data integrity deals with the reliability of the data stored in the database, that
is, the requirement that the database must describe the real world as credible
as possible. The NAVISION means to obtain data integrity are described in
the following sections:
Write Transactions and Recovery. We present a logical unit of
179
180
181
procedure.
Figure 11. Three
application
accessing different version of the
database
Version
D
Time
(A)
Report
Entry
Backup
(B)
182
Data Versions
Database
Version 1:
Free
C
Free
Database
Version 2:
C1
A1
If an error occurs during the transaction or the user decides to abort the
changes, the database blocks occupied by the copied branch will be released
and be available for new database updates.
If the transaction is committed, this new internal node will replace the old
node, and the database blocks used by the old versions of customer A and B
will now be available as free database blocks which can be used by database
updates.
The database contains a number of historical versions. Gradually, as the free
area in the database is consumed by succeeding historical versions, new
versions begin to replace the oldest versions.
Slow operations can run into trouble in this environment. Suppose
Application A is reading data from the latest version, while generating a very
time-consuming report. In the meantime, Application B begins performing
write transactions which consist of order entries.
As order entries are added to the database, newer versions of the database is
created. The maximum number of historic versions in your database, depends
on the space in the database which currently is not used by the newest
183
Table Locking
In multi-user environments the DBMS ensures the integrity of the data, by
setting write locks on all the tables you are updating. This prevents other users
from making changes to the same tables.
While write operations automatically lock a table during updates, you can
explicitly lock a table, even if you are not certain a write operation will be
performed. By locking a table immediately before accessing a record, you
are assured that the data you eventually might change in the record conforms
to the data you have read, even if some time passes in between. A write lock
does not influence data retrieval; that is, although a table is locked, it does not
prevent other users from read access to the records in the table.
A write lock is active until the write transaction is either aborted or
committed. Figure 13 uses pseudo language mnemonics to illustrate the
184
Table Locking
.
.
.
.
.
Table B locked
Table A locked
BeginWriteTransaction;
LockTable(TableA)
FindRec(TableA, ...);
(1)
(2)
InsertRec(TableA, ...)
(3)
InsertRec(TableB, ...);
(4)
.
.
.
.
.
EndWriteTransaction
(5)
.
.
The figure illustrates both an explicit lock and an automatic lock. Line (1) in
the write transaction explicitly locks table A. If this explicit lock was not set
on table A, the DBMS would automatically lock this table when a record is
inserted (3). Table B is not locked explicitly, but is locked automatically by
the DBMS when a record is inserted (4). Both locks are active until the End
Write Transaction command is executed in line (5).
Deadlock Detection
The correct functioning of a multi-user system will depend on the
coordination of the activities. If a transaction process requires write access to
several tables at once, care must be taken to avoid the situation where it can
obtain access to some of the necessary tables and another transaction process
can obtain others of them, but where neither of them can proceed without the
other finishing. This causes both of the transaction processes to wait for the
other transaction process to finish. As a result both processes will have to
wait forever. Such a situation is known as a Deadlock (or as Deadly Embrace).
In order to avoid deadlock situations, the DBMS has been provided with an
automatic deadlock detection mechanism, which detects these situations and
ejects one of the write transactions. Figure 14 illustrates how a deadlock can
185
occur.
Application 1
Time
A
A
A
A
A
A
A
A
LockTable(A)
Table AA now Locked
A
A
A
A
A
A
A
A
A
A
LockTable(B)
Wait for table B to
be unlocked
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
Application 2
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
A
LockTable(B)
Table BAA now locked
A
A
A
A
A
A
A
A
A
A
A
LockTable(A)
Wait for table A to
be unlocked
AA
AA
AA
AA
AA
AA
AA
AA
A
A
A
A
A
A
A
Application 2 ejected
and transaction aborted.
Lock attempt on Table A
cancelled and Table B
automatically unlocked
Table B locked
AA
AA
AA
AA
AA
AA
AA
AA
AA
AA
AA
AA
The DBMS will always eject the application which causes the deadlock to
occur, cf. the example shown in figure 14. This rule applies for any number
of applications involved in a deadlock.
Commit in AL and C
Although the concept of committing an update is the same whether you are
using AL code or the C-Library, there are some minor differences. This
subsection explains these differences in detail.
When you want to perform an update using the C-Library, the first thing you
must do, is to explicitly tell the system that you want to perform a write
transaction by using DBL_BWT (BeginWriteTransaction). Likewise you
must use DBL_EWT (EndWriteTransaction) to explicitly tell the system
when your write transaction ends.
When you use AL code to perform updates to a NAVISION database, these
BeginWriteTransaction and EndWriteTransaction statements are handled
implicitly by the system, that is, the system automatically executes these
commands before the AL code is entered, and when the AL code has been
executed. This means that if you only need to perform a single write
186
AL code
C code
BeginWriteTransaction
AL Module
AL Statements
dbCommit(...)
AL Statements
EndWriteTransaction
DBL_BWT();
}
}
1. Trans.
C code
DBL_EWT();
DBL_BWT();
2. Trans.
C code
DBL_EWT();
}
}
1. Trans.
2. Trans.
187
modified whenever the database is open. A user may change his password at
any time, but only a special user, the super user is authorized to create,
change and delete users, passwords and user rights.
Encryption
Security precautions continue after database manipulation stops; all data
stored to disk are automatically encrypted. The encrypted data cannot be
deciphered by low-level editors or disk utilities; only proper, authorized
accesses will yield legible material.
188
Interfacing
the DBMS
Application
retrieving data
Table Handle:
Current key
Filter(s)
Handle
Handle
Handle
Database
Interface
AAAA
AAAAAAAA
AAAAAAAA
AAAAAAAA
AAAAAAAA
AAAAAAAA
AAAAAAAA
AAAAAAAA
AAAAAAAA
AAAAAAAA
AAAAAAAA
AAAAAAAA
AAAAAAAA
AAAAAAAA
AAAAAAAA
AAAAAAAA
AAAAAAAA
AAAAAAAA
AAAAAAAA
AAAAAAAA
AAAAAAA
AAA
DBMS
Database
Table
...
Table
...
Table
Table Handles
When a table is closed it is identified only by a number defined by the
developer when the table was created. However, when an application
requests for access to a specific table, the DBMS assigns the table a table
189
When your application access a NAVISION table via a handle, all its records
are accessible. Alternatively, you can define another view of the table by
assigning a key and filters to the table handle. This allows you to open
various "views" of a single table, each with its own set of filters and a key.
Current key
As discussed in the section Secondary keys on page 173, the DBMS can
maintain up to 19 secondary keys. These secondary keys can be used when
you want to view records in an order different from the order they are sorted
according to the primary key fields. When you select a secondary key to be
used instead of the primary key, the newly activated secondary key is called
the current key.
An example: assume that the table Customer includes four entries (records).
The records in the Customer table have two fields: CustomerNo and
CustomerName. The Keylist for the Customer table is:
Key no. Key type
Definition
Secondary
<CustomerName>
When using a handle, your default view of the records in the Customer table
will be sorted according to primary key:
CustomerNo
CustomerName
001
PC&C
002
IBM
003
Lotus
004
PC&C
Alternatively you can assign key no. 2 to the table handle, that is, define the
current key to be key no. 2. This changes your view of the Customer table
into:
CustomerName CustomerNo
IBM
002
Lotus
003
PC&C
001
PC&C
004
Filters
A filter can be set for any field in any table, to limit the number of records
upon which operations such as searches and calculations are based. When
190
accessing a NAVISION table via a table handle, you can assign one or more
filters to the handle, in order to suit your specific task.
You can apply a filter to one or more fields and then perform a task that
would typically affect all of the elements in the table, but now that you have
applied a filter, only those elements that fulfil the conditions of the filter are
affected. When you apply a filter to more than one field, there will implicitly
be a logical AND between these filters.
Figure 17 gives an example of the use of filters, and illustrates the effect of
the implicit logical AND between the filters. Suppose you want an overview
of the French customers in your Customer table. This can be obtained by
applying the filter FR to the Country field in the Customer table.
Furthermore you want to see which french customers have a credit limit
greater than $3000, so you will also have to apply the filter >3000 to the
Credit limit field.
Figure 17. Applying
filters on the Customer table to find
french customers
with a credit limit
greater than $3000
Filters
Filters:
Table:
>3000
Number
10000
CustomerName
10010
CreditLimit
FR
CountryCode
US
1000
400
10020
5000
FR
10030
Russel Publishing
34000
UK
10040
La Cuisine Francais
1500
FR
5000
US
Your View:
10020
FR
As figure 17 illustrates, you have two french customers, no. 10020 and
10040. But as customer no. 10040 has a credit limit less than $3000, your
view of the table will only show one customer, namely customer no. 10020
Jean Saint Laurant who has a credit limit of $5000.
A filter is a composite string, containing one or more of the operators shown
in the table below:
Operator Meaning
..
Range
Example
Explanation
30..40
..310790
OR
5|6
&
AND
<>
Different from
<> 0
>
Greater than
> 100
191
>=
Greater than
or equal
>= 10
<
Less than
< 100
<=
Less than or
equal
<= 100
Contains
?Ltd.
Operator Hierarchy
The operators used in filter expressions are organized in four hierarchical
groups which determines the order in which the operations are carried out.
The lower the number of the group, the higher the precedence: The four
groups are:
1. .. (Range), () (parentheses)
2. <, >, <=, >=, <>, ?
3. & (AND)
4. | (OR)
The hierarchy causes the apparently identical expressions below to produce
different results:
Expression 1:
Expression 2:
35
40
10
35
40
Expression 2:
192
Features for
Increasing
Performance
This section describes special features designed to increase the run time
performance of NAVISION. We will present the following features:
The DBMS Cache
The COMMIT Cache
The Command Buffer
Application 1
Application 2
Application 3
Network
DBMS
DB Request Handler
Cache
Database
: Data flow
193
changes), the data in the cache modified during the transaction will be written
to the disk; the cache is said to be flushed.
The DBMS Cache always holds the most recently used data. The cache
automatically replaces parts of the cache memory with relevant parts of the
database.
The size of the cache has great impact on the performance. Two simple rules
apply when determining the size of the cache:
The more memory you assign to your cache, the more efficient the cache
will be (Of course there are no reason to assign more memory to the cache
than the total size of your database).
The size of the cache should not exceed the amount of physical memory
available on your system, as this may cause your operating system to
swap the cache memory out and in from disk; this will slow down the
overall speed of your NAVISION system tremendously.
Nevertheless, there are upper limits for the DBMS Cache size. The maximum
cache size in DOS and OS/2 versions of NAVISION is 6400 KB, while the
maximum size in UNIX versions are 32000 KB.
194
DBMS
Commit Cache
Separate
Process
Separate
Process
Separate
Process
c:
d:
f:
Database
195
Two commands are executed for each record in the table, but each record will
only cause one request to be sent to the DBMS, as the dbDELREC command
will be stored in the Command buffer until the dbFINDREC command is
executed.
The system automatically turns off the Command buffer when you activate
the AL debugger, as unexpected results may occur if it is used when
debugging. Nevertheless, if an error occurs at run time, and you enter the AL
editor in order to find a potential bug in your code, a special situation may
occur as the Command buffer always is active when an application is
executed. Consider the following example:
(1)
(2)
(3)
(4)
dbINSREC(CustomerA);
dbINSREC(CustomerB);
dbINSREC(CustomerC);
IF dbFINDREC(CustomerX) THEN ...
If CustomerB inserted in line (2) already exists in the database, a run time
error will occur. But the error will not occur before the IF statement in line
(4) is executed, as the commands in line (1), (2) and (3) are stored in the
Command buffer until the dbFINDREC command must return a value in
order for the execution to continue.
When you enter the AL editor, the cursor will be placed on line (4), and the
following error message will be shown:
The Customer B already exists.
This might seem to be a rather strange error message for line (4), but the
explanation is simple: the error message applies to line (2), but the error was
not encountered by the DBMS until line (4) was executed by your
application.
196
Appendix
Sum Fields
A sum field is a fundamental feature which forms the basis for the concept of
Calculated fields. Sum fields permits fast calculation of sums of numeric
columns in tables, even in tables with many thousands of records.
A sum field is associated to a key; each key can have at most 10 sumfields.
During database design, a field of the Decimal No. type can be associated to
a key as a sumfield. This tells the DBMS to create and maintain a structure
which contains the accumulated sum of values in a column. When a new
current key is selected, any sum fields associated with it, becomes accessible.
Figure 26 illustrates a table where the Amount field (column) is defined as a
sum field in the AccountNo + Date key. This enables the DBMS to
automatically maintain the accumulated sum of the column. Every time a
change is made to a field in the column, the accumulated values are updated.
Figure 26. A table with
sumfields, and the same
table when a calculation
filter is applied
Amount
Accumulated
sum
AccountNo
Date
50000
01-01-96
100
60100
50000
01-02-96
200
90300
50020
01-04-96
300
210600
50020
01-25-96
400
1000
50040
02-01-96
500
300
1500
(sum field)
Calculation Filter:
=50020
Used in computation
for the Calculated field:
300
50020
01-04-96
300
600
50020
01-25-96
400
1000
To the right of the table is shown an area in the database where the
Sum Fields
197
accumulated sums for the Amount column are kept. In figure 26, the third
field in the column holding the accumulated sum, contains the value 600,
because the first three Amount values are 100, 200 and 300, respectively - a
total of 600. The fourth virtual field contains 1000, the total of the first four
values in the Amount column, and so on. If the table contained a second
sumfield, its values would be accumulated in the same way.
What advantages do sumfields offer? They allow fast calculation of sums of
columns to be performed and shown via Calculated fields. Let us say you
want the sum of all the values in the Amount fields. In a conventional
system, the DBMS is forced to access every record and add each value in the
field Amount, a very time-consuming operation in a database with thousands
of records. Here, the DBMS only needs to access the final field, where the
sum of all the Amount fields is always maintained.
Operations with sumfields are equally fast when calculation filters are
applied. The second table in figure 26 shows a group of records selected by
using a calculation filter on the AccountNo. field. Two records fulfils the
conditions of the calculation filter. Only two accesses are needed to sum
Amount for these records: one acces to get the accumulated sum associated
to the last record before the specified range, and one access to get the
accumulated sum associated to the last record in the specified range .
The value 300 is subtracted from the value 1000 to produce the correct sum
(700). No matter the number of records in the selected range, the system will
always only need to perform two accesses in order to compute the desired
sum.
The time used to maintain the accumulated sum for sum fields is negligible
due to a special index structure used in the DBMS.
198