Caché SQL Reference
INSERT
[Back] [Next]
   
Server:docs2
Instance:LATEST
User:UnknownUser
 
-
Go to:
Search:    

Adds a new row (or rows) to a table.
Synopsis
INSERT [%NOFPLAN] [restriction] [INTO] table
          SET column1 = scalar-expression1 {,column2 = scalar-expression2} ...  |
          [ (column1{,column2} ...) ] VALUES (scalar-expression1 {,scalar-expression2} ...)  |
          VALUES :array()  |
          [ (column1{,column2} ...) ] query  |
          DEFAULT VALUES
Arguments
%NOFPLAN Optional — The %NOFPLAN keyword specifies that Caché will ignore the frozen plan (if any) for this operation and generate a new query plan. The frozen plan is retained, but not used. For further details, refer to Frozen Plans in Caché SQL Optimization Guide.
restriction Optional — One or more of the following keywords, separated by spaces: %NOLOCK, %NOCHECK, %NOINDEX, %NOTRIGGER.
table The name of the table or view on which to perform the insert operation. This argument may be a subquery. The INTO keyword is optional.
column Optional — A column name or comma-separated list of column names that correspond in sequence to the supplied list of values. If omitted, the list of values is applied to all columns in column-number order.
scalar-expression A scalar expression or comma-separated list of scalar expressions that supplies the data values for the corresponding column fields.
:array() Embedded SQL only — A dynamic local array of values specified as a host variable. The lowest subscript level of the array must be unspecified. Thus :myupdates(), :myupdates(5,), and :myupdates(1,1,) are all valid specifications.
query A query’s result set that supplies the data values for the corresponding column fields for one or more rows.
Description
The INSERT statement can be used in two ways:
An INSERT statement adds one new row to a table. This operation sets the %ROWCOUNT variable to the number of affected rows (always either 0 or 1).
An INSERT statement combined with a SELECT statement can insert multiple new rows to a table. This technique is commonly used to populate a table with existing data extracted from other tables. This use of INSERT is described in the “INSERT Query Results” section below.
INSERT OR UPDATE
The INSERT OR UPDATE statement is a variant of the INSERT statement that performs both insert and update operations. First it attempts to perform an insert operation. If the insert request fails due to a UNIQUE KEY violation (for the field(s) of some unique key, there exists a row that already has the same value(s) as the row specified for the insert), then it automatically turns into an update request for that row, and INSERT OR UPDATE uses the specified field values to update the existing row.
Table and Column Arguments
You can specify the table argument to insert into a table directly, insert through a view, or insert via a subquery. Inserting through a view is subject to requirements and restrictions, as described in CREATE VIEW. The following is an example of an INSERT using a subquery in place of the table argument:
INSERT INTO (SELECT field1 AS ff1 FROM MyTable) (ff1) VALUES ('test')
The subquery target must be updateable, following the same criteria used to determine if a view's query is updateable. Attempting to INSERT using a view or a subquery that is not updateable generates an SQLCODE -35 error.
If you omit the column list argument, the INSERT assumes all columns are to be inserted, in column number order. If you specify a column list, the individual values must correspond positionally with the column names in the column list.
Privileges
To insert one or more rows of data into a table, you must have either table-level privileges or column-level privileges for that table.
Table-level Privileges
You must have both INSERT and SELECT privileges for the table. Failing to have these privileges results in an SQLCODE -99 error (Privilege Violation). You can determine if the current user has these privileges by invoking the %CHECKPRIV command. You can determine if a specified user has these privileges by invoking the $SYSTEM.SQL.CheckPriv() method. For privilege assignment, refer to the GRANT command.
Table-level privileges are equivalent to (but not identical to) having column-level privileges on all columns of the table.
Column-level Privileges
If you do not have table-level INSERT privilege, you must have column-level INSERT privilege for at least one column of the table. To insert a specified value into a column, you must have column-level INSERT privilege for that column. Only those columns for which you have INSERT privilege receive the value specified in the INSERT command.
If you do not have column-level INSERT privilege for a specified column, Caché SQL inserts the column's default value (if defined), or NULL (if no default is defined). If you do not have INSERT privilege for a column that has no default and is defined as NOT NULL, Caché issues an SQLCODE -99 (Privilege Violation) error at Prepare time.
If the INSERT command specifies fields in a WHERE clause of a result set SELECT, you must have SELECT privilege for those fields if they are not data insert fields, and both SELECT and INSERT privileges for those fields if they are included in the result set.
When a property is defined as ReadOnly, the corresponding table field is also defined as ReadOnly. A ReadOnly field may only be assigned a value using InitialExpression or SqlComputed. Attempting to insert a value for a field for which you have column-level ReadOnly (SELECT or REFERENCES) privilege results in an SQLCODE -138 error: Cannot INSERT/UPDATE a value for a read only field.
You can use %CHECKPRIV to determine if you have the appropriate column-level privileges. See the GRANT command for privilege assignment.
Value Assignment
When inserting a record, you can assign values to specified columns in a variety of ways. All non-specified columns must have a defined default value.
If you specify column names and corresponding data values, you can omit columns for which there is a defined default value. An INSERT can insert a default value for most field data types, including stream fields.
If you do not specify column names, data values must correspond positionally to the defined column list. You must specify a value for every user-specifiable base table column; defined default values cannot be used. (You can, of course, specify an empty string as a column value.)
To list all of the column names and column numbers defined for a specified table, refer to Column Names and Numbers in the “Defining Tables” chapter of Using Caché SQL.
SQLCODE Errors
By default, an INSERT is an all-or-nothing event: either the row (or rows) is inserted completely or not at all. Caché returns a status variable SQLCODE, indicating the success or failure of the INSERT. To insert a row into a table, the insert must meet all table, field name, and field value requirements, as follows.
Tables:
Field Names:
Field Values:
INSERT DEFAULT VALUES
You can insert a row into a table that has all of its field values set to default values. Fields that have a defined default value are set to that value. Fields without a defined default value are set to NULL. This is done using the following command:
INSERT INTO Mytable DEFAULT VALUES
Fields defined with the NOT NULL constraint and no defined DEFAULT fail this operation with an SQLCODE -108.
Fields defined with the UNIQUE constraint can be inserted using this statement. If a field is defined with a UNIQUE constraint and no DEFAULT value, repeated invocations insert multiple rows with this UNIQUE field set to NULL. If a field is defined with a UNIQUE constraint and a DEFAULT value, this statement can only be used once. A second invocation fails with an SQLCODE -119.
DEFAULT VALUES inserts a row with a system-generated integer values for counter fields. These include the RowID, and the optional IDENTITY field, %Counter field, and ROWVERSION field.
Insert Counter Values
A table can optionally have one field defined as IDENTITY. By default, this field receives an integer from an automatically incremented table counter whenever a row is inserted into the table. By default, an insert cannot specify a value for this field. However, this default is configurable. An IDENTITY field value cannot be modified by an update operation. This counter is reset by a TRUNCATE TABLE operation.
A table can optionally have one or more fields defined as data type %Counter (%Library.Counter). By default, this field receives an integer from an automatically incremented table counter whenever a row is inserted into the table. However, a user can specify an integer value for this field during an insert, overriding the table counter default. A %Counter field value cannot be modified by an update operation. This counter is reset by a TRUNCATE TABLE operation.
A table can optionally have one field defined as data type ROWVERSION. If this field is defined, an insert operation automatically inserts an integer from a namespace-wide counter into this field. An update operation also automatically inserts an integer from a namespace-wide counter into this field, replacing the prior value. No user-specified, calculated, or default value can be inserted for a ROWVERSION field. This counter cannot be reset.
Insert Computed Values
A field defined with COMPUTECODE may insert a value as part of the INSERT operation, unless the field is CALCULATED. If you supply a value for a COMPUTED field or if this field has a default value, INSERT stores this explicit value. Otherwise, the field value is computed, as follows:
If the compute code contains a programming error (for example, divide by zero), the INSERT operation fails with an SQLCODE -415 error.
DISPLAY to LOGICAL Data Conversion
Data is stored in LOGICAL mode format. For example, a date is stored as an integer count of days. Input data that is not in LOGICAL mode format must be converted to LOGICAL mode format. Compiled SQL supports automatic conversion of input values from DISPLAY or ODBC format to LOGICAL format. Automatic conversion of input data requires two factors: when compiled, the SQL must specify RUNTIME mode; when executed, the SQL must execute in a LOGICAL mode environment.
The input data may be in any format: DISPLAY format (for example, 6/17/2011), ODBC format (for example, 2011-06-17), or LOGICAL format (for example, 62259). The data is stored in LOGICAL format if the SQL execution environment is in LOGICAL mode. This is the default mode for all Caché SQL execution environments.
You can explicitly set the select mode to LOGICAL in SQL execution environments as follows:
INSERT Field of SERIAL Data Type
An INSERT operation can specify one of the following values for a field with the SERIAL data type, with the following results:
Thus a SERIAL field contains a series incremental integer values. These values are not necessarily continuous or unique. For example, the following is a valid series of values for a SERIAL field: 1, 2, 3, 17, 18, 25, 25, 26, 27. Sequential integers are either Caché-generated or user-supplied; nonsequential integers are user-supplied. If you wish SERIAL field values to be unique, you must apply a UNIQUE constraint on the field.
Restriction Arguments
To use a restriction argument, you must have the corresponding admin-privilege for the current namespace. Refer to GRANT for further details.
Specifying restriction argument(s) restricts processing as follows:
You can specify multiple restriction arguments in any order. Multiple arguments are separated by spaces.
Referential Integrity
If you do not specify %NOCHECK, Caché uses the system configuration setting to determine whether to perform foreign key referential integrity checking. You can set the system default as follows:
This setting does not apply to foreign keys that have been defined with the NOCHECK keyword.
During an INSERT operation, for every foreign key reference a shared lock is acquired on the corresponding row in the referenced table. This row is locked while performing referential integrity checking and inserting the row. The lock is then released (it is not held until the end of the transaction). This ensures that the referenced row is not changed between the referential integrity check and the completion of the insert operation.
However, if you specify the %NOLOCK restriction argument, no locking is performed either on the specified table or on the corresponding foreign key row in the referenced table.
Child Table Insert
During an INSERT operation on a child table, a shared lock is acquired on the corresponding row in the parent table. This row is locked while inserting the child table row. The lock is then released (it is not held until the end of the transaction). This ensures that the referenced parent row is not changed during the insert operation.
List Structures
Caché supports the list structure data type %List (data type class %Library.List). This is a compressed binary format, which does not map to a corresponding native data type for Caché SQL. It corresponds to data type VARBINARY with a default MAXLEN of 32749. For this reason, Dynamic SQL cannot use INSERT or UPDATE to set a property value of type %List. For further details, refer to the Data Types reference page in this manual.
Stream Data
You cannot use a single INSERT to insert multiple rows containing a stream value. Rows containing stream data must be inserted one row at a time.
You can insert the following types of data values into a stream field:
Attempting to insert an improperly defined stream value results in an SQLCODE -412 error: General Stream Error.
Microsoft Access
To use INSERT to add data to a Caché table using Microsoft Access, either mark the table RowID as private or define a unique index on one or more additional fields.
INSERT Query Results
A single INSERT can be used to insert multiple rows into a table by combining it with a SELECT statement. The SELECT extracts column data from multiple rows of one table, and the INSERT creates corresponding new rows containing this column data in another table. However, you cannot use this technique to insert multiple rows if the data contains a stream value.
You can limit the number of rows inserted by specifying a TOP clause in the SELECT statement. You can also use an ORDER BY clause in the SELECT statement to determine which rows will be selected by the TOP clause.
An INSERT with SELECT operation sets the %ROWCOUNT variable to the number of rows inserted (either 0 or a positive integer).
The following example uses two embedded SQL programs to show this use of INSERT. The first example uses CREATE TABLE to create a new table Sample.MyStudents, and the second example populates this table with data extracted from Sample.Person. (Alternatively, you can create a new table from an existing table definition and insert data from the existing table in a single operation using the $SYSTEM.SQL.QueryToTable() method.)
To demonstrate this, please run the first embedded SQL program, then run the second. (It is necessary to use two embedded SQL programs here because embedded SQL cannot compile an INSERT statement unless the referenced table already exists.)
The following program creates the MyStudents table with two stored data fields, and one calculated field:
   ZNSPACE "Samples"
   WRITE !,"Creating table"
  &sql(CREATE TABLE Sample.MyStudents (
    StudentName VARCHAR(32),
    StudentDOB DATE,
    StudentAge INTEGER COMPUTECODE {SET {StudentAge}=
                       $PIECE(($PIECE($H,",",1)-{StudentDOB})/365,".",1)}
                       CALCULATED )
    )
  IF SQLCODE=0 {
    WRITE !,"Created table, SQLCODE=",SQLCODE }
  ELSEIF SQLCODE=-201 {
    WRITE !,"Table already exists, SQLCODE=",SQLCODE }
 
