Easysoft ODBC-SQI SQL Engine User Guide - Technical Reference

ODBC and SQL conformance

This section sets out the ODBC and SQL conformance for the Easysoft ODBC-SQI SQL Engine, listing the ODBC API function calls and the SQL components that are supported.

Appendix Guide

Introduction

Refer to this section if you are using the Easysoft ODBC-SQI SQL Engine in conjunction with (for example):

This section does not describe ODBC API calls or the different components of SQL.

If you require more detailed information about implementing ODBC and SQL, the following publications may be of interest to you:

For more general information about ODBC and SQL, please refer to the many reference books available on these subjects.

ODBC API Function Calls

ODBC API function calls can be used by programmers to enable applications to connect to data in databases.

By including an SQL statement as an argument of an ODBC function call, programmers can also develop features that allow end users to manipulate data in their databases.


NB

The Purpose column in the following tables is taken from the Microsoft ODBC 3.0 Programmer's Reference Volumes 1 and 2 (Microsoft Press, 1997).


The Easysoft ODBC-SQI SQL Engine provides the following ODBC API function calls:



Function ODBC Conformance Purpose
SQLAllocHandle Core Obtains an environment, connection, statement or descriptor handle.
SQLBindCol Core Assigns storage for a result column and specifies the data type.
SQLBindParameter Core Assigns storage for a parameter in an SQL statement.
SQLBrowseConnect Level 1 Returns successive levels of connection attributes and valid attribute values. When a value has been specified for each connection attribute, connects to the data source.
SQLCancel Core Cancels an SQL statement.
SQLCloseCursor Core Closes a cursor that has been opened on a statement handle.
SQLColAttribute Core Describes attributes of a column in the results set.
SQLColumnPrivileges Level 2 Returns a list of columns and associated privileges for one or more tables.
SQLColumns Core Returns the list of column names in specified tables.
SQLConnect Core Connects to a specific driver by data source name, user ID and password.
SQLCopyDesc Core Copies descriptor information from one descriptor handle to another.
SQLDescribeCol Core Describes a column in the result set.
SQLDescribeParam Level 2 Returns the description for a specific parameter in a statement.
SQLDisconnect Core Closes the connection.
SQLDriverConnect Core Connects to a specific driver by connection string or requests that the Driver Manager and driver display connection dialog boxes for the user.
SQLEndTran Core Commits or rolls back a transaction.
SQLExecDirect Core Executes a statement.
SQLExecute Core Executes a prepared statement.
SQLFetch Core Returns multiple result rows.
SQLFetchScroll Core Returns scrollable result rows.
SQLForeignKeys Level 2 Returns a list of column names that make up foreign keys, if they exist for a specified table.
SQLFreeHandle Core Releases an environment, connection, statement or descriptor handle.
SQLFreeStmt Core Ends statement processing, discards pending results, and, optimally, frees all resources associated with the statement handle.
SQLGetConnectAttr Core Returns the value of a connection attribute
SQLGetCursorName Core Returns the cursor name associated with a statement handle.
SQLGetData Core Returns part or all of one column of one row of a result set (useful for long data values).
SQLGetDescField Core Returns the value of a single descriptor field.
SQLGetDescRec Core Returns the values of multiple descriptor fields
SQLGetDiagField Core Returns additional diagnostic information (a single field of the diagnostic data structure).
SQLGetDiagRec Core Returns additional diagnostic information (multiple fields of the diagnostic data structure).
SQLGetEnvAttr Core Returns the value of an environment variable.
SQLGetFunctions Core Returns supported driver functions
SQLGetInfo Core Returns information about a specific driver and data source
SQLGetStmtAttr Core Returns the value of a statement attribute.
SQLGetTypeInfo Core Returns information about supported data types.
SQLMoreResults Level 1 Determines whether there are more result sets available and, if so, initializes processing for the next result set.
SQLNativeSql Core Returns the text of an SQL statement as translated by the driver.
SQLNumParams Core Returns the number of parameters in a statement.
SQLNumResultCols Core Returns the number of columns in the result set.
SQLParamData Core Used in conjunction with SQLPutData to supply parameter data at execution time. (Useful for long data values.)
SQLPrepare Core Prepares and SQL statement for later execution.
SQLPrimaryKeys Level 1 Returns the list of column names that make up the primary key for a table.
SQLProcedureColumns Level 1 Returns the list of input and output parameters, as well as the columns that make up the result set for the specified procedures.
SQLProcedures Level 1 Returns the list of procedure names stored in a specific data source.
SQLPutData Core Sends part or all of a data value for a parameter. (Useful for long data values.)
SQLRowCount Core Retuns the number of rows affected by an insert, update or delete request.
SQLSetConnectAttr Core Sets a connection attribute
SQLSetCursorName Core Specifies a cursor name.
SQLSetDescField Core Sets a single descriptor field.
SQLSetDescRec Core Sets multiple descriptor fields.
SQLSetEnvAttr Core Sets an environment variable.
SQLSetPos Level 1 Positions a cursor within a fetched block of data, and allows an application to refresh data in the rowset, or update or delete data in the result set.
SQLSetStmtAttr Core Sets a statement attribute.
SQLSpecialColumns Core Returns information about the optimal set of columns that uniquely identifies a row in a specified table, or the columns that are automatically updated when any value in the row is updated by a transaction.
SQLStatistics Core Returns statistics about a single table and the list of indexes associated with the table.
SQLTablePrivileges Level 2 Returns a list of tables and the privileges associated with each table.
SQLTables Core Returns the list of table names stored in a specific data source.

