Sei sulla pagina 1di 51

La Gua del programador de ADO se ha creado para ayudar a programadores que no conocen ADO, ofrecindoles una introduccin completa

a la tecnologa. Esta gua describe las bibliotecas de la familia de ADO y utiliza cdigos de ejemplo en diversos lenguajes para explicar cmo utilizar las bibliotecas, prcticas recomendadas para usar las bibliotecas, y sugerencias y trucos para maximizar el rendimiento de una aplicacin de ADO. La Gua del programador de ADO contiene las secciones y los captulos siguientes: Seccin I: Objetos de datos ActiveX (ADO) Captulo 1: Conceptos bsicos de ADO Captulo 2: Obtener datos Captulo 3: Examinar datos Captulo 4: Modificar datos Captulo 5: Actualizar y almacenar datos. Captulo 6: Tratamiento de errores Captulo 7: Controlar eventos de ADO Captulo 8: Cursores y bloqueos Captulo 9: Forma de datos Captulo 10: Objetos Record y Stream Seccin II: Servicio de datos remotos (RDS) Captulo 11: Conceptos bsicos de RDS Captulo 12: Tutorial de RDS Captulo 13: Uso y seguridad de RDS Seccin III: ActiveX Data Objects (Multidimensional) (ADO MD) Captulo 14: Conceptos bsicos de ADO MD Seccin IV: Extensiones de ActiveX Data Objects para lenguaje de definicin de datos y seguridad (ADOX) Captulo 15: Conceptos bsicos de ADOX Seccin V: Apndices Apndice A: Proveedores Apndice B: Errores de ADO Apndice C: Programar con ADO Apndice D: Ejemplos de ADO Glosario de ADO

Seccin I: Objetos de datos ActiveX (ADO) Esta seccin contiene los captulos siguientes: Captulo 1: Conceptos bsicos de ADO Captulo 2: Obtener datos Captulo 3: Examinar datos Captulo 4: Modificar datos Captulo 5: Actualizar y almacenar datos Captulo 6: Tratamiento de errores Captulo 7: Controlar eventos de ADO Captulo 8: Cursores y bloqueos Captulo 9: Forma de datos Captulo 10: Objetos Record y Stream

Captulo 1: Conceptos bsicos de ADO Este captulo es una introduccin a la biblioteca ADO. Describe qu se puede hacer con ADO, revisa los objetos de la jerarqua de ADO y presenta una aplicacin sencilla de ADO que utiliza muchos de los objetos de ADO para recuperar, modificar y actualizar datos de un origen de datos. Por ltimo, en este captulo se tratan dos problemas que es importante comprender para escribir aplicaciones de ADO: proveedores OLE DB y errores. Qu se puede hacer con ADO ADO se ha diseado para proporcionar a los programadores un modelo de objetos lgico y eficaz para el acceso, modificacin y actualizacin, mediante cdigo de programacin, de una gran variedad de orgenes de datos por medio de interfaces de sistema OLE DB. El uso ms comn de ADO es el de consultar en una o varias tablas de una base de datos relacional, recuperar y mostrar los resultados en una aplicacin y, quiz, permitir a los usuarios que realicen y guarden cambios en los datos. Otras acciones que se pueden realizar mediante programacin con ADO son las siguientes: Consultar una base de datos mediante SQL y mostrar los resultados. Obtener acceso a informacin ubicada en un almacn de archivos a travs de Internet. Manipular mensajes y carpetas en un sistema de correo electrnico. Guardar los datos de una base de datos en un archivo XML. Permitir a un usuario revisar y realizar cambios en datos de tablas de base de datos. Crear y volver a usar comandos de base de datos parametrizados. Ejecutar procedimientos almacenados. Crear dinmicamente una estructura flexible, denominada Recordset, para contener, manipular datos y navegar por ellos. Realizar operaciones transaccionales de bases de datos. Filtrar y ordenar copias locales de informacin de base de datos segn criterios especificados en tiempo de ejecucin. Crear y manipular resultados jerrquicos de bases de datos. Enlazar campos de base de datos a componentes diseados para datos. Crear conjuntos de registros desconectados remotos. ADO debe exponer una gran variedad de opciones y valores de configuracin para proporcionar dicha flexibilidad. Por lo tanto, es importante adoptar un enfoque metdico para aprender a utilizar ADO en una aplicacin, descomponiendo cada uno de sus objetivos en partes manejables. En la mayora de los programas ADO existen cuatro operaciones principales implicadas: obtener, examinar, modificar y actualizar datos. Los siguientes cuatro captulos describen cada una de estas operaciones con ms detalle. Antes de continuar, familiarcese con los objetos del Modelo de objetos ADO. A continuacin, revise HelloData: una aplicacin ADO sencilla. Esta aplicacin est escrita en Visual Basic y realiza cada una de las cuatro operaciones principales de ADO. HelloData: una aplicacin ADO simple Para establecer el trabajo de base de una exploracin de la biblioteca ADO, considere la opcin de utilizar una aplicacin ADO simple denominada "HelloData". HelloData ejecuta cada una de las cuatro operaciones principales de ADO (obtener, examinar, editar y actualizar datos). Para centrarse

en los conceptos bsicos de ADO y evitar la sobrecarga de cdigo, se realiza un mnimo tratamiento de errores en este ejemplo. La aplicacin realiza consultas en la base de datos de ejemplo Neptuno que se incluye con Microsoft SQL Server 2000. Para ejecutar HelloData Cree un nuevo proyecto estndar ejecutable de Visual Basic que haga referencia a la biblioteca de ADO 2.5. Cree cuatro botones de comando en la parte superior del formulario, estableciendo las propiedades Name y Caption en los valores que se muestran en la tabla que figura ms abajo. Debajo de los botones, agregue un control cuadrcula de datos de Microsoft (Msdatgrd.ocx). El archivo Msdatgrd.ocx se incluye con Visual Basic y est ubicado en el directorio \windows\system32 o \winnt\system32. Para agregar el control cuadrcula de datos al panel de cuadro de herramientas de Visual Basic, seleccione Componentes en el men Proyecto. A continuacin, compruebe el cuadro situado junto a "Microsoft DataGrid Control 6.0 (SP3) (OLEDB)" y haga clic en Aceptar. Para agregar el control al proyecto, arrastre el control cuadrcula de datos desde el cuadro de herramientas hasta el formulario de Visual Basic. Cree un control cuadro de texto en el formulario debajo de la cuadrcula y establezca sus propiedades tal como se muestra en la tabla. El formulario debe tener un aspecto similar a la ilustracin siguiente cuando haya finalizado. Por ltimo, copie el cdigo que se muestra en "Cdigo HelloData" y pguelo en la ventana del editor de cdigo del formulario. Presione F5 para que se ejecute el cdigo. Nota En el ejemplo siguiente y en toda la Gua, se utiliza el identificador de usuario "MyId" con la contrasea "123aBc" para autenticacin en el servidor. Debe sustituir estos valores con credenciales de inicio de sesin vlidas para su servidor. Sustituya tambin el valor "MyServer" por el nombre del servidor. Para obtener una descripcin detallada del cdigo, vea "Detalles sobre HelloData".
Tipo de control Formulario Propiedad Name Height Width Cuadrcula de datos de MS Cuadro de texto Botn de comando Botn de comando Botn de comando Botn de comando Name Name Multiline Name Caption Name Caption Name Caption Name Caption Valor Form1 6500 6500 grdDisplay1 txtDisplay1 true cmdGetData Get Data cmdExamineData Examine Data cmdEditData Edit Data cmdUpdateData Update Data

Cdigo HelloData

'BeginHelloData Option Explicit Dim m_oRecordset As ADODB.Recordset Dim m_sConnStr As String Dim m_flgPriceUpdated As Boolean Private Sub cmdGetData_Click() GetData If Not m_oRecordset Is Nothing Then If m_oRecordset.State = adStateOpen Then ' Set the proper states for the buttons. cmdGetData.Enabled = False cmdExamineData.Enabled = True End If End If End Sub Private Sub cmdExamineData_Click() ExamineData End Sub Private Sub cmdEditData_Click() EditData End Sub Private Sub cmdUpdateData_Click() UpdateData ' Set the proper states for the buttons. cmdUpdateData.Enabled = False End Sub Private Sub GetData() On Error GoTo GetDataError Dim sSQL As String Dim oConnection1 As ADODB.Connection m_sConnStr = "Provider='SQLOLEDB';Data Source='MySqlServer';" & _ "Initial Catalog='Northwind';Integrated Security='SSPI';" ' Create and Open the Connection object. Set oConnection1 = New ADODB.Connection oConnection1.CursorLocation = adUseClient oConnection1.Open m_sConnStr sSQL = "SELECT ProductID, ProductName, CategoryID, UnitPrice " & _ "FROM Products" ' Create and Open the Recordset object. Set m_oRecordset = New ADODB.Recordset

m_oRecordset.Open sSQL, oConnection1, adOpenStatic, _ adLockBatchOptimistic, adCmdText m_oRecordset.MarshalOptions = adMarshalModifiedOnly ' Disconnect the Recordset. Set m_oRecordset.ActiveConnection = Nothing oConnection1.Close Set oConnection1 = Nothing ' Bind Recordset to the DataGrid for display. Set grdDisplay1.DataSource = m_oRecordset Exit Sub GetDataError: If Err <> 0 Then If oConnection1 Is Nothing Then HandleErrs "GetData", m_oRecordset.ActiveConnection Else HandleErrs "GetData", oConnection1 End If End If If Not oConnection1 Is Nothing Then If oConnection1.State = adStateOpen Then oConnection1.Close Set oConnection1 = Nothing End If End Sub Private Sub ExamineData() On Err GoTo ExamineDataErr Dim iNumRecords As Integer Dim vBookmark As Variant iNumRecords = m_oRecordset.RecordCount DisplayMsg "There are " & CStr(iNumRecords) & _ " records in the current Recordset." ' Loop through the Recordset and print the ' value of the AbsolutePosition property. DisplayMsg "****** Start AbsolutePosition Loop ******" Do While Not m_oRecordset.EOF ' Store the bookmark for the 3rd record, ' for demo purposes. If m_oRecordset.AbsolutePosition = 3 Then _ vBookmark = m_oRecordset.Bookmark DisplayMsg m_oRecordset.AbsolutePosition m_oRecordset.MoveNext Loop DisplayMsg "****** End AbsolutePosition Loop ******" & vbCrLf

' Use our bookmark to move back to 3rd record. m_oRecordset.Bookmark = vBookmark MsgBox vbCr & "Moved back to position " & _ m_oRecordset.AbsolutePosition & " using bookmark.", , _ "Hello Data" ' Display meta-data about each field. See WalkFields() sub. Call WalkFields ' Apply a filter on the type field. MsgBox "Filtering on type field. (CategoryID=2)", _ vbOKOnly, "Hello Data" m_oRecordset.Filter = "CategoryID=2" ' Set the proper states for the buttons. cmdExamineData.Enabled = False cmdEditData.Enabled = True Exit Sub ExamineDataErr: HandleErrs "ExamineData", m_oRecordset.ActiveConnection End Sub Private Sub EditData() On Error GoTo EditDataErr 'Recordset still filtered on CategoryID=2. 'Increase price by 10% for filtered records. MsgBox "Increasing unit price by 10%" & vbCr & _ "for all records with CategoryID = 2.", , "Hello Data" m_oRecordset.MoveFirst Dim cVal As Currency Do While Not m_oRecordset.EOF cVal = m_oRecordset.Fields("UnitPrice").Value m_oRecordset.Fields("UnitPrice").Value = (cVal * 1.1) m_oRecordset.MoveNext Loop ' Set the proper states for the buttons. cmdEditData.Enabled = False cmdUpdateData.Enabled = True Exit Sub EditDataErr: HandleErrs "EditData", m_oRecordset.ActiveConnection End Sub Private Sub UpdateData() On Error GoTo UpdateDataErr Dim oConnection2 As New ADODB.Connection

MsgBox "Removing Filter (adFilterNone).", , "Hello Data" m_oRecordset.Filter = adFilterNone Set grdDisplay1.DataSource = Nothing Set grdDisplay1.DataSource = m_oRecordset MsgBox "Applying Filter (adFilterPendingRecords).", , "Hello Data" m_oRecordset.Filter = adFilterPendingRecords Set grdDisplay1.DataSource = Nothing Set grdDisplay1.DataSource = m_oRecordset DisplayMsg "*** PRE-UpdateBatch values for 'UnitPrice' field. ***" ' Display Value, UnderlyingValue, and OriginalValue for ' type field in first record. If m_oRecordset.Supports(adMovePrevious) Then m_oRecordset.MoveFirst DisplayMsg "OriginalValue = " & _ m_oRecordset.Fields("UnitPrice").OriginalValue DisplayMsg "Value = " & _ m_oRecordset.Fields("UnitPrice").Value End If oConnection2.ConnectionString = m_sConnStr oConnection2.Open Set m_oRecordset.ActiveConnection = oConnection2 m_oRecordset.UpdateBatch m_flgPriceUpdated = True DisplayMsg "*** POST-UpdateBatch values for 'UnitPrice' field ***" If m_oRecordset.Supports(adMovePrevious) Then m_oRecordset.MoveFirst DisplayMsg "OriginalValue = " & _ m_oRecordset.Fields("UnitPrice").OriginalValue DisplayMsg "Value = " & _ m_oRecordset.Fields("UnitPrice").Value End If MsgBox "See value comparisons in txtDisplay.", , _ "Hello Data" 'Clean up oConnection2.Close Set oConnection2 = Nothing Exit Sub UpdateDataErr: If Err <> 0 Then HandleErrs "UpdateData", oConnection2 End If If Not oConnection2 Is Nothing Then

If oConnection2.State = adStateOpen Then oConnection2.Close Set oConnection2 = Nothing End If End Sub Private Sub WalkFields() On Error GoTo WalkFieldsErr Dim Dim Dim Dim iFldCnt As Integer oFields As ADODB.Fields oField As ADODB.Field sMsg As String

Set oFields = m_oRecordset.Fields DisplayMsg "****** BEGIN FIELDS WALK ******" For iFldCnt = 0 To (oFields.Count - 1) Set oField = oFields(iFldCnt) sMsg = "" sMsg = sMsg & oField.Name sMsg = sMsg & vbTab & "Type: " & GetTypeAsString(oField.Type) sMsg = sMsg & vbTab & "Defined Size: " & oField.DefinedSize sMsg = sMsg & vbTab & "Actual Size: " & oField.ActualSize grdDisplay1.SelStartCol = iFldCnt grdDisplay1.SelEndCol = iFldCnt DisplayMsg sMsg MsgBox sMsg, , "Hello Data" Next iFldCnt DisplayMsg "****** END FIELDS WALK ******" & vbCrLf 'Clean up Set oField = Nothing Set oFields = Nothing Exit Sub WalkFieldsErr: Set oField = Nothing Set oFields = Nothing If Err <> 0 Then MsgBox Err.Source & "-->" & Err.Description, , "Error" End If End Sub Private Function GetTypeAsString(dtType As ADODB.DataTypeEnum) As String ' To save space, we are only checking for data types ' that we know are present. Select Case dtType Case adChar GetTypeAsString = "adChar" Case adVarChar GetTypeAsString = "adVarChar" Case adVarWChar GetTypeAsString = "adVarWChar"