The following program uses INSERT to populate the MyStudents table with query results. Because the StudentAge field is calculated you cannot supply a value to this field; its value is calculated each time the MyStudents table is queried:
  ZNSPACE "Samples"
  WRITE !,"Populating table with data"
  NEW SQLCODE,%ROWCOUNT,%ROWID
  &sql(INSERT INTO Sample.MyStudents (StudentName,StudentDOB)
     SELECT Name,DOB
     FROM Sample.Person WHERE Age <= '21')
  IF SQLCODE=0 {
    WRITE !,"Number of records inserted=",%ROWCOUNT
    WRITE !,"Row ID of last record inserted=",%ROWID }
  ELSE {
    WRITE !,"Insert failed, SQLCODE=",SQLCODE }
 
Note that executing this INSERT program multiple times will succeed, but produces generally undesirable results. Each execution populates Sample.MyStudents with another set of records (%ROWCOUNT) with identical Name and DOB field values, automatically assigning each record a unique row ID (%ROWID).
To view the data, go to the Management Portal, select the Globals option for the SAMPLES namespace. Scroll to “Sample.MyStudentsD” and click the Data option.
The following programs display the MyStudents table data, then delete this table:
SELECT * FROM Sample.MyStudents ORDER BY StudentAge
 
  &sql(DROP TABLE Sample.MyStudents)
  IF SQLCODE=0 {WRITE !,"Table deleted" }
  ELSE {WRITE !,"SQLCODE=",SQLCODE," ",%msg }
 