Figure 19: ODBC API functions

The following functions are provided by the ODBC Driver Manager:



Function ODBC Conformance Purpose
SQLDataSources Core Returns the list of available data sources
SQLDrivers Core Returns the list of installed drivers and their attributes

Figure 20: ODBC Driver Manager functions

The following functions are provided by the Setup DLL:



Function ODBC Conformance Purpose
SQLConfigDriver Core Loads the driver-specific setup DLL.
SQLConfigDSN Core Adds, modifies or deletes a data source.

Figure 21: ODBC Setup DLL functions

The following functions have been superceded, but are still supported by theEasysoft ODBC-SQI SQL Engine:



Function ODBC Conformance Purpose
SQLAllocConnect Core ODBC 2.x function superseded by SQLAllocHandle
SQLAllocEnv Core ODBC 2.x function superseded by SQLAllocHandle
SQLError Core ODBC 2.x function superseded by SQLGetDiagRec
SQLGetConnectOption Core ODBC 2.x function superseded by SQLGetConnectAttr
SQLSetParam Core ODBC 1 function, superseded by SQLBindParameter

Figure 22: Superceeded functions

The following function is currently not supported, but are planned for future release:



Function ODBC Conformance Purpose
SQLBulkOperations Level 1 Performs bulk insertions and bulk bookmark operations, including update, delete and fetch by bookmark.

Figure 23: Unsuppported functions

Statement Types

The Easysoft ODBC-SQI SQL Engine supports the following SQL statements:



SQL Minimum Grammar Additional
CREATE TABLE ALTER TABLE

CREATE INDEX

CREATE VIEW
DELETE STATEMENT (searched) DELETE (positioned)
DROP TABLE DROP INDEX

DROP VIEW
INSERT
SELECT SELECT FOR UPDATE
UPDATE (searched) UPDATE (positioned)

GRANT

REVOKE

COMMIT

ROLLBACK

Figure 24: Supported statements


NB

Some of these commands (e.g. COMMIT and ROLLBACK) are only available if they are supported by the back-end DBMS. Also, unless you are using link names, you can only use the CREATE, ALTER and DROP commands (the SQL Data Definition Language commands) if the virtual data source has only one DBMS at the 'back-end'.


Table References

The Table reference list in a SELECT query can contain all or any of:

Constructs

The Easysoft ODBC-SQI SQL Engine supports the following constructs:

INNER JOIN

LEFT OUTER JOIN

RIGHT OUTER JOIN

FULL OUTER JOIN

NATURAL JOIN

UNION

UNION ALL

Correlated and non-correlated subqueries

TRIM, SUBSTRING, CHARACTER_LENGTH, BIT_LENGTH, OCTET_LENGTH and POSITION value functions

The SQL-92 CAST function and the ODBC CONVERT function for conversion between compatible data types.

When using JOINs, note that:

SQL

SELECT * from x LEFT OUTER JOIN y ON x.a = y.a

ODBC

SELECT * from {oj x LEFT OUTER y ON x.a = y.a }

Predicates