Case adCurrency GetTypeAsString = "adCurrency" Case adInteger GetTypeAsString = "adInteger" End Select End Function Private Sub HandleErrs(sSource As String, ByRef m_oConnection ADODB.Connection) DisplayMsg "ADO (OLE) ERROR IN " & sSource DisplayMsg vbTab & "Error: " & Err.Number DisplayMsg vbTab & "Description: " & Err.Description DisplayMsg vbTab & "Source: " & Err.Source As

If Not m_oConnection Is Nothing Then If m_oConnection.Errors.Count <> 0 Then DisplayMsg "PROVIDER ERROR" Dim oError1 As ADODB.Error For Each oError1 In m_oConnection.Errors DisplayMsg vbTab & "Error: " & oError1.Number DisplayMsg vbTab & "Description: " & oError1.Description DisplayMsg vbTab & "Source: " & oError1.Source DisplayMsg vbTab & "Native Error:" & oError1.NativeError DisplayMsg vbTab & "SQL State: " & oError1.SQLState Next oError1 m_oConnection.Errors.Clear Set oError1 = Nothing End If End If MsgBox "Error(s) information.", , _ "Hello Data" Err.Clear End Sub Private Sub DisplayMsg(sText As String) txtDisplay1.Text = (txtDisplay1.Text & vbCrLf & sText) End Sub Private Sub Form_Resize() grdDisplay1.Move 100, 700, Me.ScaleWidth - 200, (Me.ScaleHeight 800) / 2 txtDisplay1.Move 100, grdDisplay1.Top + grdDisplay1.Height + 100, _ Me.ScaleWidth - 200, (Me.ScaleHeight - 1000) / 2 End Sub Private Sub Form_Load() cmdGetData.Enabled = True cmdExamineData.Enabled = False cmdEditData.Enabled = False cmdUpdateData.Enabled = False grdDisplay1.AllowAddNew = False grdDisplay1.AllowDelete = False grdDisplay1.AllowUpdate = False occurred. See txtDisplay1 for specific

m_flgPriceUpdated = False End Sub Private Sub Form_Unload(Cancel As Integer) On Error GoTo ErrHandler: Dim oConnection3 As New ADODB.Connection Dim sSQL As String Dim lAffected As Long ' Undo the changes we've made to the database on the server. If m_flgPriceUpdated Then sSQL = "UPDATE Products SET UnitPrice=(UnitPrice/1.1) " & _ "WHERE CategoryID=2" oConnection3.Open m_sConnStr oConnection3.Execute sSQL, lAffected, adCmdText MsgBox "Restored prices for " & CStr(lAffected) & _ " records affected.", , "Hello Data" End If 'Clean up oConnection3.Close Set oConnection3 = Nothing m_oRecordset.Close Set m_oRecordset = Nothing Exit Sub ErrHandler: If Not oConnection3 Is Nothing Then If oConnection3.State = adStateOpen Then oConnection3.Close Set oConnection3 = Nothing End If If Not m_oRecordset Is Nothing Then If m_oRecordset.State = adStateOpen Then m_oRecordset.Close Set m_oRecordset = Nothing End If End Sub 'EndHelloData

Detalles sobre HelloData La aplicacin HelloData realiza las operaciones bsicas de una aplicacin ADO tpica: obtener, examinar, editar y actualizar datos. Cuando inicie la aplicacin, haga clic en el primer botn, Obtener datos. De esta forma, se ejecutar la subrutina GetData(). GetData GetData coloca una cadena de conexin vlida en una variable del mdulo, m_sConnStr. Para obtener ms informacin sobre cadenas de conexin, vea Crear la cadena de conexin. Asigne un controlador de errores mediante una instruccin OnError de Visual Basic. Para obtener ms informacin acerca del tratamiento de errores en ADO, vea Captulo 6: Tratamiento de errores. Se crea un nuevo objeto Connection y la propiedad CursorLocation se establece en adUseClient,

dado que el ejemplo de HelloData crea un objeto Recordset desconectado. Eso significa que una vez que se han recuperado los datos del origen de datos, se rompe la conexin fsica con el origen de datos, aunque se puede seguir trabajando con los datos almacenados en cach de forma local en el objeto Recordset. Una vez establecida la conexin, asigne una cadena SQL a una variable (sSQL). A continuacin, cree una instancia de un nuevo objeto Recordset, m_oRecordset1 . En la siguiente lnea del cdigo, abra el objeto Recordset a travs del objeto Connection existente, pasando sSQL como origen del objeto Recordset. Ayude a ADO a tomar la determinacin de que la cadena SQL que se acaba de pasar como origen del objeto Recordset es una definicin textual de un comando al pasar adCmdText en el argumento al mtodo Open del objeto Recordset. Esta lnea tambin establece las propiedades LockType y CursorType asociadas al objeto Recordset. La siguiente lnea de cdigo establece la propiedad MarshalOptions en adMarshalModifiedOnly.MarshalOptions indica en qu registros se deben calcular las referencias en el nivel intermedio (o el servidor web). Para obtener ms informacin acerca del clculo de referencias, vea la documentacin sobre COM. Cuando use adMarshalModifiedOnly con un cursor del cliente (CursorLocation = adUseClient), solo los registros modificados en el cliente se vuelven a escribir en el nivel intermedio. El establecimiento de MarshalOptions en adMarshalModifiedOnly puede mejorar el rendimiento, dado que se calculan las referencias de menos filas. A continuacin, desconecte el objeto Recordset al establecer su propiedad ActiveConnection en Nothing. Para obtener ms informacin, vea Desconectar y volver a conectar el objeto Recordset en el captulo 5: Actualizar y almacenar datos. Cierre la conexin con el origen de datos y destruya el objeto Connection existente, con lo que se liberan los recursos que ste estaba utilizando. El paso final consiste en establecer el objeto Recordset como DataSource de Microsoft DataBound Grid Control en el formulario para poder mostrar fcilmente los datos del objeto Recordset en el formulario. Haga clic en el segundo botn, Examinar datos. De esta forma, se ejecuta la subrutina ExamineData. ExamineData ExamineData emplea varios mtodos y propiedades del objeto Recordset para mostrar informacin acerca de los datos del objeto Recordset. Informa acerca del nmero de registros mediante la propiedad RecordCount. Recorre el objeto Recordset e imprime el valor de la propiedad AbsolutePosition en el cuadro de texto del formulario que aparece. Adems, durante el recorrido, el valor de la propiedad Bookmark del tercer registro se coloca en una variable de variante, vBookmark, para su uso posterior.

La rutina navega directamente al tercer registro mediante la variable de marcador almacenada anteriormente. La rutina llama a la subrutina WalkFields, que recorre la coleccin Fields del objeto Recordset y muestra detalles de cada objeto Field de la coleccin. Por ltimo, ExamineData utiliza la propiedad Filter del objeto Recordset para buscar slo aquellos registros cuyo CategoryId sea igual a 2. El resultado de la aplicacin de este filtro es visible inmediatamente en la cuadrcula del formulario. Para obtener ms informacin acerca de la funcionalidad de la subrutina ExamineData, vea el Captulo 3: Examinar datos. A continuacin, haga clic en el tercer botn, Modificar datos. De esta forma, se ejecutar la subrutina EditData. EditData Cuando el cdigo entra en la subrutina EditData, el objeto Recordset sigue estando filtrado por CategoryId igual a 2, de modo que slo son visibles los elementos que satisfacen los criterios del filtro. En primer lugar recorre el objeto Recordset y aumenta el precio de cada elemento visible del objeto Recordset un 10 por ciento. El valor del campo Price cambia al establecer la propiedad Value de ese campo en una nueva cantidad vlida. Recuerde que el objeto Recordset est desconectado del origen de datos. Los cambios realizados en EditData slo se efectan de forma local en la copia almacenada en cach de los datos. Para obtener ms informacin, vea el Captulo 4: Modificar datos. Los cambios no se realizarn en el origen de datos hasta que no se haga clic en el cuarto botn, Actualizar datos. As se ejecutar la subrutina UpdateData. UpdateData En primer lugar, UpdateData quita el filtro aplicado al objeto Recordset. El cdigo quita y restablece m_oRecordset1 como el DataSource de Microsoft Bound DataGrid del formulario para que el objeto Recordset sin filtrar aparezca en la cuadrcula. A continuacin, el cdigo comprueba si es posible volver a desplazarse por el objeto Recordset mediante el mtodo Supports con el argumento adMovePrevious. La rutina se desplaza al primer registro mediante el mtodo MoveFirst y muestra los valores originales y actuales del campo mediante las propiedades OriginalValue y Value del objeto Field. Puede obtener informacin sobre estas propiedades, junto a la propiedad UnderlyingValue (que no se utiliza aqu), en el Captulo 5: Actualizar y almacenar datos.. Despus, se crea un nuevo objeto Connection que se utiliza para restablecer una conexin con el origen de datos. Se vuelve a conectar el objeto Recordset con el origen de datos al establecer el nuevo objeto Connection como ActiveConnection del objeto Recordset. Para enviar las actualizaciones al servidor, el cdigo llama al mtodo UpdateBatch del objeto Recordset. Si la actualizacin por lotes se realiza correctamente, una variable de marca del mdulo,

m_flgPriceUpdated , se establece en True. Eso le recordar ms tarde que debe limpiar todos los cambios realizados en la base de datos. Finalmente, el cdigo se desplaza al primer registro del objeto Recordset y muestra los valores originales y actuales. stos son los mismos despus de la llamada al mtodo UpdateBatch. Para obtener informacin ms detallada acerca de la actualizacin de datos, incluido qu hacer cuando los datos del servidor cambian mientras el objeto Recordset est desconectado, vea el Captulo 5: Actualizar y almacenar datos.. Form_Unload La subrutina Form_Unload es importante por varias razones. En primer lugar porque esta aplicacin de ejemplo, Form_Unload, limpia los cambios realizados en la base de datos antes de salir de la aplicacin. En segundo lugar, el cdigo muestra cmo se puede ejecutar un comando directamente desde un objeto Connection abierto mediante el mtodo Execute. Por ltimo, muestra un ejemplo de ejecucin de una consulta que no devuelve filas (una consulta UPDATE) realizada en el origen de datos. Errores Toda operacin que implique a objetos de ADO puede generar errores de proveedor. Cuando se produce alguno de estos errores, se colocan objetos Error en la coleccin Errors del objeto Connection. Para obtener detalles acerca del tratamiento de advertencias y errores en una aplicacin de ADO, vea el Captulo 6: Tratamiento de errores. Los errores de aplicacin pueden ser generados por un mecanismo independiente. Por ejemplo, en Visual Basic, el objeto Err contendr errores de nivel de aplicacin. proveedores OLE DB La Introduccin de la Gua del programador de ADO analiza la relacin entre ADO y el resto de la arquitectura de acceso a datos de Microsoft. OLE DB define un conjunto de interfaces COM que proporcionan a las aplicaciones un acceso uniforme a los datos almacenados en diversos orgenes de informacin. Este enfoque permite que un origen de datos comparta sus datos a travs de las interfaces que admiten la funcionalidad de administracin de base de datos adecuada al origen de datos. Por diseo, la arquitectura de alto rendimiento de OLE DB se basa en el uso de un modelo de servicios flexible basado en componentes. En vez de tener un nmero predefinido de capas intermedias entre la aplicacin y los datos, OLE DB slo requiere los componentes estrictamente necesarios para realizar una determinada tarea. Por ejemplo, suponga que un usuario desea ejecutar una consulta. Considere los escenarios siguientes: Los datos residen en una base de datos relacional para la que existe actualmente un controlador ODBC, pero ningn proveedor OLE DB nativo: la aplicacin utiliza ADO para comunicarse con el Proveedor OLE DB para ODBC, que carga despus el controlador ODBC apropiado. El controlador pasa la instruccin SQL al sistema de administracin de bases de datos, que recupera los datos.

Los datos residen en Microsoft SQL Server para el que existe un proveedor OLE DB nativo: la aplicacin utiliza ADO para comunicarse directamente con el Proveedor OLE DB para Microsoft SQL Server. No se necesita ningn intermediario. Los datos residen en Microsoft Exchange Server, para el que existe un proveedor OLE DB, pero que no expone ningn motor con el fin de procesar consultas SQL: la aplicacin utiliza ADO para comunicarse con el Proveedor OLE DB para Microsoft Exchange y llama a un componente de procesador de consultas OLE DB a fin de procesar las consultas. Los datos residen en el sistema de archivos NTFS de Microsoft en forma de documentos: el acceso a los datos se realiza mediante un proveedor OLE DB nativo en Servicios de Microsoft Index Server, que indizan el contenido y las propiedades de los documentos del sistema de archivos para permitir bsquedas eficientes basadas en el contenido. En todos los ejemplos anteriores, la aplicacin puede consultar los datos. Las necesidades del usuario se satisfacen con un nmero mnimo de componentes. En cada caso, slo se utilizan componentes adicionales si es necesario y slo se llama a los componentes necesarios. Esta carga a peticin de los componentes que se pueden compartir y volver a usar contribuye en gran medida al alto rendimiento que se obtiene con OLE DB. Los proveedores se dividen en dos categoras: aqullos que proporcionan datos y los que proporcionan servicios. Un proveedor de datos tiene sus propios datos y los expone a la aplicacin en forma de tabla. Un proveedor de servicios encapsula un servicio mediante la generacin y el consumo de datos, que contribuye a aumentar las caractersticas de las aplicaciones ADO. Adems, un proveedor de servicios se puede definir con ms detalle como componente de servicio, que debe funcionar conjuntamente con otros componentes o proveedores de servicios. ADO proporciona una interfaz coherente de nivel superior con los diversos proveedores OLE DB. Proveedores de datos Los proveedores de datos representan diversos orgenes de datos como bases de datos SQL, archivos secuenciales indizados, hojas de clculo, almacenes de documentos y archivos de correo. Los proveedores exponen datos uniformemente mediante una abstraccin comn que se denomina conjunto de filas. ADO es eficaz y flexible porque puede conectarse a cualquiera entre varios proveedores de datos y seguir exponiendo el mismo modelo de programacin, independientemente de las caractersticas especficas de un proveedor determinado. No obstante, dado que cada proveedor de datos es nico, la interaccin de una aplicacin con ADO variar segn cul sea el proveedor de datos. Por ejemplo, las funcionalidades y las caractersticas del proveedor OLE DB para SQL Server, que se utiliza para tener acceso a bases de datos de Microsoft SQL Server, son considerablemente diferentes de las correspondientes al proveedor de Microsoft OLE DB para Internet Publishing, que se utiliza para tener acceso a almacenes de archivo en un servidor Web. Proveedores de servicios y componentes Los proveedores de servicios son componentes que amplan la funcionalidad de los proveedores de datos mediante la implementacin de interfaces extendidas que el almacn de datos no admite de forma nativa. Microsoft Data Access proporciona una arquitectura de componentes que permite a componentes individuales y especializados implementar conjuntos discretos de funciones de base de datos, o