By default, an Insert Query Results operation is an atomic operation. Either all of the specified rows are inserted in a table, or none of the rows are inserted. For example, if inserting one of the specified rows would violate foreign key referential integrity, the INSERT fails and no rows are inserted. This default is modifiable, as described below.
Atomicity
By default, INSERT, UPDATE, DELETE, and TRUNCATE TABLE are atomic operations. An INSERT either completes successfully or the whole operation is rolled back. If any of the specified rows cannot be inserted, none of the specified rows are inserted and the database reverts to its state before issuing the INSERT.
You can modify this default for the current process within SQL by invoking SET TRANSACTION %COMMITMODE. You can modify this default for the current process in Caché ObjectScript by invoking the SetAutoCommit() method. The following options are available:
You can determine the atomicity setting for the current process using the GetAutoCommit() method, as shown in the following Caché ObjectScript example:
  DO $SYSTEM.SQL.SetAutoCommit($RANDOM(3))
  SET x=$SYSTEM.SQL.GetAutoCommit()
  IF x=1 {
    WRITE "Default atomicity behavior",!
    WRITE "automatic commit or rollback" }
  ELSEIF x=0 {
    WRITE "No transaction initiated, no atomicity:",!
    WRITE "failed DELETE can leave database inconsistent",!
    WRITE "rollback is not supported" }
  ELSE { WRITE "Explicit commit or rollback required" }
 
