4D v13.4

Accessing the 4D SQL Engine

Home

 
4D v13.4
Accessing the 4D SQL Engine

Accessing the 4D SQL Engine  


 

The 4D built-in SQL engine can be called in three different ways:

  • Using the QUERY BY SQL command. Simply pass the WHERE clause of an SQL SELECT statement as a query parameter. Example:
 QUERY BY SQL([OFFICES];"SALES > 100")
  • Using the integrated SQL commands of 4D, found in the “SQL” theme (SQL SET PARAMETER, SQL EXECUTE, etc.). These commands can work with an ODBC data source or the 4D SQL engine of the current database.
  • Using the standard Method editor of 4D. SQL statements can be written directly in the standard 4D Method editor. You simply need to insert the SQL query between the tags: Begin SQL and End SQL. The code placed between these tags will not be parsed by the 4D interpreter and will be exe-cuted by the SQL engine (or by another engine, if set by the SQL LOGIN command).

It is possible to reference any type of valid 4D expression (variable, field, array, expression...) within WHERE and INTO clauses of SQL expressions. To indicate a 4D reference, you can use either of the following notations:

  • Place the reference between double less-than and greater-than sym-bols as shown here “<<” and “>>”
  • Place a colon “:” in front of the reference.

Examples:

 C_STRING(80;vName)
 vName:=Request("Name:")
 SQL EXECUTE("SELECT age FROM PEOPLE WHERE name=<<vName>>")

or:

 C_STRING(80;vName)
 vName:=Request("Name:")
 Begin SQL
    SELECT age FROM PEOPLE WHERE name= :vName
 End SQL

Note: The use of brackets [] is required when you work with interprocess variables (for example, <<[<>myvar]>> or :[<>myvar]).

In compiled mode, you can use local variable references (beginning with the $ character) in SQL statements under certain conditions:

  • You can use local variables within a Begin SQL / End SQL sequence, except with the EXECUTE IMMEDIATE command;
  • You can use local variables with the SQL EXECUTE command when these variables are used directly in the parameter of the SQL request and not through references.
    For example, the following code works in compiled mode:
     SQL EXECUTE("select * from t1 into :$myvar") // works in compiled mode

    The following code generates an error in compiled mode:
     C_TEXT(tRequest)
     tRequest:="select * from t1 into :$myvar"
     SQL EXECUTE(tRequest// error in compiled mode

The data retrieval in a SELECT statement will be managed either inside Begin SQL/End SQL tags using the INTO clause of the SELECT command or by the "SQL" language commands.

  • In the case of Begin SQL/End SQL tags, you can use the INTO clause in the SQL query and refer to any valid 4D expression (field, variable, array) to get the value:
 Begin SQL
    SELECT ename FROM emp INTO <<[Employees]Name>>
 End SQL
  • With the SQL EXECUTE command, you can also use the additional parameters:
 SQL EXECUTE("SELECT ename FROM emp";[Employees]Name)

The main difference between these two ways of getting data from SQL (Begin SQL/End SQL tags and SQL commands) is that in the first case all the information is sent back to 4D in one step, while in the second case the records must be loaded explicitly using SQL LOAD RECORD.

For example, supposing that in the PEOPLE table there are 100 records:

  • Using 4D generic SQL commands:
 ARRAY INTEGER(aBirthYear;0)
 C_STRING(40;vName)
 vName:="Smith"
 $SQLStm:="SELECT Birth_Year FROM PEOPLE WHERE ename= <<vName>>"
 SQL EXECUTE($SQLStm;aBirthYear)
 While(Not(SQL End selection))
    SQL LOAD RECORD(10)
 End while

Here we have to loop 10 times to retrieve all 100 records. If we want to load all the records in one step we should use:

 ARRAY INTEGER(aBirthYear;0)
 C_STRING(40;vName)
 vName:="Smith"
 Begin SQL
    SELECT Birth_Year FROM PEOPLE WHERE ename= <<vName>> INTO <<aBirthYear>>
 End SQL

In this situation, after the execution of the SELECT statement, the aBirthYear array size becomes 100 and its elements are filled with all the birth years from all 100 records.
If, instead of an array, we want to store the retrieved data in a column (i.e., a 4D field), then 4D will automatically create as many records as necessary to save all the data. In our preceding example, supposing that in the PEOPLE table there are 100 records:

  • Using 4D generic SQL commands:
 C_STRING(40;vName)
 vName:="Smith"
 $SQLStm:="SELECT Birth_Year FROM PEOPLE WHERE ename= <<vName>>”
 SQL EXECUTE($SQLStm;[MYTABLE]Birth_Year)
 While(Not(SQL End selection))
    SQL LOAD RECORD(10)
 End while

Here we have to loop 10 times to retrieve all the 100 records. Every step will create 10 records in the [MYTABLE] table and store each retrieved Birth_Year value from the PEOPLE table in the Birth_Year field.

 C_STRING(40;vName)
 vName:="Smith"
 Begin SQL
    SELECT Birth_Year FROM PEOPLE WHERE ename= <<vName>> INTO <<[MYTABLE]Birth_Year>>
 End SQL

In this case, during the execution of the SELECT statement, there will be 100 records created in the [MYTABLE] table and each Birth_Year field will contain the corresponding data from the PEOPLE table, Birth_Year column.

4D includes a specific automatic functioning (LISTBOX keyword) that can be used for placing data from SELECT queries into a listbox. For more information, please refer to the Design Reference manual.

For optimization purposes, it is preferable to use 4D expressions rather than SQL functions in queries. 4D expressions will be calculated once before the execution of the query whereas SQL functions are evaluated for each record found.

For example, with the following statement:

 SQL EXECUTE("SELECT FullName FROM PEOPLE WHERE FullName=<<vLastName+vFirstName>>")

... the vLastName+vFirstName expression is calculated once, before query execution. With the following statement:

 SQL EXECUTE("SELECT FullName FROM PEOPLE WHERE FullName=CONCAT(<<vLastName>>,<<vFirstName>>)")

... the CONCAT(<<vLastName>>,<<vFirstName>>) function is called for each record of the table; in other words, the expression is evaluated for each record.

 
PROPERTIES 

Product: 4D
Theme: Using SQL in 4D

 
SEE ALSO 

4d_language_reference