Changing Data Using Rowset Objects
A consumer can change data through rowset objects. OLE DB Provider for Teradata generates the DELETE, INSERT or UPDATE statement that is used to modify the data of the underlying table. The WHERE clause (for DELETE and UPDATE) identifies the rows.
After a consumer generates a rowset, the consumer changes the data through either the IRowsetChange (immediate mode) or the IRowsetUpdate (deferred mode) interface.
Setting Rowset Properties
To update through a rowset under OLE DB Provider for Teradata, the consumer must set the rowset properties as follows:
Property |
Value |
DBPROP_UPDATABILITY |
DBPROPVAL_UP_CHANGE DBPROPVAL_UP_DELETE DBPROPVAL_UP_INSERT |
DBPROP_IRowsetChange |
TRUE |
DBPROP_IRowsetUpdate |
TRUE for deferred update mode FALSE for immediate update mode |
Unsearchable Columns
In order to update using a rowset object, searchable columns must exist in the rowset. Rowsets that only contain columns that are unsearchable cannot be updated. Columns that are of the following data types are unsearchable:
If a rowset only contains columns that are unsearchable E_FAIL is returned when IRowset::GetNextRows is called and the following error message is generated:
Query cannot be updated because it contains no searchable columns to use as a key.
Rowset Restrictions
Example of proper format:
SELECT column1 from table1
[OLE DB Provider for Teradata]Query cannot be updated because FROM clause is not a single simple table name.
[Teradata Database]Column/Parameter <column alias> does not exist.
For example, OLE DB Provider for Teradata is not able to update the rowset generated from the following SELECT statement:
SELECT ItemNo, Description AS ItemDesc, PackageType AS PkgType FROM ItemTable
FLOAT, REAL, DOUBLE Restriction
OLE DB Provider for Teradata does not use columns of type FLOAT, REAL, and DOUBLE in the WHERE clause. This restriction might have unintended consequences.
When the desired rowset contains a column of type FLOAT, REAL or DOUBLE, include the primary key of the underlying table in the SELECT statement. If you do not include the key, several other rows can be affected unintentionally.
Example
In the Item table, the Price column is type FLOAT.
Item No (INTEGER) PK |
Description (VARCHAR) |
Package Type (VARCHAR) |
Price (FLOAT) |
1 |
Peas |
1 can |
1.21 |
2 |
Carrots |
1 can |
1.30 |
3 |
Soda |
6 pack |
3.00 |
4 |
Potatoes |
1 sack |
2.40 |
5 |
Ham |
1 can |
6.54 |
6 |
Soda |
12 pack |
5.50 |
The consumer submits the following SELECT statement that does not contain the primary key column:
SELECT Description, Price FROM Item
The rowset that returns from ICommand::Execute is:
Row Handle |
Description |
Price |
0x1 |
Peas |
1.21 |
0x2 |
Carrots |
1.30 |
0x3 |
Soda |
3.00 |
0x4 |
Potatoes |
2.40 |
0x5 |
Ham |
6.54 |
0x6 |
Soda |
5.50 |
Assume the user wants to increase the price of a six-pack of Soda to $3.25.
The consumer uses IRowset::SetData to update the Price in the row containing Row Handle 0x3 from 3.00 to 3.25. The SQL that OLE DB Provider for Teradata submits to Teradata Database is similar to:
UPDATE Item SET Price = ? WHERE Description = ?
Soda is bound to the Description column in the FROM clause, and 3.25 is bound to the Price column.
The UPDATE statement has the following effect on the Item table:
Item No (INTEGER) PK |
Description (VARCHAR) |
Package Type (VARCHAR) |
Price (FLOAT) |
1 |
Peas |
1 can |
1.21 |
2 |
Carrots |
1 can |
1.30 |
3 |
Soda |
6 pack |
3.25 |
4 |
Potatoes |
1 sack |
2.40 |
5 |
Ham |
1 can |
6.54 |
6 |
Soda |
12 pack |
3.25 |
The intention was to only update the six-pack price in the row of ItemNo = 3. However, because Soda is bound to the Description column, this SQL statement updates rows with Item No 3 and 6 in the underlying table.
A usual practice is to specify Price in the UPDATE statement WHERE clause, to restrict the update to the six-pack price. However, OLE DB Provider for Teradata did not include Price in the WHERE clause because Price is type FLOAT in the underlying table. OLE DB Provider for Teradata does not use columns of type FLOAT, REAL, and DOUBLE in the WHERE clause. To solve this problem, you should always include the primary key in the SELECT statement that creates the rowset:
SELECT ItemNo, Description, Price from Item
The rowset that returns from ICommand::Execute is:
Row Handle |
ItemNo |
Description |
Price |
0x1 |
1 |
Peas |
1.21 |
0x2 |
2 |
Carrots |
1.30 |
0x3 |
3 |
Soda |
3.00 |
0x4 |
4 |
Potatoes |
2.40 |
0x5 |
5 |
Ham |
6.54 |
0x6 |
6 |
Soda |
5.50 |
The ItemNo primary key column is now available in the rowset. The unique ItemNo can identify the row instead of the non-unique soda description.
The consumer uses IRowsetChange::SetData to update the Price in the row with the Row Handle 0x3. OLE DB Provider for Teradata generates the UPDATE statement:
UPDATE Item SET Price = ? WHERE Description = ? and ItemNo = ?
This statement uniquely identifies the target row. Teradata Database only updates the six-pack Soda price.
Recommendations
When you update rowsets, the following is recommended:
For more information on using IRowsetChange and IRowsetUpdate to change data, refer to the Microsoft Developer’s Network (MSDN) documentation on Changing Data.