Use a WHILE statement is used to control flow. It allows code to be executed repeatedly as long as the WHILE condition is true. Optionally, you may use the WHILE statement with DO and END WHILE.
Note You cannot use a mixed syntax for the WHILE statement. You may use either WHILE with DO and END WHILE, or only WHILE.
If you are using multiple statements with a WHILE condition, you must use BEGIN and END to indicate the beginning and ending of the statement blocks.
Syntax
[ label-name : ] WHILE proc-search-condition [ DO ] [ proc-stmt [; proc-stmt ] ]... [ END WHILE ][ label-name ]
Remarks
A WHILE statement can have a beginning label, in which case it is called a labeled WHILE statement.
Examples
The following example increments the variable vInteger by 1 until it reaches a value of 10, when the loop ends.
Global variables are prefaced with two at signs, @@. All global variables are variables per connection. Each database connection has its own @@IDENTITY, @@BIGIDENTITY, @@ROWCOUNT, and @@SPID values. The value of @@VERSION is information about the version of the engine that executes the statement where it is used.
@@IDENTITY and @@BIGIDENTITY
Either of these variables returns its most recently inserted column value. The value is a signed integer value. The initial value is NULL.
The variable can refer to only a single column. If the target table includes more than one IDENTITY column, the value of this variable refers to the IDENTITY column serving as the table primary key. If no such column exists, then the value of this variable refers to the first IDENTITY column in the table.
If the most recent insert was to a table without an IDENTITY column, then the value of @@IDENTITY is set to NULL.
For BIGIDENTITY values, use @@BIGIDENTITY. For SMALLIDENTITY values, use @@IDENTITY.
Examples
SELECT @@IDENTITY
Returns NULL if no records have been inserted in the current connection, otherwise returns the IDENTITY column value of the most recently inserted row.
SELECT * FROM t1 WHERE @@IDENTITY = 12
Returns the most recently inserted row if it has an IDENTITY column value of 12. Otherwise, returns no rows.
INSERT INTO t1(c2) VALUES (@@IDENTITY)
Inserts the IDENTITY value of the last row inserted into column C2 of the new row.
UPDATE t1 SET t1.c1 = (SELECT @@IDENTITY) WHERE t1.c1 = @@IDENTITY + 10
Updates column C1 with the IDENTITY value of the last row inserted, if the value of C1 is 10 greater than the IDENTITY column value of the last row inserted.
UPDATE t1 SET t1.c1 = (SELECT NULL FROM t2 WHERE t2.c1 = @@IDENTITY)
Updates column C1 with the value NULL if the value of C1 equals the IDENTITY column value of the last row inserted.
The example below creates a stored procedure and calls it. The procedure sets variable V1 equal to the sum of the input value and the IDENTITY column value of the last row updated. The procedure then deletes rows from the table anywhere column C1 equals V1. The procedure then prints a message stating how many rows were deleted.
This variable returns the number of rows that were affected by the most recent operation in the current connection. The value is an unsigned integer. The initial value is zero.
The @@ROWCOUNT variable is valid only when used after an INSERT, UPDATE, or DELETE statement.
Examples
SELECT @@ROWCOUNT
Returns zero if no records were affected by the previous operation in the current connection, otherwise returns the number of rows affected by the previous operation.
CREATE TABLE t1 (c1 INTEGER, c2 INTEGER)
INSERT INTO t1 (c1, c2) VALUES (100,200)
INSERT INTO t1(c1, c2) VALUES (300, @@ROWCOUNT)
SELECT @@ROWCOUNT
Results:
1 (in @@ROWCOUNT variable)
In line four, the @@ROWCOUNT variable has the value of 1 because the previous INSERT operation affected one row.
Also see the example for @@IDENTITY.
@@SESSIONID
This variable returns an eight-byte integer value that identifies the connection to a Zen server engine, reporting engine, or workgroup engine. The integer is a combination of a time value and an incremental counter. This variable can be used to identify uniquely each Zen connection.
@@SESSIONID requires a connection to the database engine to return a value. If the connection to the database engine is lost, the variable cannot return an identifier.
Example
SELECT @@SESSIONID
The example returns an integer identifier such as 26552653137523.
@@SPID
This variable, the server process identifier, returns the identifier integer value of the system thread for the Zen connection.
If the connection to the database engine is lost, the SPID variable cannot return an identifier. Instead, the statement returns an error with a SqlState of 08S01.
Example
SELECT @@SPID
The example returns an integer identifier, such as 402.
@@VERSION
SQL statements that use this variable return a value based on the Zen server engine, reporting engine, or workgroup engine to which the session is connected.
•For a Zen server, the value is the version of the local engine and the bitness, name, and version of the local operating system.
•For Zen Client Reporting Engine, it is the version of the local reporting engine and the bitness, name, and version of the local operating system.
•For Zen Client, it is the version of the engine on the remote Zen server to which the client is connected and the bitness, name, and version of the operating system where the server is running.
•For Zen Workgroup Engine, the value is the version of the local engine and the bitness, name, and version of the local operating system.
Example
SELECT @@version
The example returns text information resembling the following:
Actian Zen - 14.10.020.000 (x86_64) Server Engine - Copyright (C) Actian Corporation 2019 on (64-bit) Windows NT 6.2 7d
Other Characteristics
This topic describes other characteristics of the SQL grammar. It is divided into the following sections:
When Zen must generate a temporary table in order to process a given query, it creates the file in a location determined in one of the following ways:
•If you have manually added the string key value PervasiveEngineOptions\TempFileDirectory to ODBC.INI, Zen uses the path set for TempFileDirectory. The proper location for both 32- and 64-bit Zen installations on Windows is the registry location HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI. For Linux, macOS, and Raspbian, the ODBC.INI file is located in /usr/local/actianzen/etc.
•If you have set the temporary file directory property for a Zen engine using ZenCC or bcfg, Zen uses this location. For more information, see Temporary Files in Advanced Operations Guide.
•If you have not used either of the first two options listed here, then Zen checks for the file location using the following sequence on Window platforms:
1 The path specified by the TMP environment variable
2 The path specified by the TEMP environment variable
3 The path specified by the USERPROFILE environment variable
4 The Windows directory
For example, if the TMP environment variable is not defined, Zen uses the path specified in the TEMP environment variable, and so on.
On Linux and macOS distributions, Zen uses the current directory for the server process. No attempt is made to use TMP.
Zen deletes all temporary files used to process a query after the query is finished. If the query is a SELECT statement, then the temporary files exist as long as the result set is active, meaning until the result set is freed by the calling application.
When Are Temporary Files Created?
Zen uses three types of temporary files: in-memory, on-disk, and Btrieve (MicroKernel Engine).
In-Memory Temporary File
In-memory temporary files are used for the following circumstances:
•Forward-only cursor
•Number of bytes in the temporary file is less than 250,000.
•SELECT statements with ORDER BY, GROUP BY, or DISTINCT that do not use an index, that have no BLOB or CLOB in the ORDER BY, GROUP BY, or DISTINCT, and that have no BLOB or CLOB in selection list with UNION.
On-Disk Temporary File
On-disk temporary files are used for the following circumstances:
•Forward-only cursor
•Number of bytes in the temporary file is greater than 250,000.
•SELECT statements with ORDER BY, GROUP BY, or DISTINCT that do not use an index, that have no BLOB or CLOB in the ORDER BY, GROUP BY, or DISTINCT, and that have no BLOB or CLOB in selection list with UNION.
Btrieve Temporary File
Btrieve temporary files are used for the following circumstances:
•Forward-only cursor with BLOB or CLOB in ORDER BY, GROUP BY, or DISTINCT or with BLOB or CLOB in selection list with UNION
•Dynamic or static cursor with UNION queries or SELECT statements with ORDER BY, GROUP BY, or DISTINCT that do not use an index.
Zen does not create a Btrieve temporary file for each base table in a static cursor SELECT query. Instead, each base table is opened by using the MicroKernel to reserve pages in the file as a static representation of the file. Any change made through a static cursor cannot be seen by that cursor.
Working with NULL Values
Zen interprets a NULL as an unknown value. Thus, if you try to compare two NULL values, they will compare as not equal.
An expression that evaluates to WHERE NULL=NULL returns FALSE.
Working with Binary Data
Consider the following scenario: you insert the literal value '1' into a BINARY(4) column named c1, in table t1. Next, you enter the statement, SELECT * FROM t1 WHERE c1='1'.
The engine can retrieve data using the same binary format as was used to input the data. That is, the SELECT example above works properly and returns the value, 0x01000000, even though there is no literal match.
Note The engine always adds a zero (‘0’) to the front of odd-digit binary values that are inserted. For example, if you insert the value '010', then the value '0x00100000' is stored in the data file.
Currently, Zen does not support suffix 0x to denote binary constants. Binary constants are a string of hexadecimal numbers enclosed by single quotation marks.
This behavior is the same as for Microsoft SQL Server.
Creating Indexes
The maximum column size for indexable VARCHAR columns is 254 bytes if the column does not allow Null values and 253 bytes if the column is nullable.
The maximum column size for CHAR columns is 255 bytes if the column does not allow Null values and 254 bytes if the column is nullable.
The maximum column size for indexable NVARCHAR columns is NVARCHAR(126). This limit applies to both nullable and not-null columns. The NVARCHAR size is specified in UCS-2 character units.
The maximum column size for NCHAR columns is NCHAR(127). This limit applies to both nullable and not-null columns. The NCHAR size is specified in UCS-2 character units.
The maximum Btrieve key size is 255. When a column is nullable and indexed a segmented key is created with 1 byte for the null indicator and a maximum 254 bytes from the column indexed. VARCHAR columns differ from CHAR columns in that either length byte (Btrieve lstring) or a zero terminating byte (Btrieve zstring) are reserved, increasing the effective storage by 1 byte. NVARCHAR (Btrieve wzstring) columns differ from NCHAR columns in that a zero terminating character is reserved, increasing the effective storage by 2 bytes.
Comma as Decimal Separator
Many locales use a comma to separate whole numbers from fractional numbers within a floating point numeric field. For example, they would use 1,5 instead of 1.5 to represent the number one-and-one-half.
Zen supports both the period and the comma as decimal separators. Zen accepts input values using the period or the comma, based on the regional settings for the operating system. By default, the database engine displays values using the period.
Note When the decimal separator is not a period, numbers appearing in SQL statements must be enclosed in quotes.
For output and display only, the session-level command SET DECIMALSEPARATORCOMMA can be used to specify output (for example, SELECT results) that uses the comma as the decimal separator. This command has no effect on data entry or storage.
Client-Server Considerations
Support for the comma as decimal separator is based on the locale setting in the operating system. Both the client operating system and the server operating system have a locale setting. The expected behavior varies according to both settings.
•If either the server or client locale setting uses the comma as decimal separator, then Zen accepts both period-separated values and quoted comma-separated values.
•If neither the server nor the client locale setting uses the comma decimal separator, then Zen does not accept comma-separated values.
Changing the Locale Setting
Decimal separator information can be retrieved or changed only for a machine running a Windows operating system. The decimal setting for Linux and macOS cannot be configured, and it is set to a period. If you have a Linux and macOS server engine and you want to use a comma as decimal separator, you must ensure that all your client computers are set to a locale that uses the decimal separator.
To change the regional settings on a Windows operating system, access the settings from the Control Panel. Stop and restart Zen services after your change to enable the database engine to use the setting.
Examples
Example A - Server locale uses a comma for decimal separator
Client locale uses a comma as decimal separator:
CREATE TABLE t1 (c1 DECIMAL(10,3), c2 DOUBLE)
INSERT INTO t1 VALUES (10.123, 1.232)
INSERT INTO t1 VALUES ('10,123', '1.232')
SELECT * FROM t1 WHERE c1 = 10.123
SELECT * FROM t1 FROM c1 = '10,123'
The above two SELECT statements, if executed from the client, return:
10.123, 1.232
10.123, 1.232
SET DECIMALSEPARATORCOMMA=ON
SELECT * FROM t1 FROM c1 = '10,123'
The above SELECT statement, if executed from the client after setting the decimal separator, returns:
10,123, 1,232
Client locale uses period as decimal separator, and these statements are issued from a new connection (meaning default behavior for SET DECIMALSEPARATORCOMMA):
CREATE TABLE t1 (c1 DECIMAL(10,3), c2 DOUBLE)
INSERT INTO t1 VALUES (10.123, 1.232)
INSERT INTO t1 VALUES ('10,123', '1.232')
SELECT * FROM t1 WHERE c1 = 10.123
SELECT * FROM t1 WHERE c1 = '10,123'
The above two SELECT statements, if executed from the client, return:
10.123, 1.232
10.123, 1.232
Example B - Server locale uses the period for decimal separator
Client locale uses comma as decimal separator:
Same as client using comma in Example A.
Client locale uses period as decimal separator:
CREATE TABLE t1 (c1 DECIMAL(10,3), c2 DOUBLE)
INSERT INTO t1 VALUES (10.123, 1.232)
INSERT INTO t1 VALUES ('10,123', '1,232') -- error in assignment
SELECT * FROM t1 WHERE c1 = 10.123
SELECT * FROM t1 WHERE c1 = '10,123' -- error in assignment
The first select statement above, if executed from the client, returns:
10.123, 1.232
SET DECIMALSEPARATORCOMMA=ON
SELECT * FROM t1 FROM c1 = 10.123
The above SELECT statement, if executed after setting the decimal separator for display, returns: