Using Caché SQL
Language Elements
[Home] [Back] [Next]
InterSystems: The power behind what matters   

Caché SQL supports the following language elements:

Commands and Keywords
A Caché SQL command (also known as an SQL statement) begins with a keyword followed by one or more arguments. Some of these arguments may be clauses or functions, identified by their own keywords.
Caché SQL keywords include command names, function names, predicate condition names, data type names, field constraints, optimization options, and special variables. They also include the AND, OR, and NOT logical operators, the NULL column value indicator, and ODBC function constructs such as {d dateval} and {fn CONCAT(str1,str2)}.
Caché SQL literals have the following syntax:
literal ::= 
     number | string-literal

number ::=  

digit ::=

string-literal ::= 
     std-string-literal | ObjectScript-empty-string

std-string-literal ::= 
     ' {std-character-representation} '

std-character-representation ::=
     nonquote-character | quote-symbol

quote-symbol ::= 

ObjectScript-empty-string ::= 
A literal is a series of characters that represents an actual (literal) value. It can be either a number or a character string.
The empty string is a literal string; it is represented by two single-quote characters (''). NULL is not a literal value; it represents the absence of any value. For further details, see the NULL and the Empty String section of this chapter.
In Embedded SQL, a few character sequences that begin with ## are not permitted within a string literal, as described in Literal Values in the “Using Embedded SQL” chapter. This restriction does not apply to other invocations of SQL, such as Dynamic SQL.
String Delimiters
You can use either single quote (') characters or the double quote (") characters as string delimiters. The single-quote (') character is the preferred delimiter. The use of the double-quote character (") is supported for SQL compatibility, but this use is discouraged because of potential conflict with the delimited identifier standard.
To specify the character used as the delimiter as a literal character within the string, specify a pair of these characters.
The double vertical bar (||) is the preferred SQL concatenation operator. It can be used to concatenate two numbers, two character strings, or a number and a character string.
The underscore (_) is provided as an SQL concatenation operator for ObjectScript compatibility. This concatenation operator can only be used to concatenate two character strings.
If the two operands are both character strings, and both strings have the same collation type, the resulting concatenated string has that collation type. In all other cases, the result of concatenation is of collation type EXACT.
NULL and the Empty String
Use the NULL keyword to indicate that a value is not specified. NULL is always the preferred way in SQL to indicate that a data value is unspecified or nonexistent for any reason.
The SQL zero-length string (empty string) is specified by two single quote characters. The empty string ('') is not the same thing as NULL. An empty string is a defined value, a string that contains no characters, a string of length 0. A zero-length string is represented internally by the non-display character $CHAR(0).
The SQL zero-length string is not recommended for use as a field input value or a field default value. Use NULL to represent the absence of a data value.
The SQL zero-length string should be avoided in SQL coding. However, because many SQL operations delete trailing blank spaces, a data value that contains only whitespace characters (spaces and tabs) may result in an SQL zero-length string.
Note that different SQL length functions return different values: LENGTH, CHAR_LENGTH, and DATALENGTH return SQL lengths. $LENGTH returns ObjectScript representation length. See The Length of NULL below. LENGTH does not count trailing blank spaces; all other length functions count trailing blank spaces.
The SQL zero-length string, like all SQL strings, can also be represented using double quote characters (""); this usage should be avoided because of potential conflict with SQL delimited identifiers.
NULL Processing
The NOT NULL data constraint requires that a field must receive a data value; specifying NULL rather than a value is not permitted. This constraint does not prevent the use of an empty string value. For further details, refer to the CREATE TABLE command.
The IS NULL predicate in the WHERE or HAVING clause of a SELECT statement selects NULL values; it does not select empty string values.
The IFNULL function evaluates a field value and returns the value specified in its second argument if the field evaluates to NULL. It does not treat an empty string value as a non-NULL value.
The COALESCE function selects the first non-NULL value from supplied data. It treats empty string values as non-NULL.
When the CONCAT function or the concatenate operator (||) concatenate a string and a NULL, the result is NULL. This is shown in the following example:
SELECT {fn CONCAT('fred',NULL)} AS FuncCatNull,
       'fred'||NULL AS OpCatNull 
The AVG, COUNT, MAX, MIN, and SUM aggregate functions ignore NULL values when performing their operations. (COUNT * counts all rows, because there cannot be a record with NULL values for all fields.) The DISTINCT keyword of the SELECT statement includes NULL in its operation; if there are NULL values for the specified field, DISTINCT returns one NULL row.
The AVG, COUNT, and MIN, aggregate functions are affected by empty string values. The MIN function considers an empty string to be the minimum value, even when there are rows that have a value of zero. The MAX and SUM aggregate functions are not affected by empty string values.
NULL in Expressions
Supplying NULL as an operand to most SQL functions returns NULL.
Any SQL arithmetic operation that has NULL as an operand returns a value of NULL. Thus, 7+NULL=NULL. This includes the binary operations addition (+), subtraction (-), multiplication (*), division (/), integer division (\), and modulo (#), and the unary sign operators plus (+) and minus (-).
An empty string specified in an arithmetic operation is treated as a value of 0 (zero). Division (/), integer division (\), or modulo (#) by empty string (6/'') results in a <DIVIDE> error.
The Length of NULL
Within SQL, the length of a NULL is undefined (it returns <null>). The length of an empty string, however, is defined as length zero. This is shown in the following example:
       LENGTH('') AS EmpStrLen 
As shown in this example, the SQL LENGTH function returns the SQL lengths.
You can convert an SQL zero-length string to a NULL by using the ASCII function, as shown in the following example:
       LENGTH({fn ASCII('')}) As NullLen
However, certain Caché extensions to standard SQL treat the length of NULL and the empty string differently. The $LENGTH function returns the Caché internal representation of these values: NULL is represented as a defined value with length 0, the SQL empty string is represented as a string of length 0. This functionality is compatible with ObjectScript.
$LENGTH('') AS EmpStrLenZero, 
$LENGTH('a') AS StrLenOne, 
$LENGTH(CHAR(0)) AS CharLenZero  
Another place where the internal representation of these values is significant is in the %STRING, %SQLSTRING and %SQLUPPER functions, which append a blank space to a value. Since a NULL truly has no value, appending a blank to it creates a string of length 1. But an empty string does have a character value, so appending a blank to it creates a string of length 2. This is shown in the following example:
CHAR_LENGTH(%STRING('')) AS EmpStrAndBlankLenTwo
Note that this example uses CHAR_LENGTH, not LENGTH. Because the LENGTH function removes trailing blanks, LENGTH(%STRING(NULL)) returns a length of 0; LENGTH(%STRING('')) returns a length of 2, because %STRING appends a leading blank, not a trailing blank.
ObjectScript and SQL
When an SQL NULL is output to ObjectScript, it is represented by an ObjectScript empty string (""), a string of length zero.
When an SQL zero-length string data is output to ObjectScript, it is represented by a string containing $CHAR(0), a string of length 1.
   &sql(SELECT NULL,''
        INTO :a,:b)
  WRITE !,"NULL length: ",$LENGTH(a)         // returns 0
  WRITE !,"empty string length: ",$LENGTH(b) // returns 1
In ObjectScript, the absence of a value is usually indicated by an empty string (""). When this value is passed into embedded SQL, it is treated as a NULL value, as shown in the following example:
  SET x=""
  SET myquery="SELECT NULL As NoVal,:x As EmpStr"
  SET tStatement=##class(%SQL.Statement).%New()
  SET qStatus=tStatement.%Prepare(myquery)
  IF qStatus'=1 {WRITE "%Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT}
  SET rset=tStatement.%Execute()
  WHILE rset.%Next() {
    WRITE "NoVal:",rset.%Get("NoVal")," length ",$LENGTH(rset.%Get("NoVal")),!      // length 0
    WRITE "EmpStr:",rset.%Get("EmpStr")," length ",$LENGTH(rset.%Get("EmpStr")),!   // length 0
  WRITE "End of data"
If you specify an input host variable that is not defined, embedded SQL treats its value as NULL.
When passing a NULL or empty string value out from embedded SQL to ObjectScript, the NULL is translated to a string of length 0, and the empty string is translated to a string of length 1. This is shown in the following example:
        INTO :a,:b)
  WRITE !,"The length of NULL is: ",$LENGTH(a)         // length 0
  WRITE !,"The length of empty string is: ",$LENGTH(b) // length 1
In the following example, the SQL empty string with an appended blank is passed out as string of length 2:
   &sql(SELECT %SQLUPPER('')
        INTO :y
        FROM Sample.Person)
  WRITE !,"SQL empty string length: ",$LENGTH(y)
Arithmetic Operators and Functions
Caché SQL supports the following arithmetic operators:
+ Addition operator. For example, 17+7 equals 24.
Subtraction operator. For example, 17-7 equals 10. Note that a pair of these characters is the Caché SQL comment indicator. Therefore, to specify two or more subtraction operators or negative signs you must use either spaces or parentheses. For example, 17- -7 or 17-(-7) equals 24.
* Multiplication operator. For example, 17*7 equals 119.
/ Division operator. For example, 17/7 equals 2.428571428571428571.
\ Integer division operator. For example, 17\7 equals 2.
# Modulo operator. For example, 17 # 7 equals 3. Note that because the # character is also a valid identifier character, to use it as a modulo operator you should specify it separated from its operands by spaces before and after.
E Exponentiation (scientific notation) operator. Can be uppercase or lowercase. For example, 7E3 equals 7000. A too-large exponent results in an SQLCODE -7 “Exponent out of range” error. For example, 1E309 or 7E308.
() Grouping operators. Used to nest arithmetic operations. Unless parentheses are used, the execution sequence of arithmetic operations in Caché SQL is strict left-to-right order. For example, 17+7*2 equals 48, but 17+(7*2) equals 31.
|| Concatenate operator. For example, 17||7 equals 177.
Arithmetic operations are performed on numbers in their canonical form.
For numbers of any data type, the data type for the result of an addition (+), subtraction (-), multiplication (*), or division (/, \, or #) operation is NUMERIC, unless one or both of the arguments is of data type DOUBLE; in that case, the data type of the result is DOUBLE. For example, adding two fields of data type INTEGER results in a value of data type NUMERIC. Concatenating two numbers of any data type results in a VARCHAR string.
In Dynamic SQL you can use SQL column metadata to determine the data type of a result set field. For further details on numeric data types refer to SQL Data Types.
Operator Precedence
The SQL-92 standard is imprecise with regard to operator precedence; assumptions on this matter differ amongst SQL implementations.
Precision and Scale
The precision (maximum number of digits present in the number) for a NUMERIC result for:
The scale (maximum number of fractional digits) for a NUMERIC result for:
For further details on data types, precision, and scale, refer to SQL Data Types.
Arithmetic and Trigonometric Functions
Caché SQL supports the following arithmetic functions:
ABS Returns the absolute value of a numeric expression.
CEILING Returns the smallest integer greater than or equal to a numeric expression.
EXP Returns the log exponential (base e) value of a numeric expression.
FLOOR Returns the largest integer less than or equal to a numeric expression.
GREATEST Returns the largest number from a comma-separated list of numbers.
ISNUMERIC Returns a boolean code specifying whether an expression is a valid number.
LEAST Returns the smallest number from a comma-separated list of numbers.
LOG Returns the natural log (base e) value of a numeric expression.
LOG10 Returns the base–10 log value of a numeric expression.
MOD Returns the modulus value (remainder) of a division operation. Same as the # operator.
PI Returns the numeric constant pi.
POWER Returns the value of a numeric expression raised to a specified power.
ROUND Returns a numeric expression rounded (or truncated) to a specified number of digits.
SIGN Returns a numeric code specifying whether a numeric expression evaluates to positive, zero, or negative.
SQRT Returns the square root of a numeric expression.
SQUARE Returns the square of a numeric expression.
TRUNCATE Returns a numeric expression truncated to a specified number of digits.
Caché SQL supports the following trigonometric functions.
ACOS Returns the arc-cosine of a numeric expression.
ASIN Returns the arc-sine of a numeric expression.
ATAN Returns the arc-tangent of a numeric expression.
COS Returns the cosine of a numeric expression.
COT Returns the cotangent of a numeric expression.
SIN Returns the sine of a numeric expression.
TAN Returns the tangent of a numeric expression.
DEGREES Converts radians to degrees.
RADIANS Converts degrees to radians.
Relational Operators
A conditional expression evaluates to a boolean value. A conditional expression can use the following relational operators:
= Equals operator.
Does not equal operator. The two syntactical forms are functionally identical.
< Less than operator.
> Greater than operator.
<= Less than or equal to operator.
>= Greater than or equal to operator.
When comparing a table field value, these equality operators use the field’s default collation. The Caché default is not case-sensitive. When comparing two literals, the comparison is case-sensitive.
Equality operators (equals, does not equal) should be avoided when comparing floating point numbers. Floating point numbers (data types classes %Library.Decimal and %Library.Double) are stored as binary values, not as fixed-precision numbers. During conversion, rounding operations may result in two floating point numbers that are intended to represent the same number not being precisely equal. Use less-than / greater-than tests to determine if two floating point numbers are “the same” to the desired degree of precision.
Caché SQL also supports the Contains and Follows comparison operators:
[ Contains operator. Returns all values that contain the operand, including values equal to the operator. This operator uses EXACT (case-sensitive) collation. The inverse is NOT[.
] Follows operator. Returns all values that follow the operator in collation sequence. Excludes the operand value itself. This operator uses the field’s default collation. The Caché default is not case-sensitive. The inverse is NOT].
Logical Operators
SQL logical operators are used in condition expressions that are evaluated as being True or False. These conditional expressions are used in the SELECT statement WHERE and HAVING clauses, in the CASE statement WHEN clauses, in the JOIN statement ON clause, and the CREATE TRIGGER statement WHEN clause.
NOT Unary Operator
You can use the NOT unary logical operator to specify the logical inverse of a condition, as shown in the following examples:
SELECT Name,Age FROM Sample.Person
SELECT Name,Age FROM Sample.Person
You can place the NOT operator before the condition (as shown above). Or you can place NOT immediately before a single-character operator; for example, NOT<, NOT[, and so forth. Note that there must be no space between NOT and the single-character operator it inverts.
AND and OR Operators
You can use the AND and OR logical operators between two operands in a series of two or more conditions. These logical operators can be specified by keyword or symbol:
OR !
Spaces are not required (though recommended for readability) between a symbol operator and its operand. Spaces are required before and after a keyword operator.
These logical operators can be used with the NOT unary logical operator, such as the following: WHERE Age<65 & NOT Age=21.
The following two examples use logical operators to schedule an assessment based on age. People between the ages of 20 and 40 are assessed every three years, people from 40 to 64 are assessed every two years, and those 65 and over are assessed every year. The examples give identical results; the first example uses keywords, the second uses symbols:
SELECT Name,Age FROM Sample.Person
WHERE Age>20
      AND Age<40 AND (Age # 3)=0 
      OR Age>=40 AND (Age # 2)=0 
      OR Age>=65
SELECT Name,Age FROM Sample.Person
WHERE Age>20
      & Age<40 & (Age # 3)=0 
      ! Age>=40 & (Age # 2)=0 
      ! Age>=65
Logical operators can be grouped using parentheses. This establishes a grouping level; evaluation proceeds from the lowest grouping level to the highest. In the first of the following examples, the AND condition is applied only to the second OR condition. It returns persons of any age from MA, and persons with age less than 25 from NY:
SELECT Name,Age,Home_State FROM Sample.Person
WHERE Home_State='MA' OR Home_State='NY' AND Age < 25
Using parentheses to group conditions gives a different result. The following example returns persons from MA or NY whose age is less than 25:
SELECT Name,Age,Home_State FROM Sample.Person
WHERE (Home_State='MA' OR Home_State='NY') AND Age < 25
Caché SQL supports both single-line comments and multi-line comments. Comment text can contain any characters or strings, except, of course, the character(s) that indicate the end of the comment.
Using Embedded SQL marker syntax (&sql<marker>(...)<reversemarker>) imposes a restriction on the contents of SQL comments. If you are using marker syntax, the comments within the SQL code may not contain the character sequence )<reversemarker>”. For further details, refer to The &sql Directive in the “Using Embedded SQL” chapter of this manual.
You can use the preparse() method to return an SQL DML statement stripped of comments. The preparse() method also replaces each query argument with a ? character and returns a %List structure of these arguments. The preparse() method in the following example returns a parsed version of the query, stripped of single-line and multi-line comments and whitespace:
  SET myq=4
  SET myq(1)="SELECT TOP ? Name /* first name */, Age "
  SET myq(2)="   FROM Sample.MyTable -- this is the FROM clause"
  SET myq(3)="   WHERE  /* various conditions "
  SET myq(4)="apply */ Name='Fred' AND Age > 21 -- end of query"
  DO ##class(%SQL.Statement).preparse(.myq,.stripped,.args)
  WRITE stripped,!
Single Line Comments
A single-line comment is specified by a two-hyphen prefix. A comment can be on a separate line, or can appear on the same line as SQL code. When a comment follows SQL code on the same line, at least one blank space must separate the code from the double-hyphen comment operator. A comment can contain any characters, including hyphens, asterisks, and slashes. The comment continues to the end of the line.
The following example contains multiple single-line comments:
-- This is a simple SQL query
-- containing -- (double hyphen) comments
SELECT TOP 10 Name,Age, -- Two columns selected
Home_State -- A third column
FROM Sample.Person -- Table name
-- Other clauses follow
WHERE Age > 20 AND -- Comment within a clause
Age < 40
ORDER BY Age,  -- Comment within a clause
-- End of query
Multiple Line Comments
A multiple-line comment is specified by a /* opening delimiter and a */ closing delimiter. A comment can appear on one or more separate lines, or can begin or end on the same line as SQL code. A comment delimiter should be separated from SQL code by at least one blank space. A comment can contain any characters, including hyphens, asterisks and slashes, with the obvious exception of the */ character pair.
The following example contains several multiple-line comments:
/* This is 
   a simple 
   SQL query. */
SELECT TOP 10 Name,Age /* Two fields selected */
FROM Sample.Person  /* Other clauses 
could appear here */ ORDER BY Age
/* End of query */
When commenting out Embedded SQL code, always begin the comment before the &sql directive or within the parentheses. The following example correctly comments out two the Embedded SQL code blocks:
   SET a="default name",b="default age"
   WRITE "(not) Invoking Embedded SQL",!
   /*&sql(SELECT Name INTO :a FROM Sample.Person) */
   WRITE "The name is ",a,!
   WRITE "Invoking Embedded SQL (as a no-op)",!
   &sql(/* SELECT Age INTO :b FROM Sample.Person */)
   WRITE "The age is ",b
SQL Code Retained as Comments
Embedded SQL statements can be retained as comments in the .INT code version of routines. This is done by setting a configuration option as follows:
Set this option to “Yes” to retain SQL statements as comments in the .INT code version of a routine. Setting this option to “Yes” also lists all non-% variables used by the SQL statements in the comment text. These listed variables should also be listed in the ObjectScript procedure’s PUBLIC variable list and re-initialized using the NEW command. For further details, refer to Host Variables in the “Embedded SQL” chapter of this manual.

Send us comments on this page
Copyright © 1997-2019 InterSystems Corporation, Cambridge, MA