Transaction Locking
If you do not specify %NOLOCK, Caché automatically performs standard record locking on INSERT, UPDATE, and DELETE operations. Each affected record (row) is locked for the duration of the current transaction.
The default lock threshold is 1000 locks per table. This means that if you insert more than 1000 records from a table during a transaction, the lock threshold is reached and Caché automatically escalates the locking level from record locks to a table lock. This permits large-scale inserts during a transaction without overflowing the lock table.
Caché applies one of the two following lock escalation strategies:
For both lock escalation strategies, you can determine the current systemwide lock threshold value using the $SYSTEM.SQL.GetLockThreshold() method. The default is 1000. This systemwide lock threshold value is configurable:
You must have USE permission on the %Admin Manage Resource to change the lock threshold. Caché immediately applies any change made to the lock threshold value to all current processes.
On potential consequence of automatic lock escalation is a deadlock situation that might occur when an attempt to escalate to a table lock conflicts with another process holding a record lock in that table. There are several possible strategies to avoid this: (1) increase the lock escalation threshold so that lock escalation is unlikely to occur within a transaction. (2) substantially lower the lock escalation threshold so that lock escalation occurs almost immediately, thus decreasing the opportunity for other processes to lock a record in the same table. (3) apply a table lock for the duration of the transaction and do not perform record locks. This can be done at the start of the transaction by specifying LOCK TABLE, then UNLOCK TABLE (without the IMMEDIATE keyword, so that the table lock persists until the end of the transaction), then perform inserts with the %NOLOCK option.
Automatic lock escalation is intended to prevent overflow of the lock table. However, if you perform such a large number of inserts that a <LOCKTABLEFULL> error occurs, INSERT issues an SQLCODE -110 error.
For further details on transaction locking refer to Transaction Processing in the “Modifying the Database” chapter of Using Caché SQL.
Row-Level Security
Caché row-level security permits INSERT to add a row even if the row security is defined so that you will not be permitted to subsequently access the row. To ensure that an INSERT does not prevent you from subsequent SELECT access to the row, it is recommended that you perform the INSERT through a view that has a WITH CHECK OPTION. For further details, refer to CREATE VIEW.
Embedded SQL and Dynamic SQL Examples
The following Embedded SQL example creates a new table Sample.MyKids. The examples that follow use INSERT to populate this table with data. After the INSERT examples, an example is provided to delete Sample.MyKids.
CreateTable
   ZNSPACE "Samples"
   &sql(CREATE TABLE Sample.MyKids (
    KidName VARCHAR(16) UNIQUE NOT NULL,
    KidDOB INTEGER NOT NULL,
    KidPetName VARCHAR(16) DEFAULT 'no pet') )
  IF SQLCODE=0 {
    WRITE !,"Table created" }
  ELSEIF SQLCODE=-201 {WRITE !,"Table already exists"  QUIT}
  ELSE {
    WRITE !,"CREATE TABLE failed. SQLCODE=",SQLCODE }
 