"servicios", en almacenes con menos funcionalidades. En vez de obligar a que cada almacn de datos proporcione su propia implementacin de la funcionalidad ampliada o forzar a las aplicaciones genricas a que implementen internamente la funcionalidad de base de datos, los componentes de servicios proporcionan una implementacin comn que puede ser utilizada por cualquier aplicacin al obtener acceso a cualquier almacn de datos. El hecho de que una parte de la funcionalidad la implemente de forma nativa el almacn de datos y la otra mediante componentes genricos es transparente a la aplicacin. Por ejemplo, un motor de cursor, como el Servicio de cursores de Microsoft para OLE DB, es un componente de servicio que puede consumir datos de un almacn de datos secuencial de slo avance y generar datos desplazables. Otros proveedores de servicios que suele usar ADO son el Proveedor OLE DB de persistencia de Microsoft (para guardar datos en un archivo), el Servicio de forma de datos de Microsoft para OLE DB (para objetos Recordset jerrquicos) y el Proveedor de acceso remoto de Microsoft para OLE DB (para llamar a proveedores de datos en un equipo remoto). Para obtener ms informacin acerca de proveedores de servicios y datos, vea Apndice A: Proveedores.

Captulo 2: Obtener datos


En el captulo anterior, se presentaron cuatro operaciones principales que tenan que ver con la creacin de una aplicacin de ADO: obtener datos, examinar datos, editar datos y actualizar datos. Este captulo se centrar en los detalles de los conceptos relativos a la primera operacin: obtener datos. Hay varios objetos de ADO que pueden desempear un rol en esta operacin. Primero, hay que conectarse al origen de datos usando un objeto Connection de ADO (que, en ocasiones, se crear implcitamente). Despus, se pasan instrucciones al origen de datos acerca de lo que se desea hacer usando un objeto Command de ADO (que tambin se puede crear de forma implcita). El resultado de pasar un comando a un origen de datos y recibir su respuesta normalmente se representar con un objeto Recordset de ADO. Para obtener datos, la aplicacin debe estar en comunicacin con un origen de datos, como DBMS, un almacn de archivos o un archivo de texto delimitado por comas. Esta comunicacin representa una conexin (el entorno necesario para intercambiar datos). El modelo de objetos de ADO representa el concepto de una conexin con el objeto Connection (la base sobre la que se construye una parte importante de la funcionalidad de ADO). El propsito de un objeto Connection es: Definir la informacin que ADO necesita para comunicarse con orgenes de datos y crear sesiones. Definir las caractersticas transaccionales de la sesin. Permitirle crear y ejecutar comandos en el origen de datos. Proporcionar informacin acerca del diseo del origen de datos subyacente en forma de conjuntos de filas de esquema. Para obtener ms informacin acerca de conjuntos de filas de esquema, vea Mtodo OpenSchema. OpenSchema (mtodo, ADO) Obtiene informacin del esquema de base de datos del proveedor.

Sintaxis Set recordset = connection.OpenSchema (QueryType, Criteria, SchemaID)

Valores devueltos Devuelve un objeto Recordset que contiene informacin de esquema. El objeto Recordset se abrir como un cursor esttico de solo lectura. El parmetro QueryType determina qu columnas aparecen en el objeto Recordset. Parmetros QueryType Cualquier valor de SchemaEnum que represente el tipo de consulta de esquema que se va a ejecutar. Criteria Es opcional. Matriz de restricciones de consulta para cada opcin QueryType, tal y como se muestra en SchemaEnum. SchemaID Identificador GUID de una consulta de esquema del proveedor no definida por la especificacin OLE DB. Este parmetro es necesario si el valor de QueryType es adSchemaProviderSpecific; en caso contrario, no se utiliza. Comentarios El mtodo OpenSchema devuelve informacin autodescriptiva sobre el origen de datos, como qu tablas hay en el origen de datos, las columnas de las tablas y los tipos de datos admitidos. El argumento de QueryType es un identificador GUID que indica las columnas devueltas (esquemas). La especificacin OLE DB tiene una lista completa de esquemas. El argumento de Criteria limita los resultados de una consulta de esquema. Criteria especifica una matriz de valores que se deben producir en un subconjunto correspondiente de columnas, denominadas columnas de restriccin, del objeto Recordset resultante.

La constante adSchemaProviderSpecific se utiliza en el argumento de QueryType si el proveedor define sus propias consultas de esquema no estndar adems de las anteriormente mencionadas. Cuando se utiliza esta constante, el argumento de SchemaID debe pasar el identificador GUID de la consulta de esquema que se va a ejecutar. Si el valor de QueryType es adSchemaProviderSpecific pero no se proporciona SchemaID, se producir un error. Los proveedores no tienen que admitir necesariamente todas las consultas de esquema OLE DB estndar. En concreto, la especificacin OLE DB slo requiere AdSchemaTables, adSchemaColumns y adSchemaProviderTypes. Sin embargo, el proveedor no tiene que admitir necesariamente las restricciones de Criteria anteriormente mencionadas para esas consultas de esquema. Uso del Servicio de datos remotos (RDS) El mtodo OpenSchema no est disponible en un objeto Connection de cliente. Nota En Visual Basic, las columnas que tienen un entero sin signo de cuatro bytes (DBTYPE UI4) en el objeto Recordset devuelto por el mtodo OpenSchema en el objeto Connection, no se pueden

comparar con otras variables. Para obtener ms informacin sobre los tipos de datos OLE DB, vea el captulo 13 y el apndice A de la Referencia del programador de Microsoft OLE DB. Utilizar el objeto Connection Un objeto Connection representa una sesin nica con un origen de datos. En el caso de un sistema de base de datos cliente/servidor, puede ser equivalente a una conexin de red real con el servidor. Segn la funcionalidad admitida por el proveedor, algunas colecciones, mtodos o propiedades de un objeto Connection podran no estar disponibles. Antes de abrir un objeto Connection, debe definir parte de la informacin sobre el origen de datos y el tipo de conexin. El parmetro ConnectionString del mtodo Open del objeto Connection (o la propiedad ConnectionString del objeto Connection) normalmente contiene la mayor parte de esta informacin. Una cadena de conexin es una cadena de caracteres que define un nmero variable de argumentos. Los argumentos, algunos requeridos por ADO y otros especficos del proveedor, contienen informacin que el objeto Connection debe tener para realizar su trabajo. Los argumentos que componen el parmetro ConnectionString se separan con caracteres de punto y coma (;). Nota Tambin puede especificar un nombre del origen de datos ODBC (DSN) o un archivo de vnculo de datos (UDL) en una cadena de conexin. Para obtener ms informacin acerca de los DSN, vea Orgenes de datos en la primera parte de Referencia del programador de ODBC. Para obtener ms informacin acerca de los UDL, vea Introduccin a la API de vnculo de datos en la Referencia del programador de OLE DB. Realizar una conexin Para conectarse a un origen de datos, debe especificar una cadena de conexin, cuyos parmetros podran ser distintos para cada proveedor y para cada origen de datos. Para obtener ms informacin, vea Crear la cadena de conexin. Lo ms normal es que ADO abra una conexin utilizando el mtodo Open del objeto Connection. La sintaxis del mtodo Open se muestra aqu:

Dim connection as New ADODB.Connection connection.Open ConnectionString, UserID, Password, OpenOptions

Otra posibilidad es invocar una tcnica de acceso directo, Recordset.Open, para abrir una conexin implcita y emitir un comando a travs de esa conexin en una sola operacin. Para hacerlo, pase una cadena de conexin vlida como argumento ActiveConnection para el mtodo Open. Esta es la sintaxis para cada mtodo en Visual Basic:

Dim recordset as ADODB.Recordset Set recordset = New ADODB.Recordset recordset.Open Source, ActiveConnection, CursorType, LockType, Options

Nota

Cundo conviene utilizar un objeto Connection y cuando el acceso directo Recordset.Open? Utilice el objeto Connection si piensa abrir ms de un conjunto de registros, o cuando tenga que ejecutar varios comandos. ADO sigue creando una conexin implcitamente cuando se utiliza el acceso directo Recordset.Open. Crear la cadena de conexin ADO admite directamente cinco argumentos en una cadena de conexin. ADO pasa otros argumentos al proveedor que se menciona en el argumento Provider sin ningn procesamiento. Argumento Descripcin Provider Especifica el nombre de un proveedor para usarlo para la conexin. File Name Indica el nombre de un archivo especfico del proveedor (por ejemplo, un objeto de origen de datos conservado) que contiene informacin de conexin preestablecida. URL Especifica la cadena de conexin como una direccin URL absoluta que identifica un recurso, como un archivo o un directorio. Remote Provider Especifica el nombre de un proveedor para usarlo al abrir una conexin de cliente (slo Servicio de datos remoto). Remote Server Especifica el nombre de la ruta de acceso del servidor que se utilizar al abrir una conexin de cliente (slo Servicio de datos remoto). Nota En los ejemplos siguientes y en toda la Gua del programador de ADO, se utiliza el identificador de usuario "MyId" con la contrasea "123aBc" para autenticacin en el servidor. Debe sustituir estos valores con credenciales de inicio de sesin vlidas para su servidor. Sustituya tambin el nombre de su servidor por "MySqlServer". La aplicacin HelloData del captulo 1 utiliz la cadena de conexin siguiente:
m_sConnStr = "Provider='SQLOLEDB';Data Source='MySqlServer';" & _ "Initial Catalog='Northwind';Integrated Security='SSPI';"

El nico parmetro de ADO que se proporcion en esta cadena de conexin fue "Provider=SQLOLEDB ", que indic el proveedor de Microsoft OLE DB para SQL Server. Para determinar otros parmetros vlidos que se pueden pasar en la cadena de conexin, se puede consultar la documentacin de cada proveedor. Segn la documentacin de OLE DB Provider para SQL Server, se puede sustituir "Server" por el parmetro Data Source y "Database" por el parmetro Initial Catalog. Por tanto, la cadena de conexin siguiente generara resultados idnticos a la primera:
m_sConnStr = "Provider='SQLOLEDB';Server='MySqlServer';" & _ "Database='Northwind';Integrated Security='SSPI';"

Para abrir la conexin, simplemente pase la cadena de conexin como primer argumento en el mtodo Open del objeto Connection:
objConn.Open m_sConnStr

Tambin es posible proporcionar una gran parte de esta informacin estableciendo propiedades del objeto Connection antes de abrir la conexin. Por ejemplo, se podra lograr el mismo efecto que con la cadena de conexin anterior utilizando el cdigo siguiente:
With objConn .Provider = "SQLOLEDB"

.DefaultDatabase = "Northwind" .Properties("Data Source") = "MySqlServer" .Properties("Integrated Security") = "SSPI" .Open End With

Controlar transacciones Una transaccin delimita el principio y el final de una serie de operaciones de acceso a datos que ocurren durante una conexin. Dependiendo de las funcionalidades transaccionales de un origen de datos, el objeto Connection tambin permite crear y administrar transacciones. Por ejemplo, si utiliza el proveedor de Microsoft OLE DB para SQL Server para tener acceso a una base de datos en Microsoft SQL Server 2000, puede crear varias transacciones anidadas para los comandos que ejecute. ADO garantiza que los cambios en un origen de datos resultantes de operaciones en una transaccin se producen correctamente en conjunto o no en absoluto. Si cancela la transaccin o si se produce un error en una de sus operaciones, el resultado final ser equivalente a que no se haya producido ninguna de las operaciones en la transaccin. El origen de datos se mantendr igual que antes de que se iniciase la transaccin. El modelo de objetos ADO no incluye transacciones explcitamente, pero las representa con un conjunto de mtodos de objetos Connection (BeginTrans, CommitTrans y RollbackTrans). Para obtener ms informacin acerca de transacciones, vea el Captulo 5: Actualizar y almacenar datos.. Utilizar el objeto Command Despus de conectar con un origen de datos, debe ejecutar peticiones en l para obtener conjuntos de resultados. ADO encapsula este tipo de funcionalidad de comando en el objeto Command. Puede usar el objeto Command para solicitar cualquier tipo de operacin del proveedor, suponiendo que ste pueda interpretar correctamente la cadena del comando. Una operacin comn para los proveedores de datos es la de consultar una base de datos y devolver registros en un objeto Recordset. Los objetos Recordset se tratarn ms adelante en ste y otros captulos; por ahora, considrelos como herramientas para contener y ver conjuntos de resultados. Al igual que ocurre con muchos objetos ADO, segn la funcionalidad del proveedor, algunas colecciones de objetos Command, mtodos o propiedades podran generar errores al hacer referencia a ellos. No siempre es necesario crear un objeto Command para ejecutar un comando en un origen de datos. Puede utilizar el mtodo Execute en el objeto Connection o el mtodo Open en el objeto Recordset. Sin embargo, debe usar un objeto Command si necesita volver a usar un comando en el cdigo o si debe pasar informacin detallada de parmetros con el comando. Estos escenarios se describen con ms detalle posteriormente en este captulo. Nota Algunos objetos Command pueden devolver un conjunto de resultados como una secuencia binaria o un nico registro, en vez de un objeto Recordset, si el proveedor admite esa posibilidad. Adems, algunos objetos Command no devuelven ningn conjunto de resultados (por ejemplo, una consulta

Update de SQL). Este captulo tratar el escenario ms tpico: ejecutar objetos Command que devuelven resultados en un objeto Recordset. Para obtener ms informacin acerca de los resultados devueltos en objetos Record o Stream, vea Captulo 10: Objetos Record y Stream. Descripcin general del objeto Command Con las colecciones, los mtodos y las propiedades de un objeto Command, puede hacer lo siguiente: Definir el texto ejecutable del comando (por ejemplo, una instruccin SQL o un procedimiento almacenado) utilizando la propiedad CommandText. Definir consultas parametrizadas o argumentos de procedimientos almacenados utilizando objetos Parameter y la coleccin Parameters. Ejecutar un comando y devolver un objeto Recordset, si procede, usando el mtodo Execute. Especificar el tipo de comando mediante la propiedad CommandType antes de la ejecucin para optimizar el rendimiento. Controlar si el proveedor guarda una versin preparada (o compilada) del comando antes de la ejecucin mediante la propiedad Prepared. Establecer el nmero de segundos que esperar un proveedor para la ejecucin de un comando mediante la propiedad CommandTimeout. Asociar una conexin abierta con un objeto Command estableciendo su propiedad ActiveConnection. Establecer la propiedad Name para identificar el objeto Command como un mtodo en el objeto Connection asociado. Pasar un objeto Command a la propiedad Source de un conjunto de registros para obtener datos. Crear y ejecutar un comando sencillo Aunque no es un uso habitual del objeto Command, el cdigo siguiente muestra el mtodo bsico para usar este objeto con el fin de ejecutar un comando en un origen de datos. En este caso, se trata de un comando que devuelve filas, por tanto, devuelve los resultados de la ejecucin del comando en un objeto Recordset.
'BeginBasicCmd On Error GoTo ErrHandler: Dim objConn As New ADODB.Connection Dim objCmd As New ADODB.Command Dim objRs As New ADODB.Recordset objCmd.CommandText = "SELECT OrderID, OrderDate, " & _ "RequiredDate, ShippedDate " & _ "FROM Orders " & _ "WHERE CustomerID = 'ALFKI' " & _ "ORDER BY OrderID" objCmd.CommandType = adCmdText ' Connect to the data source. Set objConn = GetNewConnection objCmd.ActiveConnection = objConn ' Execute once and display...