The Easysoft ODBC-SQI SQL Engine supports the following predicates:



Predicate Example Syntax
Comparisons, = <> < <= > >= WHERE x = y
BETWEEN WHERE a BETWEEN x AND y
LIKE / NOT LIKE WHERE a LIKE '%green%'
NULL / NOT NULL WHERE a is NULL
IN value_list WHERE aIN ( value1, value2, value3 )
IN sub_query WHERE a IN ( SELECT x FROM y )
Quantified comparison WHERE a = SOME ( SELECT x FROM y )
EXISTS subquery WHERE EXISTS ( SELECT x FROM y )
CASE, NULLIF, COALESCE Refer to an SQL reference for example syntax of these conditional expressions.

Figure 25: Supported predicates

Subqueries in predicates can be correlated or non-correlated:

Correlated

SELECT a FROM b WHERE c = ALL ( SELECT x FROM y WHERE z = a )

Non-correlated

SELECT a FROM b WHERE c = ALL ( SELECT x FROM y WHERE z = 12 )

Scalar Functions

The Easysoft ODBC-SQI SQL Engine provides all the functions required by ODBC and also functions from SQL92.

Functions can be specified in SQL92 or ODBC format.

For example:

SQL

SELECT CURRENT_DATE, EXTRACT( YEAR FROM

Employee.data_of_birth ) FROM Employee

ODBC

SELECT {fn CURRENT_DATE()}, {fn EXTRACT( YEAR

FROM Employee.data_of_birth )} FROM Employee


NB

The Description column in the following tables is taken from the Microsoft ODBC 3.0 Programmer's Reference.


The following functions are supported by the Easysoft ODBC-SQI SQL Engine:

String Functions



Function Description
ASCII(string_exp) Returns the ASCII code value of the leftmost character of string_exp as an integer.
BIT_LENGTH(string_exp) Returns the length in bits of the string expression.
CHAR(code) Returns the character that has the ASCII code value specified by code. The value of code should be between 0 and 255, otherwise the return value is data source-dependent.
CHAR_LENGTH(string_exp) Returns the length in characters of the string expression, if the string expression is of a character data type, otherwise returns the length in bytes of the string expression (the smallest integer not less than the number of bits divided by 8). This is the same function as CHARACTER_LENGTH.
CHARACTER_LENGTH See CHAR_LENGTH
CONCAT(string_exp1, string_exp2) Returns a character string that is the result of concatenating string_exp2 to string_exp1. The resulting string is DBMS-dependent.
DIFFERENCE(string_exp1, string_exp2) Returns an integer value that indicates the difference between the values returned by the SOUNDEX function for string_exp1 and string_exp2.
INSERT(string_exp1,
start, length, string_exp2
)
Returns a character string where length characters have been deleted from string_exp1 beginning at start and where string_exp2 has been inserted into string_exp, beginning at start.
LCASE(string_exp) Returns a string equal to that in string_exp with all uppercase characters converted to lowercase.
LEFT(string_exp, count) Returns the leftmost count characters of string_exp.
LENGTH(string_exp) Returns the number of characters in string_exp, excluding trailing blanks.
LOCATE(string_exp1, string_exp2[,start]) Returns the starting position of the first occurrence of string_exp1 within string_exp2. The search for the first occurrence of string_exp1 begins with the first character position in string_exp2 unless the optional argument, start, is specified. If start is specified, the search begins with the character position indicated by the value of start. The first character position in string_exp2 is indicated by the value1. If string_exp1 is not found within string_exp2, the value 0 is returned.
LTRIM(string_exp) Returns the characters of string_exp, with leading blanks removed.
OCTET_LENGTH(string_exp) Returns the length in bytes of the string expression. The result is the smallest integer not less than the number of bits divided by 8.
POSITION(char_exp IN char_exp) Returns the position of the first character expression in the second character expression. The result is an exact numeric with an implementation-defined precision and a scale of 0.
REPEAT(string_exp, count) Returns a character string composed of string_exp repeated count times.
REPLACE(string_exp1, string_exp2, string_exp3) Search string_exp1 for occurrences of string_exp2 and replace with string_exp3.
RIGHT(string_exp, count) Returns the rightmost count characters of string_exp.
RTRIM(string_exp) Returns the characters of string_exp with trailing blanks removed.
SOUNDEX(string_exp) Returns a data source-dependent character string representing the sound of the words in string_exp.
SPACE(count) Returns a character string consisting of count spaces.
SUBSTRING(string_exp, start, length) Returns a character string that is derived from string_exp beginning at the character position specified by start for length characters.
TRIM This is an SQL92 version of the ODBC LTRIM/RTRIM functions.
UCASE(string_exp) Returns a string equal to that in string_exp with all lowercase characters converted to uppercase.