The following Embedded SQL example inserts a row with two field values (the third field, KidPetName, takes a default value). Note that the table schema name is supplied by the #SQLCompile Path macro directive:
EmbeddedSQLInsertByColName
  #SQLCompile Path=Sample
  NEW SQLCODE,%ROWCOUNT,%ROWID
  &sql(INSERT INTO MyKids (KidName,KidDOB) VALUES 
   ('Molly',60000))
  IF SQLCODE=0 {
    WRITE !,"Insert succeeded"
    WRITE !,"Row count=",%ROWCOUNT
    WRITE !,"Row ID=",%ROWID
    QUIT }
  ELSEIF SQLCODE=-119 {
    WRITE !,"Duplicate record not written",!
    WRITE %msg,!
    QUIT }
  ELSE {
    WRITE !,"Insert failed, SQLCODE=",SQLCODE }
 
The following Embedded SQL example inserts a row with three field values using the table's column order:
EmbeddedSQLInsertByColOrder
  NEW SQLCODE,%ROWCOUNT,%ROWID
  &sql(INSERT INTO Sample.MyKids VALUES ('Josie','40100','Fido') )
  IF SQLCODE=0 {
    WRITE !,"Insert succeeded"
    WRITE !,"Row count=",%ROWCOUNT
    WRITE !,"Row ID=",%ROWID
    QUIT }
  ELSEIF SQLCODE=-119 {
    WRITE !,"Duplicate record not written",!
    WRITE %msg,!
    QUIT }
  ELSE {
    WRITE !,"Insert failed, SQLCODE=",SQLCODE }
 
The following Embedded SQL example uses host variables to insert a row with two field values. The INSERT syntax used here specifies column=value pairs:
EmbeddedSQLInsertHostVars
  #SQLCompile Path=Sample
  NEW SQLCODE,%ROWCOUNT,%ROWID
  SET x = "Sam"
  SET y = "57555"
  &sql(INSERT INTO MyKids SET KidName=:x,KidDOB=:y )
  IF SQLCODE=0 {
    WRITE !,"Insert succeeded"
    WRITE !,"Row count=",%ROWCOUNT
    WRITE !,"Row ID=",%ROWID
    QUIT }
  ELSEIF SQLCODE=-119 {
    WRITE !,"Duplicate record not written",!
    WRITE %msg,!
    QUIT }
  ELSE {
    WRITE !,"Insert failed, SQLCODE=",SQLCODE }
 