Set objRs = objCmd.Execute Debug.Print "ALFKI" Do While Not objRs.EOF Debug.Print vbTab & objRs(0) & vbTab & objRs(1) & vbTab & _ objRs(2) & vbTab & objRs(3) objRs.MoveNext Loop 'clean up objRs.Close objConn.Close Set objRs = Nothing Set objConn = Nothing Set objCmd = Nothing Exit Sub ErrHandler: 'clean up If objRs.State = adStateOpen Then objRs.Close End If If objConn.State = adStateOpen Then objConn.Close End If Set objRs = Nothing Set objConn = Nothing Set objCmd = Nothing If Err <> 0 Then MsgBox Err.Source & "-->" & Err.Description, , "Error" End If 'EndBasicCmd

El comando que se va a ejecutar se especifica con la propiedad CommandText. Nota Son varios los ejemplos de esta seccin que llaman a una funcin de utilidad, GetNewConnection, para establecer una conexin con el proveedor de datos. Para evitar la redundancia, aparece slo una vez:

'BeginNewConnection Private Function GetNewConnection() As ADODB.Connection Dim oCn As New ADODB.Connection Dim sCnStr As String sCnStr = "Provider='SQLOLEDB';Data Source='MySqlServer';" & _ "Integrated Security='SSPI';Database='Northwind';" oCn.Open sCnStr If oCn.State = adStateOpen Then Set GetNewConnection = oCn End If

End Function 'EndNewConnection

Parmetros del objeto Command En el ejemplo siguiente, se muestra un uso ms interesante para el objeto Command. En el ejemplo, el texto del comando SQL se ha modificado para hacerlo parametrizado. De este modo, se puede volver a utilizar el comando, pasando un valor diferente para el parmetro cada vez. Dado que la propiedad Prepared del objeto Command se ha establecido en True, ADO requerir que el proveedor compile el comando especificado en CommandText antes de ejecutarlo por primera vez. Tambin guardar el comando compilado en memoria. Esto ralentiza ligeramente la ejecucin del comando la primera vez que se ejecuta, debido a la sobrecarga necesaria para prepararlo, pero tiene como consecuencia una mejora del rendimiento cada vez que se vuelve a llamar al comando posteriormente. Por tanto, los comandos slo se deberan preparar si se van a utilizar ms de una vez.
'BeginManualParamCmd On Error GoTo ErrHandler: Dim Dim Dim Dim objConn As New ADODB.Connection objCmd As New ADODB.Command objParm1 As New ADODB.Parameter objRs As New ADODB.Recordset

' Set the CommandText as a parameterized SQL query. objCmd.CommandText = "SELECT OrderID, OrderDate, " & _ "RequiredDate, ShippedDate " & _ "FROM Orders " & _ "WHERE CustomerID = ? " & _ "ORDER BY OrderID" objCmd.CommandType = adCmdText ' Prepare command since we will be executing it more than once. objCmd.Prepared = True ' Create new parameter for CustomerID. Initial value is ALFKI. Set objParm1 = objCmd.CreateParameter("CustId", adChar, _ adParamInput, 5, "ALFKI") objCmd.Parameters.Append objParm1 ' Connect to the data source. Set objConn = GetNewConnection objCmd.ActiveConnection = objConn ' Execute once and display... Set objRs = objCmd.Execute Debug.Print objParm1.Value Do While Not objRs.EOF Debug.Print vbTab & objRs(0) & vbTab & objRs(1) & vbTab & _ objRs(2) & vbTab & objRs(3) objRs.MoveNext Loop

' ...then set new param value, re-execute command, and display. objCmd("CustId") = "CACTU" Set objRs = objCmd.Execute Debug.Print objParm1.Value Do While Not objRs.EOF Debug.Print vbTab & objRs(0) & vbTab & objRs(1) & vbTab & _ objRs(2) & vbTab & objRs(3) objRs.MoveNext Loop 'clean up objRs.Close objConn.Close Set objRs = Nothing Set objConn = Nothing Set objCmd = Nothing Set objParm1 = Nothing Exit Sub ErrHandler: 'clean up If objRs.State = adStateOpen Then objRs.Close End If If objConn.State = adStateOpen Then objConn.Close End If Set Set Set Set objRs = Nothing objConn = Nothing objCmd = Nothing objParm1 = Nothing

If Err <> 0 Then MsgBox Err.Source & "-->" & Err.Description, , "Error" End If 'EndManualParamCmd

No todos los proveedores admiten comandos preparados. Si el proveedor no admite la preparacin de comandos, podra devolver un error en cuanto esta propiedad se estableciese en True. Si no devuelve un error, omite la solicitud de preparar el comando y establece la propiedad Prepared en False. Llamar a un procedimiento almacenado con un comando Tambin puede utilizar un comando cuando llame a un procedimiento almacenado. El cdigo siguiente llama a un procedimiento almacenado en la base de datos de ejemplo Neptuno, denominado CustOrdersOrders, que se define como se indica a continuacin:
CREATE PROCEDURE CustOrdersOrders @CustomerID nchar(5) AS SELECT OrderID, OrderDate, RequiredDate, ShippedDate FROM Orders WHERE CustomerID = @CustomerID ORDER BY OrderID

Este procedimiento almacenado es similar al comando utilizado en Parmetros del objeto Command, en cuanto a que toma un parmetro identificador de cliente y devuelve informacin sobre los pedidos de ese cliente. El cdigo siguiente utiliza este procedimiento almacenado como origen para un conjunto de registros de ADO. El uso del procedimiento almacenado le permite tener acceso a otra funcionalidad de ADO: el mtodo Refresh de la coleccin Parameters. Utilizando este mtodo, ADO puede rellenar automticamente toda la informacin acerca de los parmetros que requiere el comando en tiempo de ejecucin. El uso de esta tcnica afecta negativamente al rendimiento, puesto que ADO debe consultar informacin acerca de los parmetros en el origen de datos. Existen otras diferencias importantes entre el cdigo de este ejemplo y el cdigo en Parmetros del objeto Command, donde los parmetros se introdujeron manualmente. En primer lugar, este cdigo no establece la propiedad Prepared en True porque es un procedimiento almacenado de SQL Server y est precompilado por definicin. En segundo lugar, la propiedad CommandType del objeto Command se cambi a adCmdStoredProc en el segundo ejemplo para informar a ADO de que el comando era un procedimiento almacenado.
'BeginAutoParamCmd On Error GoTo ErrHandler: Dim Dim Dim Dim objConn As New ADODB.Connection objCmd As New ADODB.Command objParm1 As New ADODB.Parameter objRs As New ADODB.Recordset

' Set CommandText equal to the stored procedure name. objCmd.CommandText = "CustOrdersOrders" objCmd.CommandType = adCmdStoredProc ' Connect to the data source. Set objConn = GetNewConnection objCmd.ActiveConnection = objConn ' Automatically fill in parameter info from stored procedure. objCmd.Parameters.Refresh ' Set the param value. objCmd(1) = "ALFKI" ' Execute once and display... Set objRs = objCmd.Execute Debug.Print objParm1.Value Do While Not objRs.EOF Debug.Print vbTab & objRs(0) & vbTab & objRs(1) & vbTab & _ objRs(2) & vbTab & objRs(3) objRs.MoveNext Loop ' ...then set new param value, re-execute command, and display. objCmd(1) = "CACTU" Set objRs = objCmd.Execute

Debug.Print objParm1.Value Do While Not objRs.EOF Debug.Print vbTab & objRs(0) & vbTab & objRs(1) & vbTab & _ objRs(2) & vbTab & objRs(3) objRs.MoveNext Loop 'clean up objRs.Close objConn.Close Set objRs = Nothing Set objConn = Nothing Set objCmd = Nothing Set objParm1 = Nothing Exit Sub ErrHandler: 'clean up If objRs.State = adStateOpen Then objRs.Close End If If objConn.State = adStateOpen Then objConn.Close End If Set Set Set Set objRs = Nothing objConn = Nothing objCmd = Nothing objParm1 = Nothing

If Err <> 0 Then MsgBox Err.Source & "-->" & Err.Description, , "Error" End If 'EndAutoParamCmd

Comandos con nombre Se puede establecer la propiedad Name en un objeto Command y despus, ejecutar el comando llamndolo como si fuese un mtodo para la propiedad ActiveConnection del objeto Command. Esto se muestra en el ejemplo siguiente, en el que el comando se denomina GetCustomers. Observe que el cdigo pasa un objeto Recordset declarado y del que se cre una instancia al "mtodo" GetCustomers. Tambin se pueden pasar parmetros al "mtodo" si as lo requiere el comando.
'BeginNamedCmd On Error GoTo ErrHandler: Dim objConn As New ADODB.Connection Dim objCmd As New ADODB.Command Dim objRs As New ADODB.Recordset ' Connect to the data source. Set objConn = GetNewConnection objCmd.CommandText = "SELECT CustomerID, CompanyName FROM Customers" objCmd.CommandType = adCmdText

'Name the command. objCmd.Name = "GetCustomers" objCmd.ActiveConnection = objConn ' Execute using Command.Name from the Connection. objConn.GetCustomers objRs ' Display. Do While Not objRs.EOF Debug.Print objRs(0) & vbTab & objRs(1) objRs.MoveNext Loop 'clean up objRs.Close objConn.Close Set objRs = Nothing Set objConn = Nothing Set objCmd = Nothing Exit Sub ErrHandler: 'clean up If objRs.State = adStateOpen Then objRs.Close End If If objConn.State = adStateOpen Then objConn.Close End If Set objRs = Nothing Set objConn = Nothing Set objCmd = Nothing If Err <> 0 Then MsgBox Err.Source & "-->" & Err.Description, , "Error" End If 'EndNamedCmd

Agregar datos a un conjunto de registros Probablemente, el objeto Recordset es el ms usado de los objetos de ADO. En ADO, un conjunto de registros se entiende mejor como la combinacin de un conjunto de resultados de un origen de datos y sus comportamientos de cursor asociados. As pues, puede colocar datos en un conjunto de registros y luego utilizar los mtodos y las propiedades del conjunto de registros para desplazarse por las filas de datos, ver los valores de las filas y manipular de otras maneras el conjunto de resultados. Esta seccin se centra en agregar datos al objeto Recordset. Para obtener informacin acerca de la navegacin por los datos o la actualizacin de los datos, vea el Captulo 4: Modificar datos y el Captulo 5: Actualizar y almacenar datos. No siempre son necesarias las caractersticas avanzadas

de un objeto Command para agregar un conjunto de resultados a un objeto Recordset. A menudo, se puede ejecutar el comando si establece la propiedad Origen para el objeto Recordset o pasa una cadena de comandos al mtodo Open del objeto Recordset. Hay diversas formas de agregar datos a un conjunto de registros desde un origen de datos. La tcnica que se utilice depende de las necesidades de la aplicacin y de las caractersticas del proveedor.

Captulo 3: Examinar datos


El Captulo 2 explicaba cmo se recuperan datos de un origen de datos en forma de objeto Recordset. En este captulo se analizar con ms detalle el objeto Recordset, incluyendo la forma de navegar a travs de Recordset y ver sus datos. Los objetos Recordset tienen mtodos y propiedades que se disearon para facilitar el desplazamiento por ellos y examinar su contenido. En funcin de la funcionalidad admitida por el proveedor, algunas propiedades o mtodos de Recordset pueden no estar disponibles. Para continuar explorando el objeto Recordset, considere un objeto Recordset que sera devuelto por la base de datos de ejemplo Neptuno en Microsoft SQL Server 2000, usando el cdigo siguiente:
'BeginRsTour Public Sub RecordsetTour() On Error GoTo ErrHandler: Dim objRs As New ADODB.Recordset Dim strSQL As String strSQL = "SELECT ProductID, ProductName, UnitPrice FROM Products " & _ "WHERE CategoryID = 7" '7 = Produce objRs.Open strSQL, strConnStr, adOpenForwardOnly, _ adLockReadOnly, adCmdText 'Clean up objRs.Close Set objRs = Nothing Exit Sub ErrHandler: If Not objRs Is Nothing Then If objRs.State = adStateOpen Then objRs.Close Set objRs = Nothing End If If Err <> 0 Then MsgBox Err.Source & "-->" & Err.Description, , "Error" End If End Sub 'EndRsTour

Esta consulta SQL devuelve un objeto Recordset con cinco filas (registros) y tres columnas (campos). En la tabla siguiente se muestran los valores correspondientes a cada fila.
CAMPO Nombre = ProductID 7 14 28 51 74 0 CAMPO Nombre = ProductName Peras secas orgnicas del to Bob Cuajada de judas Col fermentada Rssle Manzanas secas Manjimup Queso de soja Longlife 1 CAMPO Nombre = UnitPrice 30,00 23,25 45,60 53,00 10,00 2

