In this recipe, you learn how to use the IOM and SAS/SHARE providers to write missing values to a data set by using either ADO or OLE DB. Sample code is provided for both interfaces.
Applies to: | SAS IOM Data Provider, SAS/SHARE Data Provider |
Implement using: | ADO or OLE DB |
You can write missing values (character or numeric) to a SAS data set using either the ADO or the OLE DB interface.
ADO generally represents missing values of both types as Null. Missing character values also can be represented by a string of spaces.
The following Visual Basic code uses the SAS IOM Data Provider to set every field in the data set to missing. (The IOM provider is running locally, which is done by using "_LOCAL_" as the "Data Source" property value.)
Dim cn As ADODB.Connection Dim rs As ADODB.Recordset Dim f As Field Set cn = New ADODB.Connection Set rs = New ADODB.Recordset cn.Provider = "sas.IOMProvider.1" cn.Properties("Data Source") = "_LOCAL_" cn.Open rs.LockType = adLockPessimistic ' Note that rs.LockType was set above and ' therefore no LockType is passed to the Open call rs.Open "sashelp.shoes", cn, adOpenDynamic, , adCmdTableDirect rs.MoveFirst While Not rs.EOF For Each f in rs.Fields If f.Type = adWChar Then 'character value f.Value = "" ' or f.Value = Null ' or f.Value = " " Else 'numeric value f.Value = Null End If Next f rs.MoveNext Wend
In OLE DB, you would use dwStatus to enable your application to write a missing value of either type into the data set. In addition, a string of spaces can be written to fill in a missing character value.
The following Visual C++ code is an example of how to set all the fields of one observation in a data set to Null. The iteration through the fields starts at 1 rather than 0 because the first column contains the bookmark for that row. This example assumes that the rowset has been opened in immediate update mode. If a delayed update is used instead, an additional call to IRowsetUpdate::Update must be made before the changes will be accepted.
Here is a summary of the tasks that must be done before the sample code starts:hr = pIRowset->GetData(hRow, hAccessor, pRowData); if (FAILED(hr)){ /* an error occurred */ } for (int i = 1; i < cNumColumns; i++) { pCol = (COLUMNDATA*)(pRowData + pBindings[i].obLength);pCol->dwStatus = DBSTATUS_S_ISNULL; } hr = pIRowset->QueryInterface(IID_IRowsetChange, (void**)&pIRowsetChange); if (FAILED(hr)){ /* an error occurred */ } hr = pIRowsetChange->SetData(hRow, hAccessor, pRowData); if (FAILED(hr)){ /* an error occurred */ }
The alternative method for writing character values to a data set is illustrated by the following example.
hr = pIRowset->GetData(hRow, hAccessor, pRowData); if (FAILED(hr)){ /* an error occurred */ } for (int i = 1; i < cNumColumns; i++) { pCol = (COLUMNDATA*)(pRowData + pBindings[i].obLength); if (pBindings[i].wType == DBTYPE_STR) { memset(pCol->bData, ' ', pCol->dwLength); } else // numeric column { pCol->dwStatus = DBSTATUS_S_ISNULL; } } hr = pIRowset->QueryInterface(IID_IRowsetChange, (void**)&pIRowsetChange); if (FAILED(hr)){ /* an error occurred */ } hr = pIRowsetChange->SetData(hRow, hAccessor, pRowData); if (FAILED(hr)){ /* an error occurred */ }