Figure 26: Supported string functions

Numeric Functions



Function Description
ABS(numeric_exp) Returns the absolute value of numeric_exp.
ACOS(float_exp) Returns the arccosine of float_exp as an angle, expressed in radians.
ASIN(float_exp) Returns the arcsine of float_exp as an angle, expressed in radians.
ATAN(float_exp) Returns the arctangent of float_exp as an angle, expressed in radians.
ATAN2(float_exp1, float_exp2) Returns the arctangent of the x and y coordinates, specified by float_exp1 and float_exp2 respectively, as an angle expressed in radians.
CEILING(numeric_exp) Returns the smallest integer greater than or equal to numeric_exp.
COS(float_exp) Returns the cosine of float_exp where float_exp is an angle expressed in radians.
COT(float_exp) Returns the cotangent of float_exp where float_exp is an angle expressed in radians.
DEGREES(numeric_exp) Returns the number of degrees converted from numeric_exp radians.
EXP(float_exp) Returns the exponential value of float_exp.
FLOOR(numeric_exp) Returns the largest integer less than or equal to numeric_exp.
LOG(float_exp) Returns the natural logarithm of float_exp.
LOG10(float_exp) Returns the base 10 logarithm of float_exp.
MOD(integer_exp1, integer_exp2) Returns the remainder (modulus) of integer_exp1 divided by integer_exp2.
PI() Returns the constant value of pi as a floating point value.
POWER(numeric_exp, integer_exp) Returns the value of numeric_exp to the power of integer_exp.
RADIANS(numeric_exp) Returns the number of radians converted from numeric_exp degrees.
RAND([integer_exp]) Returns a random floating point value using integer_exp as the optional seed value.
ROUND(numeric_exp, integer_exp) Returns numeric_exp rounded to integer_exp places right of the decimal point. If integer_exp is negative, numeric_exp is rounded to |integer_exp| places to the left of the decimal point.
SIGN(numeric_exp) Returns an indicator of the sign of numeric_exp. If numeric_exp is less than zero, -1 is returned. If numeric_exp equals aero, 0 is returned. If numeric_exp is greater than zero, 1 is returned.
SIN(float_exp) Returns the sine of float_exp, where float_exp is an angle expressed in radians.
SQRT(float_exp) Returns the square root of float_exp.
TAN(float_exp) Returns the tangent of float_exp where float_exp is an angle expressed in radians.
TRUNCATE(numeric_exp, integer_exp) Returns numeric_exp truncated to integer_exp places right of the decimal point. If integer_exp is negative, numeric_exp is truncated to |integer_exp| places to the left of the decimal point.

Figure 27: Supported numeric functions

Time, Date and Interval Functions



