Summary:
See also: Records, Arrays, Data Types, Constants, User Types.
A variable is a program element that can hold volatile data. The following list summarizes variables usage:
A variable contains volatile information of a specific data type.
[PUBLIC|PRIVATE] DEFINE variable-definition [,...]
where variable-definition is:
identifier [,...] { datatype | LIKE
[dbname:]tabname.colname }
A variable is a named location in memory that can store a single value, or an ordered set of values. Variables can be global to the program, module-specific, or local to a function.
You cannot reference any program variable before it has been declared by the DEFINE statement.
By default, module-specific variables are private; They cannot be used by an other module of the program. In order to improve code reusability by data encapsulation, we recommend you to keep module variables private, except if you want to share large data (like arrays) between modules. To make a module variable public, add the PUBLIC keyword before DEFINE. When a module variable is declared as public, it can be referenced by another module by using the IMPORT instruction.
Note that when defining variables with the LIKE clause, the data types are taken from the schema file during compilation. Make sure that the schema file of the development database corresponds to the production database; otherwise the variables defined in the compiled version of your modules will not match the table structures of the production database.
To write well-structured programs, it is recommended that you not use global variables. If you need persistent data storage during a program's execution, use variables local to the module and give access to them with functions.
The DEFINE statement declares the identifier of one or more variables. There are two important things to know about these identifiers:
The context of its declaration in the source module determines where a variable can be referenced by other language statements, and when storage is allocated for the variable in memory. The DEFINE statement can appear in three contexts:
A compile-time error occurs if you declare the same name for two variables that have the same scope. You can, however, declare the same name for variables that differ in their scope. For example, you can use the same identifier to reference different local variables in different program blocks.
You can also declare the same name for two or more variables whose scopes of reference are different but overlapping. Within their intersection, the compiler interprets the identifier as referencing the variable whose scope is smaller, and therefore the variable whose scope is a superset of the other is not visible.
If a local variable has the same identifier as a global variable, then the local variable takes precedence inside the program block in which it is declared. Elsewhere in the program, the identifier references the global variable.
A module variable can have the same name as a global variable that is declared in a different module. Within the module where the module variable is declared, the module variable takes precedence over the global variable. Statements in that module cannot reference the global variable.
A module variable cannot have the same name as a global variable that is declared in the same module.
If a local variable has the same identifier as a module variable, then the local identifier takes precedence inside the program block in which it is declared. Elsewhere in the same source-code module, the name references the module variable.
You can use the RECORD or ARRAY keywords to declare a structured variable.
For example:
01MAIN02DEFINE myarr ARRAY[100] OF RECORD03id INTEGER,04name VARCHAR(100)05END RECORD06LET myarr[2].id = 5207END MAIN
For more detail, refer to Arrays and Records.
You can use the LIKE keyword to declare a variable that has the same data type as a specified column in a database schema.
For example:
01SCHEMA stores02DEFINE cname LIKE customer.cust_name03MAIN05DEFINE cr RECORD LIKE customer.*06END MAIN
The following rules apply when using the LIKE keyword:
To understand how to generate database schema files with the schema extractor tool, refer to Database Schema Files
Variables can be defined with a user type:
01TYPE custlist DYNAMIC ARRAY OF RECORD LIKE customer.*02MAIN03DEFINE cl custlist04END MAIN
The scope of a user type can be global, local to a module or local to a function. Variables can be defined with a user type defined in the same scope, or in a higher level of scope.
After a variable is defined, it is automatically initialized by the runtime system to a default value based on the data type. The following table shows all possible default values that variables can take:
| Data Type | Default Value |
| CHAR | NULL |
| VARCHAR | NULL |
| STRING | NULL |
| INTEGER | Zero |
| SMALLINT | Zero |
| FLOAT | Zero |
| SMALLFLOAT | Zero |
| DECIMAL | NULL |
| MONEY | NULL |
| DATE | 1899-12-31 (= Zero in number of days) |
| DATETIME | NULL |
| INTERVAL | NULL |
| TEXT | NULL, See LOCATE |
| BYTE | NULL, See LOCATE |
The INITIALIZE instruction assigns NULL or default values to variables.
INITIALIZE target [,...] { TO NULL | LIKE {table.*|table.column} }
The TO NULL clause initializes the variable to NULL.
When initializing a static array TO NULL, all elements will be initialized to NULL. When initializing a dynamic array TO NULL, all elements will be removed (i.e. the dynamic array is cleared).
The LIKE clause initializes the variable to the default value defined in the database schema validation file. This clause works only by specifying the table.column schema entry corresponding to the variable.
To initialize a complete record, you can use the star to reference all members:
01 INITIALIZE record.* LIKE table.*
You cannot initialize variables defined with a complex data type (like TEXT
or BYTE) to a non-NULL value.
01DATABASE stores02MAIN03DEFINE cr RECORD LIKE customer.*04DEFINE a1 ARRAY[100] OF INTEGER05INITIALIZE cr.cust_name TO NULL06INITIALIZE cr.cust_name THRU cr.cust_address TO NULL07INITIALIZE cr.* LIKE customer.*08INITIALIZE a1 TO NULL09INITIALIZE a1[10] TO NULL10END MAIN
The VALIDATE instructions checks a variable value according to schema validation rules.
VALIDATE target [,...] LIKE {table.*|table.column}
If the value does not match any value defined in the INCLUDE attribute of the corresponding column, the runtime system raises an exception with error code -1321.
The LIKE clause requires the IBM Informix upscol utility to populate the syscolval table. See the database schema files for more details. Informix only!You cannot initialize variables defined with a complex data type (like TEXT or BYTE) to a non-NULL value.
01DATABASE stores02MAIN03DEFINE cname LIKE customer.cust_name04LET cname = "aaa"05VALIDATE cname LIKE customer.cust_name06END MAIN
The THRU keyword can be used to specify a range of members of a record.
record.first-member [ THRU | THROUGH ] record.last-member
The THRU keyword can be used in several instructions such as INITIALIZE, VALIDATE, LOCATE.
01DATABASE stores02MAIN03DEFINE cust LIKE customer.*04INITIALIZE cust.cust_name THRU customer.cust_address TO NULL05END MAIN
The LET statement assigns a value to a variable, or a set of values to a record.
LET target = expression [,...]
When specifying a comma-separated list of expressions for the right operand, the LET statement concatenates all expressions together. Unlike the || operator, if an expression in the comma-separated list evaluates to NULL, the concatenation result will not be null, except if all expressions to the right of the equal sign are null.
The runtime system applies data type conversion rules if the data type of expression does not correspond to the data type of target.
You can use most of the built-in functions and character string operators like CLIPPED or USING within the LET statement.
target can be record followed by dot + star (record.*) to reference all record members of the record. In this case, the right operand must also be a record using this notation (see example below).Note that variables defined with a complex data type (like TEXT or BYTE) can only be assigned to NULL.
For more details, refer to the assignment operator.
01DATABASE stores02MAIN03DEFINE c1, c2 RECORD LIKE customer.*04LET c1.* = c2.*05END MAIN
The LOCATE statement specifies where to store data of TEXT and BYTE variables.
LOCATE target [,...] IN MEMORY
LOCATE target [,...] IN FILE filename
LOCATE target [,...] IN FILE
Note that you cannot use a large object variable if the data storage location is not defined.
The first syntax using the IN MEMORY clause specifies that the large object data must be located in memory. The second syntax using the IN FILE filename clause specifies that the large object data must be located in a specific file. The third syntax using the IN FILE clause specifies that the large object data must be located in a temporary file.
When using a temporary file, the location of the temporary file can be defined with the DBTEMP environment variable. By default, the runtime system will use /tmp on UNIX and %TMP% or %TEMP% on Windows. The temporary files are automatically dropped by the runtime system when the program terminates.
On UNIX systems, the permission on the temporary file can be controlled by umask.
You can free the resources allocated to the large object variable with the FREE instruction.01MAIN02DEFINE ctext1, ctext2 TEXT03DATABASE stock04LOCATE ctext1 IN MEMORY05LOCATE ctext2 IN FILE "/tmp/data1.txt"06CREATE TABLE lobtab ( key INTEGER, col1 TEXT, col2 TEXT )06INSERT INTO lobtab VALUES ( 123, ctext1, ctext2 )07END MAIN
The FREE statement releases resources allocated to the specified variable.
FREE target
If the TEXT/BYTE variable was located in memory, the runtime system releases the memory. If the variable was located in a file, the runtime system deletes the file.
For variables declared in a local scope of reference, the resources are automatically freed by the runtime system when returning from the function or MAIN block.
After freeing a large object, you must LOCATE the variable again before usage.
01MAIN02DEFINE ctext TEXT03DATABASE stock03LOCATE ctext IN FILE "/tmp/data1.txt"04SELECT col1 INTO ctext FROM lobtab WHERE key=12305FREE ctext06END MAIN
01FUNCTION myfunc( )02DEFINE i INTEGER03FOR i=1 TO 1004DISPLAY i05END FOR06END FUNCTION
01DEFINE s VARCHAR(100)0203FUNCTION myfunc( )04DEFINE i INTEGER05FOR i=1 TO 1006LET s = "item #" || i07END FOR08END FUNCTION
File "myglobs.4gl":
01GLOBALS02DEFINE userid CHAR(20)03DEFINE extime DATETIME YEAR TO SECOND04END GLOBALS
File "mylib.4gl":
01GLOBALS "myglobs.4gl"0203DEFINE s VARCHAR(100)0405FUNCTION myfunc( )06DEFINE i INTEGER07DISPLAY "User Id = " || userid08FOR i=1 TO1009LET s = "item #" || i10END FOR11END FUNCTION
File "mymain.4gl":
01GLOBALS "myglobs.4gl"0203MAIN04LET userid = fgl_getenv("LOGNAME")05LET extime = CURRENT YEAR TO SECOND06CALL myfunc()07END MAIN