En la seccin siguiente se explicar cmo se localiza la posicin actual del cursor en este objeto Recordset de ejemplo. Ubicar el registro activo La posicin actual del cursor en el conjunto de registros delinea la posicin del registro activo. Suponiendo que el comando emitido devuelve resultados, el cursor se coloca automticamente en el primer registro cuando se llama al mtodo Open del conjunto de registros. As, con el conjunto de registros de ejemplo, el cursor estara en el primer registro: "Uncle Bob's Organic Dried Pears". Contar filas La propiedad RecordCount devuelve un valor Long que indica el nmero de registros del Recordset. Use la propiedad RecordCount para determinar cuntos registros hay en un objeto Recordset. La propiedad devuelve -1 cuando ADO no puede determinar el nmero de registros o si el proveedor o tipo de cursor no admite RecordCount. La lectura de la propiedad RecordCount de un Recordset cerrado causa un error. La propiedad RecordCount depende de las capacidades del proveedor y del tipo de cursor. La propiedad RecordCount devolver -1 para un cursor de slo avance, el recuento real para un cursor esttico o de conjunto de claves, y -1 o el recuento real para un cursor dinmico, en funcin del origen de datos. El Recordset de ejemplo presentado en Examinar datos devolver 1 porque se abri un cursor de slo avance. Para usar la propiedad RecordCount, debera abrir el Recordset con un cursor ms complejo (esttico o conjunto de claves). En algunos casos, puede que el proveedor o el cursor no puedan proporcionar el valor de RecordCount sin obtener primero todos los registros desde el origen de datos. Para forzar este tipo de bsqueda, llame al mtodo MoveLast de Recordset antes de llamar a RecordCount Si reemplazara la lnea de cdigo que llama al mtodo Open de Recordset por lo siguiente:
oRs.Open sSQL, sCnStr, adOpenStatic, adLockOptimistic, adCmdText

podra utilizar la propiedad RecordCount, ya que los cursores estticos del Proveedor de Microsoft OLE DB para SQL Server admiten RecordCount. Por ejemplo, el cdigo siguiente imprimir el nmero de registros devueltos por el comando a la ventana de depuracin, suponiendo que el cursor admita la propiedad RecordCount:
Debug.Print oRs.RecordCount ' Output: 4

A partir de este momento, se supone que se utilizan estas opciones ms eficaces (pero ms costosas) de tipo de cursor y bloqueo. Los lmites de un conjunto de registros Use las propiedades BOF y EOF para determinar si un objeto Recordset contiene registros o si se han sobrepasado los lmites de un objeto Recordset al moverse de un registro a otro. Considere BOF y EOF como registros "fantasma" situados al principio y al final del conjunto de registros. Trabajando con el conjunto de registros de ejemplo de Examinar datos, ahora tendra este aspecto:
IdProducto BOF 7 14 28 51 74 EOF Uncle Bob's Organic Dried Pears Tofu Rssle Sauerkraut Manjimup Dried Apples Longlife Tofu 30,0000 23,2500 45,6000 53,0000 10,0000 NombreProducto PrecioUnidad

La propiedad BOF devuelve True (-1) si la posicin del registro activo es anterior al primer registro y False (0) si la posicin del registro activo est en el primer registro o despus de l. La propiedad EOF devuelve True si la posicin del registro activo es posterior al ltimo registro y False si la posicin del registro activo est en el ltimo registro o antes de l. Si la propiedad BOF o EOF es True, no hay ningn registro activo, como se muestra en el cdigo siguiente:
If oRs.BOF And oRs.EOF Then ' Command returned no records. End If

Si se abre un objeto Recordset que no contiene ningn registro, las propiedades BOF y EOF se establecen en True y el valor de la propiedad RecordCount del objeto Recordset depender del tipo de cursor. Para cursores dinmicos, se devolver -1 (CursorType = adOpenDynamic) y, para otros cursores, se devolver 0. Si se abre un objeto Recordset que contiene al menos un registro, el primer registro es el activo y las propiedades BOF y EOF son False. Si se elimina el ltimo registro que queda en el objeto Recordset, el cursor queda en un estado indeterminado. Las propiedades BOF y EOF pueden permanecer en False hasta que se intente ajustar la posicin del registro activo, dependiendo del proveedor. Desplazarse por los datos Ahora que ha ejecutado un comando en el origen de datos y determinado que el conjunto de resultados contiene datos, puede moverse por los resultados mediante los mtodos de desplazamiento y las propiedades disponibles con el objeto Recordset. En los siguientes temas, se describe cmo usar estos mtodos y propiedades con el conjunto de registros de ejemplo:

Saltar a un registro Ms formas de moverse en un conjunto de registros Utilizar marcadores Utilizar pginas Colocacin de un conjunto de registros Saltar a un registro El mtodo Move permite avanzar o retroceder un nmero determinado de registros en el conjunto de registros utilizando la sintaxis siguiente:

oRs.Move NumRecords, Start

El mtodo Move se admite en todos los objetos Recordset. Si el argumento NumRecords es mayor que cero, la posicin de registro activo avanza (hacia el final del conjunto de registros). Si NumRecords es menor que cero, la posicin de registro activo retrocede (hacia el principio del conjunto de registros). Si la llamada a Move moviese la posicin del registro activo a un punto anterior al primer registro, ADO establecera el registro activo en la posicin anterior al primer registro del conjunto de registros (BOF es True). Si se intenta retroceder cuando la propiedad BOF ya es True, se produce un error. Si la llamada a Move moviese la posicin del registro activo a un punto posterior al ltimo registro, ADO establecera el registro activo en la posicin posterior al ltimo registro del conjunto de registros (EOF es True). Si se intenta avanzar cuando la propiedad EOF ya es True, se produce un error. Si se llama al mtodo Move desde un objeto Recordset vaco, se produce un error. Si se pasa un marcador en el argumento Start, el desplazamiento se realiza respecto al registro con este marcador, suponiendo que el objeto Recordset admite marcadores. Un marcador se obtiene usando la propiedad Bookmark. Si no se especifica, el desplazamiento se realiza respecto al registro activo. Si se utiliza la propiedad CacheSize para almacenar localmente en cach registros del proveedor, el paso de un argumento NumRecords que mueve la posicin del registro activo fuera del grupo actual de registros almacenados en cach provoca que ADO recupere un nuevo grupo de registros, a partir del registro de destino. La propiedad CacheSize determina el tamao del grupo recin recuperado y el registro de destino es el primer registro recuperado. Ms formas de moverse en un conjunto de registros Los cuatro mtodos siguientes sirven para moverse o desplazarse por el conjunto de registros: MoveFirst, MoveLast, MoveNext y MovePrevious (algunos de estos mtodos no estn disponibles con cursores de slo avance).

MoveFirst cambia la posicin del registro activo al primer registro del conjunto de registros.MoveLast cambia la posicin del registro activo al ltimo registro del conjunto de registros. Para utilizar MoveFirst o MoveLast, el objeto Recordset debe admitir marcadores o movimiento de cursor hacia atrs; de lo contrario, la llamada al mtodo generar un error. MoveNext hace avanzar una posicin el registro activo. Si est en el ltimo registro cuando llama a MoveNext, EOF se establece en True.MovePrevious hace retroceder una posicin el registro activo. Si est en el primer registro cuando llama a MovePrevious, BOF se establece en True. Es aconsejable revisar las propiedades EOF y BOF cuando se utilizan estos mtodos y devolver el cursor a una posicin vlida de registro activo si se sale de cualquier extremo del conjunto de registros, como se muestra aqu:
. . . oRs.MoveNext If oRs.EOF Then oRs.MoveLast . . .

O, en el caso del mtodo MovePrevious:


oRs.MovePrevious If oRs.BOF Then oRs.MoveFirst . . .

En casos en los que se filtra u ordena el conjunto de registros y se cambian los datos del registro activo, es posible que tambin cambie la posicin. En estos casos, el mtodo MoveNext funciona normalmente, pero hay que tener en cuenta que la posicin ha avanzado un registro respecto a la nueva posicin, no respecto a la antigua. Por ejemplo, si se cambian los datos del registro activo de tal manera que el registro se desplaza hasta el final del conjunto de registros ordenado, significa que la llamada a MoveNext provocar que ADO establezca el registro activo en la posicin posterior al ltimo registro del conjunto de registros (EOF = True). El comportamiento de los diversos mtodos Move del objeto Recordset depende, hasta cierto punto, de los datos contenidos en el conjunto de registros. Los nuevos registros agregados al conjunto de registros se agregan inicialmente en un orden determinado, que define el origen de datos y que puede depender implcita o explcitamente de los datos del nuevo registro. Por ejemplo, si se realiza una ordenacin o una combinacin dentro de la consulta que rellena el conjunto de registros, el nuevo registro se insertar en la posicin apropiada en el conjunto de registros. Si la ordenacin no se especifica explcitamente al crear el conjunto de registros, los cambios en la implementacin del origen de datos podran provocar que la ordenacin de las filas devueltas cambiase inadvertidamente. Adems, las funciones de ordenacin, filtro y edicin del conjunto de registros pueden afectar al orden y, posiblemente, a las filas del conjunto de registros que estarn visibles. Por lo tanto, a los mtodos MoveNext, MovePrevious, MoveFirst, MoveLast y Move les afectan otras operaciones que se realicen con el mismo conjunto de registros. ADO siempre tratar de mantener la posicin activa hasta que usted la mueva explcitamente, pero algunos cambios que se efecten pueden hacer que resulte difcil comprender los efectos de un movimiento posterior. Por ejemplo, si se llama a MoveFirst para colocarse en la primera fila de un conjunto de registros ordenado y se cambia la ordenacin de ascendente a descendente, se seguir estando en la misma fila, pero ahora ser la ltima del conjunto de registros.MoveFirst le llevar a otra fila (la nueva primera fila).

Otro ejemplo: si usted se sita en una fila determinada en medio de un conjunto de registros y llama a Delete y, a continuacin, llama a MoveNext, pasar a estar en el registro inmediatamente posterior al registro eliminado. Pero si llama a MovePrevious, el registro anterior al que se ha eliminado pasar a ser el registro activo, puesto que el registro eliminado ya no se considera perteneciente al conjunto de registros. Resulta especialmente complicado definir incoherentemente la semntica de movimientos para todos los proveedores, para mtodos que realizan desplazamientos respecto al registro activo (MovePrevious, MoveNext y Move) frente a cambiar datos del registro activo. Por ejemplo, si trabaja con un conjunto de registros ordenado y filtrado y cambia los datos del registro activo para que preceda a todos los dems registros, pero adems, los datos modificados ya no coinciden con el filtro, no queda claro dnde le llevar una operacin MoveNext. La conclusin ms cierta es que el movimiento relativo dentro de un conjunto de registros es ms arriesgado que el movimiento absoluto (como el uso de MoveFirst o MoveLast) cuando los datos cambian mientras se editan, agregan o eliminan registros. La ordenacin y el filtrado se deberan basar en una clave principal o un identificador, ya que este tipo de valor no debera cambiar. Mtodos MoveFirst, MoveLast, MoveNext y MovePrevious (ADO) Se desplaza al registro primero, ltimo, siguiente o anterior en el objeto Recordset especificado y convierte ese registro en el registro actual. Sintaxis
recordset.{MoveFirst | MoveLast | MoveNext | MovePrevious}

Comentarios Utilice el mtodo MoveFirst para mover la posicin de registro actual al primer registro del objeto Recordset. Utilice el mtodo MoveLast para mover la posicin de registro actual al ltimo registro del objeto Recordset. El objeto Recordset debe admitir marcadores o movimientos de cursor hacia atrs; en caso contrario, la llamada a este mtodo generar un error. Si se llama a MoveFirst o MoveLast cuando el objeto Recordset est vaco (el valor de BOF y de EOF es True), se generar un error. Utilice el mtodo MoveNext para avanzar un registro la posicin de registro actual (hacia el final del objeto Recordset). Si el ltimo registro es el registro actual y se llama al mtodo MoveNext, ADO establece el registro actual en la posicin situada detrs del ltimo registro del objeto Recordset (EOF es True). Si el valor de la propiedad EOF ya es True, cualquier intento de avanzar genera un error. En los casos en los que se filtr u orden el objeto Recordset y se modificaron los datos del actual registro, puede que tambin cambie la posicin. En esos casos, el mtodo MoveNext funciona normalmente, pero tenga en cuenta que la posicin avanzar un registro con respecto a la posicin nueva y no con respecto a la antigua posicin. Por ejemplo, si se cambian los datos del actual registro de modo que el registro se mueva hacia el final del objeto Recordset ordenado y se llama al mtodo MoveNext, ADO establecer el actual registro en la posicin situada detrs del ltimo registro del objeto Recordset (el valor de EOF es True).

Use el mtodo MovePrevious para retroceder un registro la posicin de registro actual (hacia el principio del objeto Recordset). El objeto Recordset debe admitir marcadores o movimientos de cursor hacia atrs; en caso contrario, la llamada al mtodo generar un error. Si el primer registro es el registro actual y se llama al mtodo MovePrevious, ADO establece el registro actual en la posicin situada delante del primer registro del objeto Recordset (el valor de BOF es True). Cualquier intento de retroceder cuando el valor de BOF ya es True genera un error. Si el objeto Recordset no admite marcadores o movimientos de cursor hacia atrs, el mtodo MovePrevious generar un error. Si el objeto Recordset es de solo avance y desea poder realizar desplazamientos tanto hacia adelante como hacia atrs, podr usar la propiedad CacheSize para crear una memoria cach de registros que admita movimientos de cursor hacia atrs mediante el mtodo Move. Dado que los registros almacenados en cach se cargan en la memoria, deber evitar almacenar en cach un nmero excesivo de registros. Puede llamar al mtodo MoveFirst en un objeto Recordset de solo avance; si lo hace, puede que el proveedor vuelva a ejecutar el comando que gener el objeto Recordset. Utilizar marcadores A menudo, es til volver directamente a un registro especfico despus de haberse movido por el conjunto de registros sin tener que desplazarse por cada registro y comparar valores. Por ejemplo, si se intenta buscar un registro mediante el mtodo Find pero la bsqueda no devuelve ningn registro, se le lleva automticamente a cualquier extremo del conjunto de registros. Si su proveedor los admite, se pueden utilizar marcadores para marcar la ubicacin propia antes de utilizar el mtodo Find, para poder regresar a esa ubicacin. Un marcador es un valor de tipo Variant que identifica un registro de un conjunto de registros de forma exclusiva. Tambin se puede usar una matriz de marcadores variant con el mtodo Filter del conjunto de registros para aplicar un filtro a un conjunto de registros seleccionados. Para obtener detalles acerca de esta tcnica, vea Filtrar los resultados en el tema Trabajar con objetos Recordset, ms adelante en este captulo. Se puede utilizar la propiedad Bookmark para obtener un marcador para un registro, o establecer el registro activo de un objeto Recordset en el registro identificado por un marcador vlido. El cdigo siguiente utiliza la propiedad Bookmark para establecer un marcador y, posteriormente, volver al registro del marcador despus de moverse por otros registros. Para determinar si un conjunto de registros admite marcadores, use el mtodo Supports.
'BeginBookmarkEg Dim varBookmark As Variant Dim blnCanBkmrk As Boolean objRs.Open adCmdText strSQL, strConnStr, adOpenStatic, adLockOptimistic,