Function Description
CURRENT_DATE() Returns the current date.
CURRENT_TIME[(time-precision)] Returns the current local time. The time-precision argument determines the seconds precision of the returned value.
CURRENT_TIMESTAMP[(timestamp-precision)] Returns the current local date and local time as a timestamp value. The timestamp-precision argument determines the seconds precision of the returned timestamp.
CURDATE() Returns the current date.
CURTIME() Returns the current local time.
DAYNAME(date_exp) Returns a character string containing the data source-specific name of the day for the day portion of date_exp.
DAYOFMONTH(date_exp) Returns the day of the month based on the month field in date_exp as an integer value in the range 1-31.
DAYOFWEEK(date_exp) Returns the day of the week based on the week field in date_exp as an integer value in the range of 1-7 where 1 represents Sunday.
DAYOFYEAR(date_exp) Returns the day of the year based on the year field in date_exp as an integer value in the range of 1-366.
EXTRACT(extract-field FROM extract-source) Returns the extract-field portion of the extract-source. The extract-source argument is a datetime or interval expression. The extract-field argument can be one of the YEAR, MONTH, DAY, HOUR, MINUTE, SECOND keywords.The precision of the returned value is implementation-defined. The scale is 0 unless SECOND is specified, in which case the scale is not less that the fractional seconds precision of the extract-source field.
HOUR(time_exp) Returns the hour based on the hour field in time_exp as an integer value in the range of 0-23.
MINUTE(time_exp) Returns the minute based on the minute field in time_exp as an integer value in the range of 0-59.
MONTH(date_exp) Returns the month based on the month field in date_exp as an integer value in the range 1-12.
MONTHNAME
(date_exp)
Returns a character string containing the data source-specific name of the month for the month portion of date_exp.
NOW() Returns the current date and time as a timestamp value.
QUARTER(date_exp) Returns the quarter in date_exp as an integer value in the range of 1-4.
SECOND(time_exp) Returns the second based on the second field in time_exp as an integer value in the range of 0-59.
TIMESTAMPADD
(interval, integer_exp, timestamp_exp)
Returns the timestamp calculated by adding integer_exp intervals of type interval to timestamp_exp. Valid values of interval are the following keywords: SQL_TSI_FRAC_SECOND, SQL_TSI_SECOND, SQL_TSI_MINUTE, SQL_TSI_HOUR, SQL_TSI_DAY, SQL_TSI_WEEK, SQL_TSI_MONTH, SQL_TSI_QUARTER, SQL_TSI_YEAR where fractional seconds are expressed in billionths of a second.If time_stamp is a time value and interval specifies days, weeks, months, quarters, or years, the date portion of timestamp_exp is set to the current date before calculating the resulting timestamp.If timestamp_exp is a date value and interval specifies fractional seconds, seconds, minutes, or hours, the time portion of timestamp_exp is set to 0 before calculating the resulting timestamp.An application determines which intervals a data source supports by calling SQLGetInfo with the SQL_TIMEDATE_ADD_INTERVALS option.
TIMESTAMPDIFF
(interval, timestamp_exp1, timestamp_exp2)
Returns the integer number of intervals of type interval by which timestamp_exp2 is greater than timestamp_exp1. The keywords SQL_TSI_FRAC_SECOND, SQL_TSI_SECOND, SQL_TSI_MINUTE, SQL_TSI_HOUR, SQL_TSI_DAY, SQL_TSI_WEEK, SQL_TSI_MONTH, SQL_TSI_QUARTER, SQL_TSI_YEAR are valid values of interval, where fractional seconds are expressed in billionths of a second.If either timestamp expression is a time value and interval specifies days, weeks, months, quarters, or years, the date portion of that timestamp is set to the current date before calculating the difference between timestamps.If either timestamp expression is a date value and interval specifies fractional seconds, seconds, minutes, or hours, the time portion of that timestamp is set to 0 before calculating the difference between timestamps.An application determines which intervals a data source supports by calling SQLGetInfo with the SQL_TIMEDATE_DIFF_INTERVALS option.
WEEK(date_exp) Returns the week of the year based on the week field in date_exp as an integer value in the range of 1-53.
YEAR(date_exp) Returns the year based on the year field in date_exp as an integer value. The range is data source-dependent.

Figure 28: Supported time, date and interval functions

System Functions



Function Description
DATABASE() Returns the name of the database corresponding to the connection handle.
IFNULL(exp, value) If exp is null, value is returned. If exp is not null, exp is returned. The possible data type or types of value must be compatible with the data type of exp.
USER() Returns the user name in the DBMS. This may be different from the login name.
CURRENT_USER This is an SQL92 version of the ODBC USER function.

Figure 29: Supported system functions

Set Functions

The Easysoft ODBC-SQI SQL Engine supports the following set functions:

COUNT

AVG

MIN

MAX

SUM

For example, the following query would return the maximum price from the PRODUCT table:

SELECT MAX (PRICE) FROM PRODUCT


NB

If your ODBC application does not return any results when using a set function, try inserting an AS clause into your query. For example:

SELECT MAX (PRICE) AS COST FROM PRODUCT


Data Types

The following SQL data types are supported, as described in Appendix D of the Microsoft ODBC 3.0 Programmer's Reference.

SQL_CHAR

SQL_VARCHAR

SQL_LONGVARCHAR

SQL_DECIMAL

SQL_NUMERIC

SQL_SMALLINT

SQL_INTEGER

SQL_REAL

SQL_FLOAT

SQL_DOUBLE

