Considerations for SQL SELECT Statements
When creating queries and views with SQL SELECT statements, be aware of the following considerations, conventions, and restrictions.
User-Defined Functions in SQL SELECT Statements
Aggregate Functions
Rules Applied to Column Names
UNION Operations
User-Defined Functions in SQL SELECT Statements
You can specify expressions containing user-defined functions for Select_Item in SQL SELECT statements. However, note the following recommendations and restrictions when using user-defined functions in SQL SELECT statements:
Use API and user-defined functions written in C or assembly language instead of performing high-volume manipulations with user-defined functions. The speed at which user-defined functions are executed can limit the speed of operations performed with SQL SELECT.
Assume nothing about the Visual FoxPro input/output (I/O) or table environment when using user-defined functions in SQL SELECT. In general, you do not know which work area is selected, the name of the current table, or even the names of the fields being processed. The value of these variables depends on the precise location in the optimization process where the user-defined function is called.
Do not change the Visual FoxPro I/O or table environment in user-defined functions called in SQL SELECT. In general, the results can be unpredictable.
Use the argument list that is passed to the function when it is called as the only reliable way to pass values to user-defined functions in SQL SELECT.
Understand that "forbidden" manipulations might provide results in one version of Visual FoxPro but might not work in later versions.
Outside of these restrictions, user-defined functions are acceptable in SQL SELECT statements. However, remember that using SQL SELECT in general might slow performance.
For more information about user-defined functions, see User-Defined Procedures and Functions.
Aggregate Functions
You can use aggregate functions with a Select_Item that is a field or an expression involving a field or within a filter condition in the HAVING clause. However, you cannot nest aggregate functions.
The following table lists aggregate functions you can use in SQL SELECT statements.
Aggregate function |
Description |
---|---|
AVG( ) |
Averages a column of numeric data. |
COUNT( ) or CNT( ) |
Counts the number of select items in a column. COUNT(*) counts the number of rows in the query output. |
MIN( ) |
Determines the smallest value of Select_Item in a column. |
MAX( ) |
Determines the largest value of Select_Item in a column. |
SUM( ) |
Totals a column of numeric data. |
The following example creates a query that displays output column names as described:
CLEAR ALL
CLOSE DATABASES
OPEN DATABASE (HOME(2) + 'Data\TestData')
SELECT AVG(TAlias1.order_amt), MIN(TAlias1.order_amt) ;
FROM Orders AS TAlias1
For more information about the aggregate functions you can use with SELECT statements, see MIN( ) Function, MAX( ) Function, and the CALCULATE Command, which contains information about the AVG( ), COUNT( ) or CNT( ), and SUM( ) functions.
Rules Applied to Column Names
The following rules apply when you specify a column with the AS clause to display results in a separate column:
If Select_Item is a field with a unique name, the output column name is the field's name.
If more than one Select_Item has the same name, an underscore (_) and a letter are appended to the end of the output column name.
For example, if a SQL SELECT statement specifies to display the Cust_ID fields for two tables, Customer and Orders, the column names displayed are FieldName_a and FieldName_b, or in this example, Cust_ID_a and Cust_Id_b. The following example creates a query that displays column names as described:
CLEAR ALL CLOSE DATABASES OPEN DATABASE (HOME(2) + 'Data\TestData') SELECT TAlias1.cust_id, TAlias2.cust_id ; FROM Customer AS TAlias1, Orders AS TAlias2 ; WHERE TAlias1.cust_id = TAlias2.cust_id
In a free table, if more than one SQL SELECT item has the same name, and the name has 10 or more characters, the name is truncated to add a number. For example, an output column name such as Department would appear as Department and Departmen2.
If Select_Item is an expression, the output column name appears as Exp_1. Additional output column names appear as Exp_2, Exp_3, and so on. The following example creates a query that displays output column names as described:
CLEAR ALL CLOSE DATABASES OPEN DATABASE (HOME(2) + 'Data\TestData') SELECT TAlias1.postalcode+"-1234", TAlias2.postalcode+"-5678" ; FROM Customer AS TAlias1, Orders AS TAlias2 ; WHERE TAlias1.cust_id = TAlias2.cust_id
If an aggregate function, such as COUNT( ), is used with Select_Item, the output column is named Cnt_FieldName. If more than one Select_Item is used with aggregate functions, the output columns are named AggregateFunction_FieldName with the aggregate function names abbreviated as needed. The following example creates a query that displays output column names as described:
CLEAR ALL CLOSE DATABASES OPEN DATABASE (HOME(2) + 'Data\TestData') SELECT COUNT(order_id), SUM(order_net)FROM Orders
For more information about aggregate functions, see Aggregate Functions.
UNION Operations
When performing UNION operations between SQL SELECT statements using the UNION clause, be aware of the following considerations and restrictions:
All select lists in the statements that are being combined with UNION must have the same number of expressions (column names, arithmetic expressions, aggregate functions, and so on).
Corresponding columns in the result sets that are being combined with UNION, or any subset of columns used in individual queries, must be of the same data type, have an implicit data conversion possible between the two data types, or have an explicit conversion supplied. For example, a UNION between a column of datetime data type and one of binary data type will not work unless an explicit conversion is supplied. However, a UNION will work between a column of money data type and one of int data type, because they can be implicitly converted.
Columns of the xml data type must be equivalent. All columns must be either typed to an XML schema, or untyped. If typed, they must be typed to the same XML schema collection.
The column names in the table that result from UNION are taken from the first individual query in the UNION statement. To refer to a column in the result set by a new name (for example, in an ORDER BY clause), the column must be referred to that way in the first SELECT.
Corresponding result set columns in the individual statements that are being combined with UNION must occur in the same order, because UNION compares the columns one-to-one in the order given in the individual queries.
When different data types are combined in a UNION operation, they are converted by using the rules of data type precedence. In the previous example, the int values are converted to float, because float has a higher precedence than int.
Data Type Conversion and Precedence in UNION Operations
Prior to Visual FoxPro 8.0, you needed to perform explicit data type conversion when performing UNION operations in SQL SELECT statements between two fields of different types. However, Visual FoxPro supports implicit data type conversion for the data types that support it.
Explicit data type conversion requires you to use Visual FoxPro conversion functions, such as CTOD( ), while implicit conversions do not require you to use such conversion functions.
When Visual FoxPro combines two columns of different data types in a UNION operation, the data type with the lower precedence is converted to the data type with the higher precedence. For field properties, NULL takes higher precedence over NOT NULL.
The following table shows all the explicit and implicit data type conversions permitted for Visual FoxPro table data types.
Data type |
Implicit conversion |
Explicit conversion |
---|---|---|
Character |
Character (Binary) |
CTOD( ), CTOT( ), VAL( ), CTOBIN( ) |
Character (Binary) |
|
|
Currency |
|
MTON( ) |
Date |
DateTime |
DTOC( ), DTOS( ), DTOT( ) |
DateTime |
|
TTOC( ), TTOD( ) |
Double |
|
STR( ), VAL( ) |
Float |
Numeric |
NTOM( ), STR( ), INT( ) |
Integer |
Numeric, Float, Double, Currency |
BINTOC( ) |
Logical |
|
|
Numeric |
Float |
NTOM( ), STR( ), INT( ) |
The following table illustrates implicit conversion results from a UNION operation between two fields.
Data type 1 |
Data type 2 |
Data type expected |
---|---|---|
Character (N) |
Character (X) |
Character (MAX(N,X)) |
Character (N) |
Character Binary (X) |
Character Binary (MAX(N,X)) |
Character (N) |
Memo |
Memo |
Character Binary (N) |
Character Binary (X) |
Character Binary (MAX(N,X)) |
Character Binary (N) |
Memo |
Memo |
Currency |
Currency |
Currency |
Date |
Date |
Date |
Date |
DateTime |
DateTime |
DateTime |
DateTime |
DateTime |
Double (N) |
Float (X,Y) |
Float (MAX(MAX(8,Y),2)) |
Double (N) |
Integer |
Double (N) |
Double (N) |
Numeric (X,Y) |
Double (MAX(MAX(8,Y),2)) |
Double (X) |
Double (Y) |
Double (MAX(X,Y)) |
Float (N,M) |
Double (X) |
Float (20, MAX(M,X)) |
Float (N,M) |
Float (X,Y) |
Float (MAX(N,M), MAX(X,Y)) |
Float (N,M) |
Numeric (X,Y) |
Float (MAX (N,X), MAX(M,Y)) |
Integer |
Currency |
Currency |
Integer |
Double (X) |
Double (X) |
Integer |
Float (X,Y) |
Float (MAX(11,X), Y) |
Integer |
Integer |
Integer |
Integer |
Numeric (X,Y) |
Numeric (MAX(11,X), Y) |
Logical |
Logical |
Logical |
Numeric (N,M) |
Double (X) |
Numeric (20, MAX(M,X)) |
Numeric (N,M) |
Float (X,Y) |
Float (MAX(N,X), MAX(M,Y)) |
Numeric (N,M) |
Numeric (X,Y) |
Numeric (MAX(N,X), MAX(M,Y)) |
Varchar (X) |
Character (Y) |
Varchar (MAX(X,Y)) |
Varchar Binary (X) |
Character Binary (Y) |
Varchar Binary (MAX(X,Y)) |
For more information about data types and conversion functions, see Data and Field Types and Data Conversion Functions.