If objRs.RecordCount > 4 Then objRs.Move 4 ' move to the fifth record blnCanBkmrk = objRs.Supports(adBookmark) If blnCanBkmrk = True Then varBookmark = objRs.Bookmark ' record the bookmark objRs.MoveLast ' move to a different record

objRs.Bookmark = varBookmark (sixth) record End If End If 'EndBookmarkEg

' return to the bookmarked

El mtodo Supports se describe posteriormente con ms detalle. Excepto en el caso de conjuntos de registros clonados, los marcadores son nicos para el conjunto de registros en el que se crearon, incluso si se utiliza el mismo comando. Esto significa que no se puede utilizar un marcador obtenido de un conjunto de registros para moverse al mismo registro en un segundo conjunto de registros abierto con el mismo comando. Supports (mtodo, ADO) Determina si el objeto Recordset especificado admite un determinado tipo de funcionalidad. Sintaxis boolean = recordset.Supports( CursorOptions )

Valor devuelto Devuelve un valor de tipo Boolean que indica si el proveedor admite todas las caractersticas identificadas por el argumento CursorOptions. Parmetros CursorOptions Expresin de tipo Long formada por uno o varios valores de CursorOptionEnum. Comentarios Use el mtodo Supports para determinar los tipos de funcionalidad compatibles con un objeto Recordset. Si el objeto Recordset es compatible con las caractersticas cuyas correspondientes constantes estn en CursorOptions, el mtodo Supports devuelve el valor True. En caso contrario, devuelve False. Nota Si bien el mtodo Supports devuelve True para una determinada funcionalidad, esto no garantiza que el proveedor tenga disponible la caracterstica en todas las circunstancias. El mtodo Supports devuelve simplemente un valor que indica si el proveedor admite la funcionalidad especificada, suponiendo que se cumplen ciertas condiciones. Por ejemplo, puede que el mtodo Supports indique que un objeto Recordset admita actualizaciones, aun cuando el cursor est basado en una combinacin de varias tablas, en las que algunas de las columnas no son actualizables. Trabajar con conjuntos de registros El objeto Recordset tiene caractersticas integradas para reorganizar el orden de los datos en el conjunto de resultados, para buscar un registro concreto segn los criterios especificados e, incluso, para optimizar aquellas operaciones de bsqueda mediante ndices. La disponibilidad de uso de estas caractersticas depende del proveedor y, en algunos casos, como en el de la propiedad Index, de la estructura del propio origen de datos.

Organizar los datos A menudo, la manera ms eficaz de ordenar los datos en un objeto Recordset consiste en especificar una clusula ORDER BY en el comando SQL usado para devolver los resultados. Sin embargo, podra ser necesario cambiar el orden de los datos en un objeto Recordset que ya se ha creado. Puede usar la propiedad Sort para establecer el orden en el que se recorren las filas de un objeto Recordset. Adems, la propiedad Filter determina cules son las filas a las que se puede tener acceso en ese recorrido. La propiedad Sort establece o devuelve un valor String que indica los nombres de campos del objeto Recordset por los que se debe ordenar. Cada nombre se separa por una coma, seguida opcionalmente de un espacio y la palabra clave ASC (que ordena el campo de forma ascendente) o DESC (que ordena el campo de forma descendente). De forma predeterminada, si no se especifica ninguna palabra clave, el campo se ordena de forma ascendente. La operacin de ordenacin es eficaz, ya que los datos no se reorganizan fsicamente, sino que el acceso a ellos se realiza simplemente en el orden especificado por un ndice. La propiedad Sort requiere que la propiedad CursorLocation se establezca en el valor adUseClient. Si no existe ningn ndice, se crear uno temporal para cada campo especificado en la propiedad Sort. Si se establece la propiedad Sort en una cadena vaca, las filas se restablecern a su orden original y se eliminarn los ndices temporales. No se eliminarn los ndices existentes. Suponga que un objeto Recordset contiene tres campos denominados firstName, middleInitial y lastName. Establezca la propiedad Sort en la cadena "
lastName DESC, firstName ASC

", que ordenar el objeto Recordset por apellidos en orden descendente y, a continuacin, por nombre en orden ascendente. La posible inicial media se omite. Las referencias a los campos en una cadena de criterios de ordenacin no se pueden denominar "ASC" o "DESC", ya que esos nombres entran en conflicto con las palabras clave ASC y DESC. Use un alias para un campo con un nombre conflictivo mediante la palabra clave AS en la consulta que devuelve el objeto Recordset. Para obtener ms detalles sobre cmo filtrar los objetos Recordset, vea Filtrar los resultados ms adelante en este tema. Buscar un registro especfico ADO proporciona los mtodos Find y Seek para buscar un registro determinado en un objeto Recordset. Diversos proveedores admiten el mtodo Find, pero se limita a criterios de bsqueda nico. El mtodo Seek permite la bsqueda con varios criterios, pero el nmero de proveedores que lo admiten es reducido. Los ndices de campos pueden mejorar mucho el rendimiento del mtodo Find y de las propiedades Sort y Filter del objeto Recordset. Puede crear un ndice interno para un objeto Field si establece su propiedad dinmica Optimize. Esta propiedad se agrega a la coleccin Properties del objeto Field al establecer la propiedad CursorLocation en el valor adUseClient. Recuerde que

este ndice es interno respecto a ADO, es decir, no se puede obtener acceso a l ni usarlo para ningn otro fin. Adems, este ndice es distinto de la propiedad Index del objeto Recordset. El mtodo Find busca rpidamente un valor en una columna (campo) de un objeto Recordset. La velocidad de operacin de este mtodo en una columna se puede mejorar, a menudo, mediante la propiedad Optimize para crear un ndice en esa columna. El mtodo Find limita la bsqueda al contenido de un campo. El mtodo Seek requiere un ndice y tiene tambin otras limitaciones. Si es necesario buscar en varios campos que no constituyan un ndice, o si su proveedor no admite ndices, puede limitar los resultados mediante la propiedad Filter del objeto Recordset. Find El mtodo Find busca en un objeto Recordset la fila que cumple un criterio especificado. Opcionalmente, es posible especificar la direccin de la bsqueda, la fila inicial y el desplazamiento desde sta. Si se cumple el criterio, la posicin de la fila actual se establece en el registro encontrado; de lo contrario, se establece al final o al principio del objeto Recordset, segn la direccin de bsqueda. Slo se puede especificar un nico nombre de columna para el criterio. Es decir, este mtodo no admite bsquedas en varias columnas. El operador de comparacin para el criterio puede ser ">" (mayor que), "<" (menor que), "=" (igual a), ">=" (mayor o igual que), "<=" (menor o igual que), "<>" (no es igual a) o "LIKE" (coincidencia de modelos). El valor del criterio puede ser una cadena, un nmero de punto flotante o una fecha. Los valores de cadena se delimitan mediante comillas sencillas o marcas "#" (signo de nmero); por ejemplo, "provincia = 'MA'"o "provincia = # WA#". Los valores de fecha se delimitan mediante marcas "#" (signo de nmero); por ejemplo, "fecha_inicial > #22/7/97#". Si el operador de comparacin es "like", el valor de cadena puede contener un asterisco (*) para que se busque una o varias apariciones de cualquier carcter o subcadena. Por ejemplo, "state like 'M*'" encuentra Maine y Massachusetts.Tambin se pueden utilizar asteriscos inicial y final para buscar una subcadena incluida en los valores. Por ejemplo, "state like '*as*' encuentra Alaska, Arkansas y Massachusetts. Se pueden utilizar asteriscos slo al final de la cadena; o bien, tanto al principio como al final de la cadena, como se ha indicado anteriormente. No se puede utilizar el asterisco como comodn inicial ('*str') o comodn incrustado ('s*r'). De lo contrario, se generar un error. Seek e Index Use el mtodo Seek junto con la propiedad Index si el proveedor subyacente admite ndices en el objeto Recordset. Use el mtodo Supports(adSeek) para determinar si el proveedor subyacente admite Seek, y el mtodo Supports(adIndex) para determinar si el proveedor admite ndices. Por ejemplo, el proveedor OLE DB para Microsoft Jet admite Seek e Index.