SQL_BIT

SQL_TINYINT

SQL_BIGINT

SQL_BINARY

SQL_VARBINARY

SQL_LONGVARBINARY

SQL_TYPE_DATE

SQL_TYPE_TIME

SQL_TYPE_TIMESTAMP

SQL_INTERVALS (all types)

Literals

All SQL92 and ODBC literals are supported and can be specified in either form. For example:

SQL92

DATE '1999-01-02', INTERVAL '10-2' YEAR TO MONTH

ODBC

{d '1999-01-02'}, {INTERVAL '10-2' YEAR TO MONTH}

Data Type Conversions

The Easysoft ODBC-SQI SQL Engine supports both the SQL92 CAST function and the ODBC CONVERT FUNCTION for conversion between compatible data types.

The following table shows how compatible data types are converted.


NB

For conciseness, the SQL_ prefix has been omitted from all data types in the Supported data type conversions table.


Figure 30: Supported data type conversions

Numeric Data Types

The following table shows which numeric data type is adopted when arithmetic operations (+-*/) are performed on two numerics of different data types.

Figure 31: Adopted numeric data types

String Concatenation

A string data type (SQL_CHAR, SQL_VARCHAR) can be concatenated with another string data type using the concat operator (|| or +).

If either of the operands are of variable length, then the result will also be of varying length.

Interval Operations

When adding or subtracting an integral numeric value to or from an interval value where the interval value is a single field, the interval type does not change.

For example, if you have the interval value 3 DAY and you add 6, the result will be 9 DAY - the interval is not recalculated as a number of weeks and days.

Optimization

The Easysoft ODBC-SQI SQL Engine performs several optimizations to improve performance, including query and table ordering optimizations:

Query Optimization

The WHERE clause of a query will be rewritten into a form that allows more efficient processing of data. For example the query:

SELECT * FROM x WHERE ( a = 10 or b = 20 ) and c = 30

will be rewritten as the equivalent:

SELECT * FROM x WHERE a = 10 and c = 30

UNION

SELECT * FROM x WHERE b = 20 and c = 30 and a <> 10

Table Optimization

In cases where indexes are present on tables, the Easysoft ODBC-SQI SQL Engine will, if necessary, rearrange the sequence in which tables are processed in order to enable an index to be used.

This will minimize the number of reads and positions executed and lead to huge increases in performance.

Informational Schema

The Easysoft ODBC-SQI SQL Engine exposes an informational schema view of the tables supplied by the target data sources, which consists of the following system tables:

INFO_SCHEMA.CHARACTER_SETS

INFO_SCHEMA.COLLATIONS

INFO_SCHEMA.COLUMN_PRIVILEGES

INFO_SCHEMA.COLUMNS

INFO_SCHEMA.INDEXES

INFO_SCHEMA.SCHEMATA

INFO_SCHEMA.SERVER_INFO

INFO_SCHEMA.SQL_LANGUAGES

INFO_SCHEMA.TABLE_PRIVILEGES

INFO_SCHEMA.TABLES

INFO_SCHEMA.USAGE_PRIVILEGES

INFO_SCHEMA.VIEWS

To get information about all the tables in the data source, use:

SELECT * FROM INFO_SCHEMA.TABLES

To get information about all the columns in the data source, use:

SELECT * FROM INFO_SCHEMA_COLUMNS

To get information about all the columns in a specific table, use:

SELECT * FROM INFO_SCHEMA_COLUMNS WHERE

TABLE_NAME='table_name'

ODBC Features

Cursors

The Easysoft ODBC-SQI SQL Engine supports FORWARD ONLY, STATIC and KEYSET cursors (but not DYNAMIC cursors).

The Easysoft ODBC-SQI SQL Engine supports:

Asynchronous Operation

The ODBC Programmer's Reference lists the functions that can be executed asynchronously. The Easysoft ODBC-SQI SQL Engine supports asynchronous operation for these functions although SQL_STILL_EXECUTING will not be returned for a function which happens immediately because of an earlier function. For example, SQLGetData will always return immediately whereas SQLExecute may not.

For example, the following query would probably not execute immediately:

SELECT * FROM EMPLOYEE

WHERE SALARY > 20000

ORDER BY AGE

whereas this query probably would:

SELECT * FROM EMPLOYEE WHERE UNIQUE_ID = 101