The following Embedded SQL example uses a host variable array to insert a row with three field values. Array elements are numbered in column order. Note that user-supplied array values start with myarray(2); the first array element corresponds to the RowID, which is automatically supplied and cannot be user-defined:
EmbeddedSQLInsertHostVarArray
  #SQLCompile Path=Sample
  NEW SQLCODE,%ROWCOUNT,%ROWID
  SET myarray(2)="Deborah"
  SET myarray(3)=60200
  SET myarray(4)="Bowie"
  &sql(INSERT INTO MyKids VALUES :myarray())
  IF SQLCODE=0 {
    WRITE !,"Insert succeeded"
    WRITE !,"Row count=",%ROWCOUNT
    WRITE !,"Row ID=",%ROWID
    QUIT }
  ELSEIF SQLCODE=-119 {
    WRITE !,"Duplicate record not written",!
    WRITE %msg,!
    QUIT }
  ELSE {
    WRITE !,"Insert failed, SQLCODE=",SQLCODE }
 
The following Caché ObjectScript Dynamic SQL example uses the %SQL.Statement class to insert a row with three field values. Note that the table schema name is supplied in the %New() method:
COSDynamicSQLInsert
  SET x = "Noah"
  SET y = "61000"
  SET z = "Luna"
  SET sqltext = "INSERT INTO MyKids (KidName,KidDOB,KidPetName) VALUES (?,?,?)"
  SET tStatement = ##class(%SQL.Statement).%New(0,"Sample")
  SET tStatus = tStatement.%Prepare(sqltext)
    IF tStatus '=1 {WRITE !,"%Prepare failed"  QUIT }
  SET rtn = tStatement.%Execute(x,y,z)
  IF rtn.%SQLCODE=0 {
    WRITE !,"Insert succeeded"
    WRITE !,"Row count=",rtn.%ROWCOUNT
    WRITE !,"Row ID=",rtn.%ROWID }
  ELSEIF rtn.%SQLCODE=-119 {
    WRITE !,"Duplicate record not written",!,rtn.%Message
    QUIT }
  ELSE {
    WRITE !,"Insert failed, SQLCODE=",rtn.%SQLCODE }
 
The following Caché Basic Dynamic SQL example uses the %SQL.Statement class to insert a row with three field values:
BasicDynamicSQLInsert:
  x = "Martha"
  y = "59000"
  z = "Avery"
  sqltext = "INSERT INTO MyKids (KidName,KidDOB,KidPetName) VALUES (?,?,?)"
  tStatement = New %SQL.Statement(0,"Sample")
  status = tStatement.%Prepare(sqltext)
  IF status<>1 THEN
      PrintLn "%Prepare failed"
      Return
  END IF
  rtn = tStatement.%Execute(x,y,z)
  IF rtn.%SQLCODE=0 THEN
    Println "Insert succeeded"
    Println "Row count=",rtn.%ROWCOUNT
    Println "Row ID=",rtn.%ROWID
  ELSE
    Println "Insert failed SQLCODE=",rtn.%SQLCODE
    Println rtn.%Message
  END IF
 
For further details, refer to the Embedded SQL and Dynamic SQL chapters in Using Caché SQL.
The following Embedded SQL example displays the inserted records, then deletes the Sample.MyKids table:
DisplayAndDeleteTable
  ZNSPACE "Samples"
  SET myquery = "SELECT * FROM Sample.MyKids"
  SET tStatement = ##class(%SQL.Statement).%New()
  SET tStatus = tStatement.%Prepare(myquery)
    IF tStatus '=1 {WRITE !,"%Prepare failed"  QUIT }
  SET rset = tStatement.%Execute()
  DO rset.%Display()
  WRITE !,"End of data"
  &sql(DROP TABLE Sample.MyKids)
   IF SQLCODE=0 {
    WRITE !,"Deleted table"
    QUIT }
  ELSE {
    WRITE !,"Table delete failed, SQLCODE=",SQLCODE }
 
The following Embedded SQL example demonstrates the use of a host variable arrays. Note that with a host variable array, you can use a dynamic local array with an unspecified last subscript to pass an array of values to INSERT at runtime. For example:
  NEW SQLCODE,%ROWCOUNT,%ROWID
  &sql(INSERT INTO Sample.Employee VALUES :emp('profile',))
  WRITE !,"SQL Error code: ",SQLCODE," Row Count: ",%ROWCOUNT
causes each field in the inserted "Employee" row to be set to:
emp("profile",col)
where "col" is the field’s column number in the Sample.Employee table.
The following example shows how the results of a SELECT query can be used as the data input into an INSERT statement, supplying the data for multiple rows:
INSERT INTO StudentRoster (NAME,GPA,ID_NUM)
     SELECT FullName,GradeAvg,ID
     FROM temp WHERE SchoolYear = '2004'
See Also