Si Seek no encuentra la fila deseada, no se produce ningn error y la fila se coloca al final del objeto Recordset. Establezca la propiedad Index en el ndice deseado antes de ejecutar este mtodo. Este mtodo se puede usar nicamente con cursores de servidor. Seek no se admite cuando el valor de la propiedad CursorLocation del objeto Recordset es adUseClient. Este mtodo se puede usar nicamente cuando el objeto Recordset se abri con el valor adCmdTableDirect de CommandTypeEnum. Filtrar los resultados El mtodo Find limita la bsqueda al contenido de un campo. El mtodo Seek requiere un ndice y tiene tambin otras limitaciones. Si es necesario buscar en varios campos que no constituyan un ndice, o si su proveedor no admite ndices, puede limitar los resultados mediante la propiedad Filter del objeto Recordset. Use la propiedad Filter para ocultar selectivamente los registros de un objeto Recordset. El objeto Recordset filtrado se convierte en el cursor actual; es decir, los registros que no cumplan los criterios de Filter no estn disponibles en el objeto Recordset hasta que se quite Filter. Otras propiedades que devuelven valores segn el cursor actual, como AbsolutePosition, AbsolutePage, RecordCount y PageCount, tambin se ven afectadas. Esto se debe a que, al establecer la propiedad Filter en un valor especfico, el registro actual pasa a ser el primer registro que cumple el nuevo valor. La propiedad Filter toma un argumento Variant. Este valor representa uno de los tres mtodos para utilizar esta propiedad: una cadena de criterio, una constante FilterGroupEnum o una matriz de marcadores. Para obtener ms informacin, vea Filtrar por una cadena de criterios, Filtrar por una constante y Filtrar por marcadores, ms adelante en este mismo tema. Nota Cuando se conocen los datos que se desean seleccionar, normalmente es ms eficiente abrir un objeto Recordset con una instruccin SQL que filtra, de hecho, el conjunto de resultados, en vez de utilizar la propiedad Filter. Para quitar un filtro de un objeto Recordset, use la constante adFilterNone. El establecimiento de la propiedad Filter en una cadena de longitud cero ("") tiene el mismo efecto que el uso de la constante adFilterNone. Filtrar por una cadena de criterios La cadena de criterios se compone de clusulas con el formato NombreCampo Operador Valor (por ejemplo,
"LastName = 'Smith'"

). Puede crear clusulas formadas concatenando clusulas individuales con AND (por ejemplo,
"LastName = 'Smith' AND FirstName = 'John'"

) y OR (por ejemplo,
"LastName = 'Smith' OR LastName = 'Jones'"

). Utilice las indicaciones siguientes para las cadenas de criterios: NombreCampo debe ser un nombre de campo vlido del objeto Recordset. Si el nombre de campo contiene espacios, debe ir entre corchetes. Operador debe ser uno de los siguientes operadores: <, >, <=, >=, <>, = o LIKE. Valor es el valor con el que comparar los valores de campo (por ejemplo,
'Smith'

,
#8/24/95#

,
12.345

o
$50.00

). Utilice comillas simples (') con las cadenas y los signos de nmero (
#

) con las fechas. Por lo que respecta a los nmeros, puede utilizar separadores decimales, signos de dlar y notacin cientfica. Si Operador es LIKE, Valor puede utilizar caracteres comodn. Slo se permiten como caracteres comodn el asterisco (*) y el signo de porcentaje (%), y deben ser el ltimo carcter de la cadena. Valor no puede ser nulo. Nota Para incluir comillas simples (') en Valor, utilice dos comillas simples para representar una. Por ejemplo, para filtrar por O'Malley, la cadena de criterios debe ser "col1 = 'O''Malley'" . Para incluir comillas simples al principio y al final del valor de filtro, ponga la cadena entre signos de nmero (#). Por ejemplo, para filtrar por '1', la cadena de criterios debe ser "col1 = #'1'#" . No se aplica ningn orden de prioridad entre AND y OR. Las clusulas se pueden agrupar entre parntesis. Sin embargo, no puede agrupar clusulas unidas por un operador OR y, a continuacin, unir el grupo a otra clusula con un operador AND, como se indica a continuacin:
(LastName = 'Smith' OR LastName = 'Jones') AND FirstName = 'John'

En su lugar, debera crear el filtro del siguiente modo:


(LastName = 'Smith' AND FirstName = 'John') OR (LastName = 'Jones' AND FirstName = 'John')

En una clusula LIKE, puede utilizar un carcter comodn al principio y al final del patrn (por ejemplo,
LastName Like '*mit*'

) o slo al final (
LastName Like 'Smit*'

). Filtrar por una constante Las constantes siguientes estn disponibles para filtrar objetos Recordset.
Constante adFilterAffectedRecords Descripcin Filtra de modo que slo se vean los registros afectados por la ltima llamada a Delete,

Resynch, UpdateBatch o CancelBatch. adFilterConflictingRecords adFilterFetchedRecords adFilterNone adFilterPendingRecords Filtra de modo que se vean los registros que no superaron la ltima actualizacin por lotes. Filtra de modo que se vean los registros almacenados en la memoria cach actual, es decir, los resultados de la ltima llamada para recuperar registros de la base de datos. Quita el filtro actual de modo que se puedan ver todos los registros. Filtra de modo que se vean slo los registros que han cambiado, pero que an no se han enviado al servidor. Slo se aplica al modo de actualizacin de proceso por lotes.

Las constantes de filtro facilitan la resolucin de conflictos de registros individuales durante el modo de actualizacin de proceso por lotes al permitir ver, por ejemplo, slo aquellos registros que se vieron afectados durante la ltima llamada al mtodo UpdateBatch, como se muestra en el ejemplo siguiente:
Constante adFilterAffectedRecords adFilterConflictingRecords adFilterFetchedRecords adFilterNone adFilterPendingRecords Descripcin Filtra de modo que slo se vean los registros afectados por la ltima llamada a Delete, Resynch, UpdateBatch o CancelBatch. Filtra de modo que se vean los registros que no superaron la ltima actualizacin por lotes. Filtra de modo que se vean los registros almacenados en la memoria cach actual, es decir, los resultados de la ltima llamada para recuperar registros de la base de datos. Quita el filtro actual de modo que se puedan ver todos los registros. Filtra de modo que se vean slo los registros que han cambiado, pero que an no se han enviado al servidor. Slo se aplica al modo de actualizacin de proceso por lotes.

Las constantes de filtro facilitan la resolucin de conflictos de registros individuales durante el modo de actualizacin de proceso por lotes al permitir ver, por ejemplo, slo aquellos registros que se vieron afectados durante la ltima llamada al mtodo UpdateBatch, como se muestra en el ejemplo siguiente:
'BeginDeleteGroup 'add some bogus records With objRs1 For i = 0 To 8 .AddNew .Fields("CompanyName") = "Shipper Number " & i + 1 .Fields("Phone") = "(425) 555-000" & (i + 1) .Update Next i 're-connect & update .ActiveConnection = GetNewConnection .UpdateBatch 'filter on newly added records .Filter = adFilterAffectedRecords Debug.Print "Deleting the " & .RecordCount & _ " records you just added." 'delete the newly added bogus records .Delete adAffectGroup .Filter = adFilterNone Debug.Print .RecordCount & " records remain." .Close End With 'EndDeleteGroup

Filtrar por marcadores Por ltimo, puede pasar una matriz Variant de marcadores a la propiedad Filter. El cursor resultante contendr solo aquellos registros cuyo marcador se pas a la propiedad. En el ejemplo de cdigo siguiente, se crea una matriz de marcadores a partir de los registros de un objeto Recordset que tienen una "B" en el campo ProductName. A continuacin, se pasa la matriz a la propiedad Filter y se muestra informacin acerca del objeto Recordset filtrado resultante.
'BeginFilterBkmk Dim vBkmkArray() As Variant Dim i As Integer 'Recordset created using "SELECT * FROM Products" as command. 'So, we will check to see if ProductName has a capital B, and 'if so, add to the array. i = 0 Do While Not objRs.EOF If InStr(1, objRs("ProductName"), "B") Then ReDim Preserve vBkmkArray(i) vBkmkArray(i) = objRs.Bookmark i = i + 1 Debug.Print objRs("ProductName") End If objRs.MoveNext Loop 'Filter using the array of bookmarks. objRs.Filter = vBkmkArray objRs.MoveFirst Do While Not objRs.EOF Debug.Print objRs("ProductName") objRs.MoveNext Loop 'EndFilterBkmk

Crear un clon de un objeto Recordset Use el mtodo Clone para crear varios objetos Recordset duplicados, sobre todo si desea mantener ms de un registro actual en un conjunto determinado de registros. El mtodo Clone es ms eficaz que crear y abrir un nuevo objeto Recordset con la misma definicin que el original. El registro actual de un clon recin creado se establece originalmente en el primer registro. El puntero del registro actual de un objeto Recordset clonado no est sincronizado con el original ni viceversa. Es posible navegar independientemente en cada objeto Recordset. Los cambios realizados en un objeto Recordset se ven en todos sus duplicados, independientemente del tipo de cursor. Sin embargo, despus de ejecutar Requery en el objeto Recordset original, los duplicados ya no estarn sincronizados con el original. Al cerrar el objeto Recordset original, no se cierran sus copias; como tampoco se cierra el original ni ninguna de las dems copias al cerrarse una copia.

Se puede clonar un objeto Recordset slo si admite marcadores. Los valores de los marcadores son intercambiables; es decir, una referencia de marcador de un objeto Recordset hace referencia al mismo registro en todos sus clones. Utilizar pginas Use la propiedad PageCount para determinar cuntas pginas de datos contiene el objeto Recordset. Las pginas son grupos de registros cuyo tamao es igual al valor de la propiedad PageSize. Incluso aunque la ltima pgina est incompleta porque haya menos registros que el valor de PageSize, cuenta como una pgina ms en el valor PageCount. Si el objeto Recordset no admite esta propiedad, PageCount ser -1, que significa que PageCount no se puede determinar. Utilice la propiedad PageSize para determinar cuntos registros componen una pgina lgica de datos. El establecimiento de un tamao de pgina permite utilizar la propiedad AbsolutePage para moverse al primer registro de una pgina determinada. Esto es til en escenarios de servidor Web cuando se desea permitir al usuario que se desplace por los datos de las pginas para ver un nmero determinado de registros a la vez. Esta propiedad se puede establecer en cualquier momento y su valor se utilizar para calcular la ubicacin del primer registro de una pgina determinada. Utilice la propiedad AbsolutePage para identificar el nmero de pgina en el que se encuentra el registro activo. De nuevo, el proveedor debe admitir la funcionalidad adecuada para que esta propiedad est disponible. AbsolutePage es de base uno y es igual a 1 cuando el registro activo es el primero del conjunto de registros. Configure esta propiedad para desplazarse al primer registro de una pgina determinada. Obtenga el nmero total de pginas a partir de la propiedad NmeroDePginas (PageCount). Colocacin de un conjunto de registros Use la propiedad AbsolutePosition para desplazarse a un registro basndose en su posicin ordinal en el objeto Recordset, o bien, para especificar la posicin ordinal del registro actual. El proveedor debe admitir la funcionalidad adecuada para que esta propiedad est disponible. AbsolutePosition es de base uno y es igual a 1 cuando el registro activo es el primero del conjunto de registros. Como se indic previamente, el nmero total de registros del objeto Recordset se puede obtener a partir de la propiedad RecordCount. Cuando se establece la propiedad AbsolutePosition, incluso aunque sea en un registro en la cach actual, ADO vuelve a cargar la cach con un nuevo grupo de registros empezando por el registro que se haya especificado. La propiedad CacheSize determina el tamao de este grupo. Nota No es aconsejable usar la propiedad AbsolutePosition como nmero de registro suplente. La posicin de un registro determinado cambia cuando se elimina un registro anterior. Adems, no se tiene la certeza de que un registro dado tenga el mismo valor de AbsolutePosition si se vuelve a consultar y a abrir el objeto Recordset. Los marcadores son el mtodo recomendado para retener

cierta posicin y volver a ella, y son la nica manera de establecer un posicionamiento a travs de todos los tipos de objetos Recordset. Estructura de un objeto Recordset Cada objeto Recordset tiene una coleccin Fields que consta de uno o varios objetos Field. Un objeto Field suele representar una columna de tabla. En los temas siguientes, se detallar cmo navegar por la coleccin Fields y obtener informacin acerca de cada campo. Despus, se explicar qu tipo de informacin se encuentra disponible a travs del objeto Field y cmo usarla. La coleccin Fields El objeto Field Trabajar con objetos Recordset

Fields (coleccin) La coleccin Fields es una de las colecciones intrnsecas de ADO. Una coleccin es un conjunto ordenado de elementos a los que se puede hacer referencia como unidad. La coleccin Fields contiene un objeto Field para cada campo (columna) del conjunto de registros. Igual que todas las colecciones de ADO, tiene las propiedades Count e Item, as como los mtodos Append y Refresh. Tambin tiene los mtodos CancelUpdate, Delete, Resync y Update, que no estn disponibles para otras colecciones de ADO. Examinar la coleccin Fields Considere la coleccin Fields del conjunto de registros de ejemplo que se introdujo en este captulo. El conjunto de registros de ejemplo se deriv de la instruccin SQL:
SELECT ProductID, ProductName, UnitPrice FROM Products WHERE CategoryID = 7

Por tanto, se deberan observar tres campos en la coleccin Fields del conjunto de registros.
'BeginWalkFields Dim objFields As ADODB.Fields objRs.Open adCmdText strSQL, strConnStr, adOpenForwardOnly, adLockReadOnly,

Set objFields = objRs.Fields For intLoop = 0 To (objFields.Count - 1) Debug.Print objFields.Item(intLoop).Name Next 'EndWalkFields

Este cdigo simplemente determina el nmero de objetos Field que contiene la coleccin Fields utilizando la propiedad Contar y recorre en bucle la coleccin, para devolver el valor de la propiedad Name para cada objeto Field. Se pueden utilizar muchas ms propiedades de campo para obtener informacin acerca de un campo. Para obtener ms informacin acerca de las consultas en un campo, vea El objeto Field. Contar columnas

Como cabe esperar, la propiedad Contar devuelve la cantidad real de objetos Field contenidos en la coleccin Fields. Dado que la numeracin de elementos de una coleccin empieza por cero, los bucles siempre se deben codificar a partir del elemento cero y hasta el valor de la propiedad Contar menos 1. Si se utiliza Microsoft Visual Basic y se desea recorrer en bucle los elementos de una coleccin sin comprobar la propiedad Contar, use el comando For Each...Next. Si la propiedad Count es cero, significa que no hay ningn objeto en la coleccin. Obtener el campo Al igual que ocurre con cualquier coleccin de ADO, la propiedad Item es la predeterminada de la coleccin. Devuelve el objeto Field individual especificado por el nombre o el ndice que se le pasa. Por tanto, las instrucciones siguientes son equivalentes para el conjunto de registros de ejemplo:
objField objField objField objField = = = = objRecordset.Fields.Item("ProductID") objRecordset.Fields("ProductID") objRecordset.Fields.Item(0) objRecordset.Fields(0)

Si estos mtodos son equivalentes, cul es el mejor? Depende. El uso de un ndice para recuperar un campo de la coleccin es ms rpido porque obtiene acceso al campo directamente, sin tener que realizar una bsqueda en cadenas. Por otra parte, se debe conocer el orden de los campos dentro de la coleccin y, si cambia el orden, se tendr que cambiar la referencia al ndice del campo siempre que aparezca. Aunque es un mtodo un poco ms lento, el uso del nombre del campo es ms flexible porque no depende del orden de los campos en la coleccin. Utilizar el mtodo Refresh Al contrario que en otras colecciones de ADO, el uso del mtodo Refresh con la coleccin Fields no tiene efectos visibles. Para recuperar cambios de la estructura de la base de datos subyacente, se debe usar el mtodo Requery o, si el objeto Recordset no admite marcadores, el mtodo MoveFirst, que provocar que se ejecute otra vez el comando para el proveedor. Agregar campos a un conjunto de registros El mtodo Append se utiliza para agregar campos a un conjunto de registros. El mtodo Append se puede utilizar para fabricar un conjunto de registros mediante programacin sin abrir una conexin con un origen de datos. Si se llama al mtodo Append en la coleccin Fields de un conjunto de registros abierto o en un conjunto de registros donde se ha configurado la propiedad ActiveConnection, se producir un error en tiempo de ejecucin. Slo se pueden anexar campos a un conjunto de registros que no est abierto y que an no se haya conectado a un origen de datos. No obstante, para especificar valores para los campos recin anexados, primero se debe abrir el conjunto de registros. Con frecuencia, los programadores necesitan una ubicacin para almacenar temporalmente algunos datos, o desean que ciertos datos se comporten como si procediesen de un servidor, para que puedan participar en enlaces de datos en una interfaz de usuario. ADO (junto con el servicio de cursores de Microsoft para OLE DB) permite al programador crear un objeto Recordset vaco especificando informacin de columnas y llamando a Open. En el siguiente ejemplo, se anexan tres nuevos campos a un nuevo objeto Recordset. A continuacin, se abre el conjunto de registros, se agregan dos nuevos registros y se conserva el conjunto de registros en un archivo (para obtener ms informacin acerca de la persistencia de conjuntos de registros, vea el Captulo 5: Actualizar y almacenar datos).
'BeginFabricate Dim objRs As New ADODB.Recordset With objRs.Fields

.Append "StudentID", adChar, 11, adFldUpdatable .Append "FullName", adVarChar, 50, adFldUpdatable .Append "PhoneNmbr", adVarChar, 20, adFldUpdatable End With With objRs .Open .AddNew .Fields(0) = "123-45-6789" .Fields(1) = "John Doe" .Fields(2) = "(425) 555-5555" .Update .AddNew .Fields(0) = "123-45-6780" .Fields(1) = "Jane Doe" .Fields(2) = "(615) 555-1212" .Update End With objRs.Save App.Path & "\FabriTest.adtg", adPersistADTG objRs.Close 'EndFabricate

El uso del mtodo Append de Fields difiere entre el objeto Recordset y el objeto Record. Para obtener ms informacin acerca del objeto Record, vea el Captulo 10: Objetos Record y Stream. El objeto Field Cada objeto Field suele corresponder a una columna en una tabla de la base de datos. Sin embargo, un campo tambin puede representar un puntero a otro conjunto de registros, denominado captulo. Las excepciones, como las columnas de captulo, se tratarn ms adelante en esta gua. Utilice la propiedad Valor de objetos Field para establecer o devolver datos para el registro activo. Dependiendo de la funcionalidad que exponga el proveedor, es posible que algunas colecciones, mtodos o propiedades de un objeto Field no estn disponibles. Con las colecciones, los mtodos y las propiedades de un objeto Field, puede hacer lo siguiente: Devolver el nombre de un campo usando la propiedad Name. Ver o cambiar los datos del campo utilizando la propiedad Valor.Valor es la propiedad predeterminada del objeto Field. Devolver las caractersticas bsicas de un campo mediante las propiedades Tipo, Precision y NumericScale. Devolver el tamao declarado de un campo mediante la propiedad DefinedSize. Devolver el tamao real de los datos de un campo dado mediante la propiedad ActualSize. Determinar qu tipos de funcionalidad se admiten para un campo dado utilizando la propiedad Attributes y la coleccin Properties. Manipular los valores de campos que contienen datos de caracteres Long o binarios largos utilizando los mtodos AppendChunk y GetChunk.

Resolver discrepancias en valores de campo durante una actualizacin por lotes (si el proveedor admite actualizaciones por lotes) utilizando las propiedades OriginalValue y UnderlyingValue. Describir un campo Los temas que siguen tratan sobre propiedades del objeto Field que representan informacin que describe el propio objeto Field (es decir, metadatos acerca del campo). Esta informacin puede servir para determinar mucho sobre el esquema del conjunto de registros. Estas propiedades son Tipo, DefinedSize y ActualSize, Name, y NumericScale y Precision. Descubrir el tipo de datos La propiedad Tipo indica el tipo de datos del campo. Las constantes enumeradas de tipos de datos que se admiten con ADO se describen en DataTypeEnum en la Referencia del programador de ADO. Para tipos numricos de coma flotante como adNumeric, se puede obtener ms informacin. La propiedad NumericScale indica cuntos dgitos a la derecha del separador decimal se utilizarn para representar valores para el campo. La propiedad Precision especifica el nmero mximo de dgitos utilizados para representar valores para el campo. Determinar el tamao del campo Utilice la propiedad DefinedSize para determinar la capacidad de datos de un objeto Field. Utilice la propiedad ActualSize para devolver la longitud real del valor de un objeto Field. Para todos los campos, la propiedad ActualSize es de slo lectura. Si ADO no puede determinar la longitud del valor del objeto Field, la propiedad ActualSize devuelve adUnknown. Las propiedades DefinedSize y ActualSize tienen propsitos diferentes. Por ejemplo, considere un objeto Field con un tipo declarado de adVarChar y un valor de la propiedad DefinedSize de 50, que contiene un solo carcter. El valor de la propiedad ActualSize que devuelve es la longitud en bytes de ese nico carcter. Determinar contenidos de campos El identificador de la columna desde el origen de datos se representa mediante la propiedad Name del campo. La propiedad Valor del objeto Field devuelve o establece el contenido de datos reales del campo. Esta es la propiedad predeterminada. Para cambiar los datos de un campo, establezca la propiedad Valor en un valor nuevo del tipo correcto. Su tipo de cursor debe admitir actualizaciones para cambiar el contenido de un campo. La validacin de la base de datos no se hace aqu en modo de proceso por lotes, por lo que deber comprobar si hay errores cuando llame a UpdateBatch en tal caso. Algunos proveedores tambin admiten las propiedades UnderlyingValue y OriginalValue del objeto Field de ADO para ayudarle a resolver conflictos cuando intenta realizar actualizaciones por lotes. Para obtener detalles acerca de cmo resolver tales conflictos, vea el Captulo 4: Modificar datos. Nota Los valores del campo Recordset no se pueden establecer al anexar nuevos campos a un conjunto de registros. Ms bien, los campos nuevos se pueden anexar a un conjunto de registros cerrado. Despus, se debe abrir el conjunto de registros, y slo entonces se podrn asignar valores a estos campos. Obtener ms informacin de campos Los objetos de ADO tienen dos tipos de propiedades: integradas y dinmicas. Hasta ahora, se han descrito slo las propiedades integradas del objeto Field. Las propiedades integradas son aquellas propiedades implementadas en ADO y disponibles inmediatamente para cualquier objeto nuevo, utilizando la sintaxis
MyObject.Property

. No aparecen como objetos Property en la coleccin Properties de un objeto.

Las propiedades dinmicas las define el proveedor de datos subyacente, y aparecen en la coleccin Properties para el objeto de ADO apropiado. Por ejemplo, una propiedad especfica del proveedor puede indicar si un objeto Recordset admite transacciones o actualizaciones. Estas propiedades adicionales aparecern como objetos Property en la coleccin Properties de ese objeto Recordset. Las referencias a las propiedades dinmicas solo se pueden establecer a travs de la coleccin, usando la sintaxis
MyObject.Properties(0)

o
MyObject.Properties("Name")

. No se puede eliminar ningn tipo de propiedad. Un objeto dinmico Property tiene cuatro propiedades integradas propias: La propiedad Name es una cadena que identifica a la propiedad. La propiedad Type es un entero que especifica el tipo de datos de la propiedad. La propiedad Value es una variante que contiene la configuracin de la propiedad. Valor es la propiedad predeterminada de un objeto Property. La propiedad Attributes es un valor Long que indica caractersticas de la propiedad especficas del proveedor. La coleccin Properties del objeto Field contiene metadatos adicionales acerca del campo. El contenido de esta coleccin vara dependiendo del proveedor. El cdigo de ejemplo siguiente examina la coleccin Properties del conjunto de registros de ejemplo que se present al principio de este captulo. Primero examina el contenido de la coleccin. Este cdigo utiliza OLE DB Provider para SQL Server, de forma que la coleccin Properties contiene informacin relativa a ese proveedor.
'BeginFieldProps Dim objProp As ADODB.Property For intLoop = 0 To (objFields.Count - 1) Debug.Print objFields.Item(intLoop).Name For Each objProp In objFields(intLoop).Properties Debug.Print vbTab & objProp.Name & " = " & objProp.Value Next objProp Next intLoop 'EndFieldProps

Captulo 4: Edicin de datos


Captulo 4: Modificar datos En los dos captulos anteriores, se explicaba cmo utilizar ADO para conectarse a un origen de datos, ejecutar un comando, obtener los resultados en un objeto Recordset y desplazarse dentro del conjunto de registros. Este captulo se centra en la siguiente operacin fundamental de ADO: la edicin de datos. En este captulo, se sigue utilizando el conjunto de registros de ejemplo introducido en el captulo 3 (con un cambio importante). El cdigo siguiente se utiliza para abrir el conjunto de registros:
. . . 'BeginEditIntro

Dim strSQL As String Dim objRs1 As ADODB.Recordset strSQL = "SELECT * FROM Shippers" Set objRs1 = New ADODB.Recordset objRs1.Open strSQL, GetNewConnection, adOpenStatic, _ adLockBatchOptimistic, adCmdText ' Disconnect the Recordset from the Connection object. Set objRs1.ActiveConnection = Nothing 'EndEditIntro . . .

El cambio importante en el cdigo consiste en establecer la propiedad CursorLocation del objeto Connection en adUseClient en la funcin GetNewConnection (que se muestra a continuacin), lo que indica el uso de un cursor de cliente. Para obtener ms informacin acerca de las diferencias entre cursores de cliente y de servidor, vea el Captulo 8: Cursores y bloqueos. El valor adUseClient de la propiedad CursorLocation mueve la ubicacin del cursor desde el origen de datos (SQL Server en este caso) a la ubicacin del cdigo de cliente (la estacin de trabajo de escritorio). Esta configuracin obliga a ADO a invocar el Client Cursor Engine para OLE DB en el cliente para crear y administrar el cursor. Es posible que tambin haya observado que el parmetro LockType del mtodo Open se ha cambiado a adLockBatchOptimistic. De este modo, el cursor se abre en modo de proceso por lotes (el proveedor almacena varios cambios en cach y los escribe en el origen de datos subyacente cuando se llama al mtodo UpdateBatch). Los cambios realizados en el conjunto de registros no se actualizarn en la base de datos hasta que se llame al mtodo UpdateBatch. Por ltimo, el cdigo de este captulo utiliza una versin modificada de la funcin GetNewConnection, que se present en el captulo 2. Esta versin de la funcin devuelve ahora un cursor de cliente. La funcin tiene la forma:
'BeginNewConnection Public Function GetNewConnection() As ADODB.Connection Dim objConn1 As ADODB.Connection Set objConn1 = New ADODB.Connection strConnStr = "Provider=SQLOLEDB;Initial Catalog=Northwind;" & _ "Data Source=MySrvr;Integrated Security=SSPI;" objConn1.ConnectionString = strConnStr objConn1.CursorLocation = adUseClient objConn1.Open Set GetNewConnection = objConn1 End Function 'EndNewConnection

Editar registros existentes Para editar registros existentes, vaya a la fila que desea modificar y cambie la propiedad Valor de los campos que desea cambiar. Para obtener ms informacin sobre la propiedad Valor del objeto Field, vea el Captulo 3: Examinar datos. Dependiendo del tipo de cursor, se utilizar Update o

UpdateBatch para enviar los cambios de vuelta al origen de datos. Para obtener ms informacin, vea el Captulo 5: Actualizar y almacenar datos.. Normalmente es ms eficaz utilizar un procedimiento almacenado con un objeto de comando para realizar actualizaciones, as como para realizar otras operaciones, ya que un procedimiento almacenado no requiere la creacin de un cursor. Para obtener ms informacin acerca de cursores, vea el Captulo 8: Cursores y bloqueos. Determinar qu se admite El mtodo Supports sirve para determinar si un objeto Recordset especificado admite un tipo determinado de funcionalidad. Tiene la sintaxis siguiente:

boolean = recordset.Supports( CursorOptions )

Supports devuelve un valor booleano que indica si el proveedor admite todas las caractersticas identificadas mediante el argumento CursorOptions. Puede usar el mtodo Supports para determinar qu tipos de funcionalidades admite un objeto Recordset. Si el objeto Recordset admite las caractersticas cuyas constantes correspondientes estn en CursorOptions, el mtodo Supports devuelve True. De lo contrario, devuelve False. Con el mtodo Supports, puede comprobar la disponibilidad del objeto Recordset para agregar nuevos registros, usar marcadores, usar el mtodo Find, usar el desplazamiento, usar la propiedad Index y realizar actualizaciones por lotes. Para consultar una lista completa de constantes y sus significados, vea CursorOptionEnum. Aunque el mtodo Supports puede devolver True para una funcionalidad determinada, no garantiza que el proveedor pueda ofrecer la funcionalidad en cualquier circunstancia. El mtodo Supports simplemente indica si el proveedor puede admitir la funcionalidad especificada, suponiendo que se cumplen ciertas condiciones. Por ejemplo, el mtodo Supports puede indicar que un objeto Recordset admite actualizaciones, incluso aunque el cursor se base en una unin de varias tablas (con algunas columnas que no se pueden actualizar). CursorOptionEnum Especifica qu funcionalidad debera comprobar el mtodo Supports.
Constante adAddNew adApproxPosition adBookmark adDelete adFind adHoldRecords adIndex adMovePrevious adNotify Valor 0x1000400 0x4000 0x2000 0x1000800 0x80000 0x100 0x100000 0x200 0x40000 Descripcin Admite el mtodo AddNew para agregar nuevos registros. Admite las propiedades AbsolutePosition y AbsolutePage. Admite la propiedad Bookmark para obtener acceso a registros especficos. Admite el mtodo Delete para eliminar registros. Admite el mtodo Find para localizar una fila en un objeto Recordset. Recupera ms registros o cambia la posicin siguiente sin confirmar todos los cambios pendientes. Admite la propiedad Index para denominar un ndice. Admite los mtodos MoveFirst y MovePrevious, as como los mtodos Move o GetRows para mover la posicin de registro actual hacia atrs sin necesidad de marcadores. Indica que el proveedor de datos subyacente admite notificaciones (lo cual determina si

se admite eventos del objeto Recordset). adResync adSeek adUpdate adUpdateBatch 0x20000 0x200000 0x1008000 0x10000 Admite el mtodo Resync para actualizar el cursor con los datos visibles de la base de datos subyacente. Admite el mtodo Seek para localizar una fila en un objeto Recordset. Admite el mtodo Update para modificar datos existentes. Admite actualizacin por lotes (mtodos UpdateBatch y CancelBatch) para transmitir grupos de cambios al proveedor.

Equivalente ADO/WFC Paquete: com.ms.wfc.data


Constante AdoEnums.CursorOption.ADDNEW AdoEnums.CursorOption.APPROXPOSITION AdoEnums.CursorOption.BOOKMARK AdoEnums.CursorOption.DELETE AdoEnums.CursorOption.FIND AdoEnums.CursorOption.HOLDRECORDS AdoEnums.CursorOption.INDEX AdoEnums.CursorOption.MOVEPREVIOUS AdoEnums.CursorOption.NOTIFY AdoEnums.CursorOption.RESYNC AdoEnums.CursorOption.SEEK AdoEnums.CursorOption.UPDATE AdoEnums.CursorOption.UPDATEBATCH

Eliminar registros utilizando el mtodo Delete Con el mtodo Delete, se marca el registro activo o un grupo de registros de un objeto Recordset para su eliminacin. Si el objeto Recordset no admite la eliminacin de registros, se produce un error. En modo de actualizacin inmediata, las eliminaciones se producen en la base de datos directamente. Si no se consigue eliminar un registro (debido a infracciones de la integridad de la base de datos, por ejemplo), el registro permanecer en modo de edicin despus de la llamada a Update. Esto significa que se debe cancelar la actualizacin mediante CancelUpdate antes de abandonar el registro activo (por ejemplo, usando Close, Move o NextRecordset). En modo de actualizacin por lotes, los registros se marcan para eliminacin de la cach y la eliminacin real ocurre cuando se llama al mtodo UpdateBatch (para ver los registros eliminados, establezca la propiedad Filter en adFilterAffectedRecords despus de llamar a Delete). Si intenta recuperar valores de campos del registro eliminado, se producir un error. Despus de eliminar el registro activo, el registro eliminado seguir siendo el activo hasta que se mueva a otro registro. Cuando abandone el registro eliminado, ya no se podr volver a obtener acceso a l. Si anida eliminaciones en una transaccin, puede recuperar registros eliminados utilizando el mtodo RollbackTrans. En modo de actualizacin por lotes, puede cancelar una eliminacin pendiente o un grupo de eliminaciones pendientes mediante el mtodo CancelBatch.

Si el intento de eliminar registros falla debido a un conflicto con los datos subyacentes (por ejemplo, que un registro ya haya sido eliminado por otro usuario), el proveedor devuelve advertencias a la coleccin Errors, pero no detiene la ejecucin del programa. Slo se produce un error en tiempo de ejecucin si hay conflictos con todos los registros solicitados. Si se ha establecido la propiedad dinmica Tabla nica y el conjunto de registros es el resultado de ejecutar una operacin JOIN en varias tablas, el mtodo Delete slo eliminar filas de la tabla mencionada en la propiedad Tabla nica. El mtodo Delete toma un argumento opcional que permite especificar a qu registros afecta la operacin Delete. Los nicos valores vlidos para este argumento son las constantes enumeradas AffectEnum de ADO siguientes: adAffectCurrent Afecta slo al registro actual. adAffectGroup Afecta slo a registros que satisfacen la configuracin activa de la propiedad Filter. La propiedad Filter debe estar establecida en un valor de FilterGroupEnum o una matriz de marcadores para poder usar esta opcin. El cdigo siguiente muestra un ejemplo de especificacin de adAffectGroup cuando se llama al mtodo Delete. En este ejemplo, se agregan algunos registros al conjunto de registros de ejemplo y se actualiza la base de datos. Despus, se filtra el conjunto de registros utilizando la constante enumerada de filtro adFilterAffectedRecords, que slo deja visibles los registros recin agregados en el conjunto de registros. Por ltimo, llama al mtodo Delete y especifica que se deben eliminar todos los registros que satisfagan la configuracin activa de la propiedad Filter (los nuevos registros).
'BeginDeleteGroup 'add some bogus records With objRs1 For i = 0 To 8 .AddNew .Fields("CompanyName") = "Shipper Number " & i + 1 .Fields("Phone") = "(425) 555-000" & (i + 1) .Update Next i 're-connect & update .ActiveConnection = GetNewConnection .UpdateBatch 'filter on newly added records .Filter = adFilterAffectedRecords Debug.Print "Deleting the " & .RecordCount & _ " records you just added." 'delete the newly added bogus records .Delete adAffectGroup .Filter = adFilterNone Debug.Print .RecordCount & " records remain." .Close End With 'EndDeleteGroup

Alternativas: Utilizar instrucciones SQL

ADO tambin permite utilizar comandos como alternativa a sus propiedades y mtodos integrados para modificar datos. Dependiendo de su proveedor, todas las operaciones mencionadas en este captulo tambin se podran realizar pasando comandos a su origen de datos. Por ejemplo, se pueden utilizar instrucciones SQL UPDATE para modificar datos sin usar la propiedad Valor de un campo. Se pueden utilizar instrucciones INSERT para agregar nuevos registros a un origen de datos, en lugar del mtodo AddNew de ADO. Para obtener ms informacin acerca de SQL o el lenguaje de manipulacin de datos de su proveedor, vea la documentacin de su origen de datos. Por ejemplo, puede pasar una cadena SQL que contiene una instruccin DELETE a una base de datos, como se muestra en el cdigo siguiente:
'BeginSQLDelete strSQL = "DELETE FROM Shippers WHERE ShipperID = " & intId objConn.Execute strSQL, , adCmdText + adExecuteNoRecords 'EndSQLDelete

Potrebbero piacerti anche