Capitulo 04 - Programacion en ADO

download Capitulo 04 - Programacion en ADO

of 68

description

ASP.NET Programación con C#

Transcript of Capitulo 04 - Programacion en ADO

Captulo 4. Programacin en ADO4.1. Las bases de datos relacionales (RDBMS)Una base de datos relacional es un conjunto de tablas que mantienen algn tipo de relacin entre ellas. Una base de datos es un conjunto de informacin que se organiza por mediacin de una estructura lgica. La informacin puede ser guardada en un fichero o en varios ficheros, tambin conocidos como tablas. 4.1.1. Las Tablas Dentro de la base de datos, las tablas son el objeto ms bsico e importante. El rendimiento de la base de datos y por extensin de las aplicaciones que accedan a ellas, dependen en gran medida del diseo de las tablas. Una tabla es una matriz bidimensional, que contiene filas y columnas. Las filas son los registros de la tabla y las columnas son los campos de la tabla. A las filas tambin se les conoce con el nombre de tuplas o registros. Un campo es una forma de decir que tipo de informacin contendrn las filas en esa posicin. Por ejemplo una columna llamada Nombre, podr contener el nombre de las personas.Campos de la Tabla: Nombre, Apellidos y DNI

Estructura de la Tabla:Nombre Antonio Luis Mara Apellidos Prez Lpez Martnez Snchez Garca Hernndez DNI 7328714K 3858582L 4738270XFilas de la tabla o registros que contienen los datos organizados por las columnas de la tabla, tambin llamadas campos.

Las tablas de datos se pueden relacionar entre s, generando bases de datos relacionales. En el mercado, existen varios sistemas administradores de bases de datos relacionales, como son: Access, SQL Server, MySQL, Oracle, SysBase, Informix, etc. Una tabla suele ser la representacin de clases de objetos fsicos, como por ejemplo, clientes, empleados, facturas, etc. Cada objeto fsico, como un empleado, tiene su registro correspondiente en la tabla.

En esta imagen podemos ver una tabla de empleados con 7 campos.Captulo 4. Programacin en ADO. Pgina 1

En este caso el campo ID de la tabla, es el campo Clave de la tabla, lo que significa que la tabla es accedida directamente por este campo y permite identificar a ese registro de forma inequvoca sobre cualquier otro registro de la tabla. El campo clave, ID de la tabla Empleados, permite que esta tabla se relacione con otras tablas de la base de datos, como por ejemplo Pedidos, o Privilegios de Empleados. 4.1.2. Las Claves. Existen distintos tipos de clave: Clave nica. Cada tabla puede tener uno o ms campos cuyos valores identifican de forma nica cada registro de dicha tabla, es decir, no pueden existir dos o ms registros diferentes cuyos valores en dichos campos sean idnticos. Este conjunto de campos se llama clave nica. Pueden existir varias claves nicas en una determinada tabla, y a cada una de stas suele llamrsele candidata a clave primaria. Clave primaria. Una clave primaria es una clave nica elegida entre todas las candidatas que define unvocamente a todos los dems atributos de la tabla, para especificar los datos que sern relacionados con las dems tablas. La forma de hacer esto es por medio de claves forneas. Slo puede existir una clave primaria por tabla y ningn campo de dicha clave puede contener valores NULL. Clave externa o fornea. Una clave externa es una referencia a una clave en otra tabla. Las claves externas no necesitan ser claves nicas en la tabla donde estn y s a donde estn referenciadas. Por ejemplo, el cdigo de departamento puede ser una clave externa en la tabla de empleados, obviamente se permite que haya varios empleados en un mismo departamento, pero existir slo un departamento. El objetivo en el diseo de las tablas es evitar la redundancia de los datos, es decir, imaginemos que la direccin del empleado apareciera en ms de una tabla como contenido de un campo. En ese caso, hablamos de redundancia. La redundancia ralentiza la ejecucin de la base de datos, as como genera un exceso de espacio en disco que, con una buena planificacin en las relaciones entre tablas, se podra solucionar. La forma de evitarlo, es crear por ejemplo una tabla con las direcciones de los empleados y usar un campo clave para acceder a ellas. A parte de la clave primaria, podemos definir claves secundarias, que son claves que se utilizan para poder relacionar de una forma ms precisa las tablas. El hecho de hace coincidir una clave secundaria con un valor de clave primaria, se denomina operacin de bsqueda.Captulo 4. Programacin en ADO. Pgina 2

Las claves primarias suelen ser campos numricos de autoincremento, llamados Autonumricos en Access e Identify en SQL Server. El uso de valores de campos alfabticos como Clave Principal, ha cado en desuso por parte de los diseadores de bases de datos, debido a su lentitud a la hora de realizar operaciones, pero muchas veces es la mejor o nica opcin. Otro mtodo para generar claves exclusivas es utilizar los identificadores globales exclusivos (GUID). Los GUID son nmeros binarios de 16 bytes cuya exclusividad est garantizada local y universalmente; ningn otro ordenador del mundo puede duplicar un GUID. En SQL Server, uniqueidentifier, es un tipo GUID. Por mediacin de las claves podemos crear relaciones que agilizan las consultas y el acceso a los datos. Una tabla puede tener mltiples relaciones con otras tablas. El tipo de relaciones posibles que se pueden implementar en una base de datos son: Uno a Varios. Representa una relacin entre un solo valor de clave principal (uno) y varias instancias del mismo valor en el campo clave secundario (varios). Las relaciones uno a varios son representadas como un 1 y el smbolo de infinito. Uno a Uno. Son relaciones en las que se conectan los valores de clave principal de dos tablas. Es una relacin poco usada. Varios a Varios. Son relaciones que requieren tres tablas, una de las cuales es la tabla de vinculacin. La tabla de vinculacin debe de tener dos claves secundarias, cada una con una relacin varios a uno con una clave principal de dos tablas relaciones. Estas relaciones tambin se las conoce como indirectas. Ejemplo de Esquema de las relaciones de una Base de Datos:

Captulo 4. Programacin en ADO.

Pgina 3

4.1.3. Las Clave ndice Las claves ndices surgen con la necesidad de tener un acceso ms rpido a los datos. Los ndices pueden ser creados con cualquier combinacin de campos de una tabla. Las consultas que filtran registros por medio de estos campos, pueden encontrar los registros de forma no secuencial usando la clave ndice. Los ndices generalmente no se consideran parte de la base de datos, pues son un detalle agregado. Un ndice es un objeto que existe slo dentro del marco de una determinada tabla o vista. Un ndice funciona de una forma anloga al ndice de un libro, donde existe algn tipo de valor (clave) de bsqueda que se organiza de una forma y, posteriormente, se proporciona otra clave con la que podremos encontrar la informacin que estamos buscando. Un ndice nos proporciona mtodos para agilizar la bsqueda de nuestra informacin. Los ndices se organizan en dos categoras: Agrupados. Slo puede haber un ndice agrupado por tabla. Tener un ndice agrupado significa que la tabla que se basa en dicho ndice agrupado est ordenada fsicamente segn dicho ndice. En un libro, el ndice agrupado sera el nmero de pgina; la informacin se guarda en el orden de los nmeros de pgina. No Agrupados. Se pueden tener tantos ndices no agrupados como se quiera en la tabla. Este tipo de ndice apunta a otro valor que nos va a permitir encontrar el dato. En nuestro ejemplo, seran los conceptos detallados en el ndice del libro. 4.1.4. Los Desencadenadores Un desencadenador es un objeto que existe slo dentro del marco de una tabla. Los desencadenadores son elementos de cdigo lgico que se ejecutan automticamente cuando se producen diversos eventos en nuestra tabla, como inserciones, actualizaciones o eliminaciones. Los desencadenadores se pueden utilizar para diversas cosas, pero principalmente se utilizan para copiar datos a medida que se introducen o para comprobar la actualizacin para asegurarse de que se satisfacen algunos criterios. 4.1.5. Restricciones Una restriccin es otro objeto que slo existe dentro de los confines de una tabla. Las restricciones confinan los datos de nuestra tabla para satisfacer determinadas condiciones. En cierto sentido, las restricciones compiten con los desencadenadores como posibles soluciones para solucionar problemas de integridad de datos. Sin embargo, no son iguales; cada elemento tiene sus propias ventajas inconfundibles.Captulo 4. Programacin en ADO. Pgina 4

La tabla es el elemento bsico de la estructura en una base de datos. Evidentemente es el objeto ms importante, pero existen otros que lo complementan y aaden la funcionalidad necesaria para sacar toda la potencia a un sistema de base de datos relacional. 4.1.6. Diagramas Un diagrama es una representacin visual del diseo de la base de datos, incluyendo las diversas tablas, los nombres de columna de cada tabla y las relaciones entre las mismas. Un Diagrama de entidad-relacin (ERD), es un diagrama en el que la base de datos se divide en dos partes: las entidades y las relaciones. 4.1.7. Vistas Una vista es algo parecido a una tabla virtual. Bsicamente se utilizan como una tabla, pero no contienen ningn dato propio. En su lugar, una vista es simplemente una planificacin previa de la asignacin y representacin de los datos guardados en tablas. El plan se guarda en la base de datos en forma de consulta. Esta consulta llama a los datos de algunas columnas (no tienen que ser todas) para su recuperacin por parte de una o ms tablas. Los datos recuperados pueden o no reunir unos criterios especiales (dependiendo de la definicin de la vista) para mostrarse como datos en dicha vista. Podemos usar una vista para incluir la informacin que todo el mundo pueda ver, dado que las aplicaciones normalmente discriminan la informacin en funcin del nivel de acceso del usuario. Asimismo, se puede hacer una vista a la medida para que los usuarios no tengan que realizar bsquedas a travs de informacin innecesaria. 4.1.8. Procedimientos Almacenados Un procedimiento almacenado sigue siendo bsico para las funciones de programacin en SQL Server. Un procedimiento almacenado es una serie de instrucciones Transact-SQL ordenadas e integradas en una sola unidad lgica. Su equivalente en C#, sera un mtodo.

Captulo 4. Programacin en ADO.

Pgina 5

4.2. Uso bsico de Transact-SQL o T-SQL Las bases de datos relacionales usan un lenguaje de programacin conocido como Transact-SQL o T-SQL. T-SQL es un lenguaje estndar para trabajar con bases de datos relacionales y es soportado por la mayora de los sistemas actuales. Los comandos o instrucciones ms habituales en SQL se aplican para: Crear y borrar tablas; Insertar registros en la tabla; actualizar la informacin de los registros en la tabla; borrar un registro o grupo de registros y; seleccionar un registro o conjunto de registros. Estas opciones son realizadas por: Create, Drop, Insert, Update, Delete y Select, respectivamente. 4.2.1. La instruccin SELECT La instruccin Select y las estructuras utilizadas en ella, forman la base de todos los comandos que vamos a ver. Sintaxis: SELECT [ FROM ] [WHERE ] [GROUP BY ] [HAVING ] [ORDER BY ] Para empezar vamos a utilizar el ejemplo Northwind suministrado como ejemplo de ayuda por Microsoft. Tanto esta base como Pubs, fueron diseadas para su uso con Access y SQl Server 2000. A partir de la versin 2005 fueron sustituidas por AdventureWorks. Esta ltima base incorpora funcionalidades de SQL Server 2005 muy avanzadas que en ocasiones dificultan el aprendizaje del T-SQL. Por ello, Microsoft mantiene tanto Pubs como Northwind disponibles para SQL Server 2005 y SQL Server 2008. Como primera prueba de Select, usemos la siguiente sintaxis: SELECT * FROM employees El resultado de esta consulta nos dar todas las columnas (*) de la tabla employee y todos los registros que contenga. Si no hemos manipulado el ejemplo, deber de dar como resultado nueve filas. El uso del * le indica al intrprete de SQL que nos devuelva todos los campos (columnas) que tiene la tabla employees. La clausula FROM, le indica cual es la tabla o tablas de las que tiene que tomar los datos.

Captulo 4. Programacin en ADO.

Pgina 6

Si quisiramos obtener slo las columnas de nombre y apellidos, utilizaremos la sentencia SELECT con esta estructura: SELECT lastname, firstname FROM employees Como podemos ver los campos que queremos obtener van separados por coma. Si ejecutamos la consulta veremos que siguen saliendo 9 filas pero slo nos da las columnas LastName y FirstName. Una cosa a tener en cuenta con el SQL es que no distingue a la hora de escribir las sentencias entre maysculas y minsculas. Por ejemplo: SELECT y Select son la misma cosa para el intrprete de SQL. Hay algunos editores de SQL que ponen las instrucciones en maysculas y otros en minsculas, pero slo tiene un efecto visual. La clusula Where. Esta clusula nos permite agregar a la consulta condiciones sobre los resultados deseados. Hasta ahora, slo hemos obtenido el total de las filas que contiene la tabla. Por ejemplo, supongamos que queremos los empleados SELECT lastname, firstname FROM employees WHERE Title = 'Sales Representative' Como observaremos, ya no son 9 las filas afectadas, ahora son slo seis. Hemos utilizado la columna Title, para restringir las filas que queramos consultar. A continuacin vemos una tabla con los operadores que podemos utilizar en una clusula Where: Operador < > < > y = = = > , = , >=). ALL indica que el valor tiene corresponderse con todos los valores del conjunto. ANY y SOME son equivalentes funcionales y se evaluarn como true si la expresin se corresponde con cualquier valor del conjunto. Devuelve true si la subconsulta devuelve, al menos, una fila.

Por ejemplo, si quisiramos obtener todos los trabajadores cuya alta en la empresa sea entre 1990 y 1993, la consulta sera: SELECT * FROM employees WHERE hiredate BETWEEN '01-01-1990' AND '01-01-1993' El resultado de esta consulta es de tres filas afectadas. La clusula Order By. En las consultas, puede ocurrir que los datos salgan ordenados alfabticamente. Eso podra ser por casualidad. Si no le indicamos que deseamos ordenar los resultados de la consulta de una forma especfica, se obtendrn los datos en la forma menos costosa para recopilar los datos.

Captulo 4. Programacin en ADO.

Pgina 8

Normalmente se basar, bien en el orden fsico de una tabla o bien en uno de los ndices de SQL Server utilizados para buscar los datos. Order By nos permite seleccionar cual es la columna o columnas que sern la base para ordenar los resultados de la consulta. Ejemplo: SELECT * FROM employees WHERE hiredate BETWEEN '01-01-1990' AND '01-01-1993' ORDER BY FirstName Si observamos esta consulta respecto a la anterior, observaremos que en esta ocasin los datos son mostrados en el orden alfabtico de la columna FirstName. Si no queremos, no es necesario colocar una clusula Where, pero en caso de ir, tiene que ir antes del Order By. Por ejemplo: SELECT * FROM employees ORDER BY FirstName, LastName En este ejemplo seleccionamos todos los empleados, pero mostrados en orden alfabtico por el FirstName y despus por el LastName. Evidentemente podemos aplicar ordenaciones por campos numricos, incluso cambiar si es ascendente o descendente, por ejemplo: SELECT * FROM products WHERE unitsonorder > 0 AND unitsinstock < 10 ORDER BY unitsonorder DESC Este ejemplo, muestra todos los valores cuyo campo unitsonorder sea superior a cero y su campo unitsinstock se inferior a 10. El resultado es ordenador de forma descendente por unitsonorder. De forma implcita un Order By ejecuta la ordenacin de forma ascendente. Podramos indicrselo de forma explcita, colocando ASC. DESC le indica que la ordenacin sea descendente. SELECT * FROM employees WHERE hiredate BETWEEN '01-01-1990' AND '01-01-1993' ORDER BY hiredate, employeeid DESC Nos muestra la consulta ordenada primeramente por la columna, hiredate, de forma descendente y si hubiera coincidencias, utilice la columna employeeid para ordenar. La clusula Group By. Esta clusula se utiliza para agregar informacin. Si realizamos la siguiente consulta, nos devolver todos los artculos que se han pedido dentro de un conjunto concreto de pedidos.

Captulo 4. Programacin en ADO.

Pgina 9

SELECT orderid, quantity FROM [order details] WHERE orderid BETWEEN 11000 AND 11002 Como podemos observar al ejecutar la consulta, nos ha devuelto 11 filas de la tabla order details, que son las que coinciden con el orderid entre el 11000 y el 11002. Si observamos detenidamente, podemos ver que por ejemplo de la orden 11000 hay tres filas, lo que significa que aunque en realidad la orden era slo para ver tres pedidos, la consulta nos ha devuelto el detalle individual de cada pedido. Cuatro filas para el pedido 11001 y 4 filas para el pedido 11002. Si quisiramos ver slo los pedidos, sin l detalle, podemos usar Group By y, adems, aplicarle un agregado a la sentencia select, que en este caso, es la funcin de la suma sum(). Si ejecutamos la orden como sigue, obtendremos tres filas con el total del valor del pedido. SELECT orderid, SUM(quantity) FROM [order details] WHERE orderid BETWEEN 11000 AND 11002 GROUP BY orderid Sum() realiza la suma, pero si lo que necesitamos es el nmero de filas, podemos utilizar la funcin Count(). Ejemplo: SELECT customerid, employeeid, COUNT(*) FROM orders WHERE customerid BETWEEN 'A' AND 'B' GROUP BY customerid, employeeid Esta consulta obtiene todos los pedidos por clientes y por empleados que hicieron esos pedidos. El resultado es que para cada cliente nos dice el nmero de pedidos que gestiono los empleados. Al usar Group By, toda columna en la lista de seleccin tienen que formar parte de Group By o tiene que ser un agregado. Agregados. Un agregado es una funcin que acta sobre grupos de datos. En el ejemplo que usamos el agregado SUM(), lo que obtuvimos fue la suma de la columna quantity. La suma se calcula y se devuelve sobre la columna seleccionada para cada grupo definido en la clusula GROUP BY(en ese caso, slo OrderId). Hay muchas clases de agregados, pero slo vamos a estudiar las ms usuales: sum, count, avg (media), min, max. AVG. Realiza una media de los valores. Por ejemplo: SELECT orderid, AVG(quantity) FROM [order details] WHERE orderid BETWEEN 11000 AND 11002 GROUP BY orderid Esta instruccin ha calculado el importe medio para cada pedido.

Captulo 4. Programacin en ADO.

Pgina 10

MIN / MAX. Devuelve el valor mnimo o mximo de una agrupacin. Por ejemplo: SELECT orderid, MAX(quantity) FROM [order details] WHERE orderid BETWEEN 11000 AND 11002 GROUP BY orderid COUNT(expression). Hace un recuento de las filas en una consulta. Por ejemplo: SELECT COUNT(*) FROM employees WHERE employeeid = 2 Devuelve el nmero de filas que el campo employeedid es igual a 2. En este caso slo hay una fila. Si por el contrario ejecutamos esta orden: SELECT COUNT(*) FROM employees El resultado ser nueve. Nos ha dado el nmero total de filas que contiene la tabla employees. Supongamos que queremos obtener el recuento para una columna concreta. En ese caso, utilizaremos una sentencia como esta: SELECT COUNT(fax) FROM customers En este caso hemos pedido saber cuntas filas hay en la tabla customers, por el campo fax. El resultado es 69. Pero esta consulta podra hacernos pensar que el resultado es idntico a preguntar por todos, por ejemplo: SELECT COUNT(*) FROM customers Si ejecutamos esta consulta, descubriremos que el resultado es 91. Cmo puede ser?. La respuesta est en los valores null. Si observamos la ventana de mensajes cuando ha realizado la primera consulta, vernos un mensaje con este texto: Advertencia: valor NULL eliminado por el agregado u otra operacin SET. Significa que cualquier valor null sobre un agregado del tipo, count, avg, etc, las columnas que contienen el null, no son consideradas para el clculo y por tanto no cuentan. En una media, el valor no est representado sobre todas las filas, sino que se aplica sobre todas las filas que no contienen null. Por ejemplo, si quisiramos saber cuntas son null, utilizaremos la siguiente sentencia: SELECT COUNT(*) FROM customers WHERE fax IS NULL El resultado de la consulta es 22, que sumadas a las 69 que dio, hacen un total de 91.

Captulo 4. Programacin en ADO.

Pgina 11

Count se puede usar junto con Group By para, por ejemplo, saber que empleados reportan a que director: SELECT reportsto, COUNT(*) FROM employees GROUP BY reportsto Hemos agrupado los resultados por reportsto. Como count es un agregado, en la clusula group by no tiene que ir. La clusula HAVING. La clusula Having se usa si existe una clusula GROUP BY en la consulta. Mientras que la clusula Where se aplica a todas las filas antes de convertirse en grupo, la clusula Having se aplica al valor agregado de dicho grupo. Por ejemplo: SELECT reportsto AS manager, COUNT(*) employees GROUP BY reportsto AS reports FROM

En este ejemplo, la columna reportsto aparece con el nombre de manager y la columna del count, como reports. El resultado puede ser equivoco, ya que presupone que todo el mundo de la empresa depende de dos directores. Y si queremos que slo aparezcan los directores que tienen a su cargo ms de cuatro personas. Si usamos la clusula Where no podemos hacer nada porque Where se ejecuta antes de la agregacin y, por tanto, no podemos devolver filas basndonos en la agregacin. Para resolver este problema tenemos la clusula Having: SELECT reportsto AS manager, COUNT(*) AS reports FROM employees GROUP BY reportsto HAVING COUNT(*) > 4 Por ejemplo, podemos realizar esta otra consulta que nos devolver 830 filas. SELECT orderid, SUM(quantity) AS Total FROM [order details] GROUP BY orderid Si quisiramos filtrar la instruccin para que slo nos de aquellos cuya cantidad es superior a 300, podramos usar una clusula Having como sigue a continuacin: SELECT orderid, SUM(quantity) AS Total FROM [order details] GROUP BY orderid HAVING SUM(quantity) > 300 En este caso solo nos da dos filas afectadas.

Captulo 4. Programacin en ADO.

Pgina 12

Predicados Distinct y ALL Supongamos que deseamos obtener un listado de todos los Id de proveedores de todos los productos que tenemos almacenados. La sentencia podra ser: SELECT supplierid FROM products WHERE unitsinstock > 0 La sentencia nos devuelve toda la lista de productos, repitiendo el id de proveedor cada vez que hay un producto de ese proveedor. La solucin, si slo queremos saber que proveedores tienen productos, pasara por el uso del predicado Distinct. La sentencia podra quedarnos: SELECT DISTINCT supplierid FROM products WHERE unitsinstock > 0 Ahora slo muestra un Id de proveedor aunque aparezca en ms de una fila. Por defecto siempre el predicado es ALL, lo que significa que incluye todas las filas.

4.2.2. La instruccin INSERT Insert es una instruccin de accin. Le indica a SQL Server lo que vamos a hacer con esta instruccin, ya que todo lo que va a continuacin son los detalles de la operacin. Sintaxis: INSERT [intro] [(lista_de_columnas)] VALUES (valores_de_datos) La palabra clave intro es de relleno. Su nico propsito es que la instruccin sea ms legible. Es completamente opcional pero su uso es recomendable por el tema de la legibilidad. Despus de intro viene la tabla en la que deseamos insertar los valores: La lista de columnas. Podemos prescindir de una lista explcita (son listas donde se especifica concretamente que columnas recibirn los valores). Es opcional, pero si no suministramos ninguna, tenemos que tener mucho cuidado de asegurarnos que los valores corresponden a las columnas. A continuacin y despus de la palabra VALUES, van los valores de las columnas separados por comas y entre parntesis. Si queremos no establecer un valor en una columna podemos usar la palabra default para que la base de datos ponga uno predeterminado. Tambin y, siempre que este permitido, podemos usar Null. Para el siguiente ejemplo usamos Pubs. Ejemplo de Insert: INSERT INTO stores VALUES ('Prue', 'Prueba Almacen', 'Prueba 15', Madrid, 'MD', '00319')Captulo 4. Programacin en ADO. Pgina 13

La ejecucin de esa instruccin genera una nueva fila dentro de la tabla stores. Si intentamos repetir la instruccin, nos dar el siguiente error: Infraccin de la restriccin PRIMARY KEY 'UPK_storeid'. No se puede insertar una clave duplicada en el objeto 'dbo.stores'. El motivo es porque la columna stor_id es un campo de Clave Primaria y no admite repeticiones. A pesar de que ha funcionado bien, lo ideal hubiera sido haber suministrado una lista de columnas explcita. Veamos un ejemplo en que facilitamos una lista de columnas: INSERT INTO stores (stor_id, stor_name, city, state, zip) VALUES ('Pru2', 'Prueba Almacen', 'Madrid', 'MD', '00319') En este segundo ejemplo hemos omitido el campo correspondiente a stor_address, pero no importa porque al ser un campo que permite valores null, dar de alta la fila colocando un null en esa columna. El hecho de usar una lista de columnas nos permite especificar qu valores van a qu columnas. Si comprobamos la insercin descubriremos que en la columna que no hemos dado un valor a colocado null. Una columna que acepta valores null permite que en una instruccin Insert se omitan valores para esa columna. Si una columna no permite null, entonces hay que proporcionar una de estas tres condiciones: La columna se ha definido con un valor predeterminado. Un valor predeterminado es un valor constante que se inserta si no se proporciona ningn valor. La columna est definida para admitir valores generados por el sistema. El valor ms comn de este tipo es un valor Identity. Suministramos un valor para la columna. Nota: Existe un procedimiento almacenado en el sistema que permite ver las propiedades de cualquier objeto de la base de datos en la ventana de consultas: sp_help. Para poder ejecutarlo usaremos la siguiente sintaxis: EXEC sp_help sales

Instruccin Insert Into - Select La instruccin Insert que hemos desarrollado permite insertar slo una fila cada vez. Si necesitamos insertar ms de una fila, entonces debemos de usar la instruccin Select en la sintaxis de la instruccin Insert.

Captulo 4. Programacin en ADO.

Pgina 14

Sintaxis: INSERT INTO [] En una instruccin Insert con Select podemos seleccionar los registros a insertar de distintos orgenes: Otra tabla de nuestra base de datos. Una base de datos totalmente diferente en el mismo servidor. Una consulta de otro SQL Server u otros datos. De la misma tabla (normalmente para ordenar clculos matemticos). En el siguiente ejemplo creamos una tabla en memoria y le asignamos por mediacin de la sentencia Insert con Select datos de la base de datos Northwind, tabla orders: USE northwind DECLARE @mitabla Table ( OrderId int, CustomerId char(5) ) INSERT INTO @mitabla SELECT OrderId, CustomerId northwind.dbo.Orders WHERE OrderId BETWEEN 10240 AND 10250 SELECT * FROM @mitabla Ejemplo: Uso InsertarTablaMemoria

FROM

4.2.3. La instruccin UPDATE La instruccin Update permite modificar valores de registros que se encuentran en la tabla. Una instruccin Update puede crearse a partir de varias tablas pero slo puede realizar cambios a una. Esto quiere decir que podemos crear una condicin, o recuperar valores de cualquier nmero de tablas distintas, pero slo una tabla a la vez puede estar sujeta a la accin de la actualizacin. Sintaxis: UPDATE SET = [, = ] [FROM ] [WHERE ]

Captulo 4. Programacin en ADO.

Pgina 15

Tomando la base de datos Pubs, supongamos que queremos actualizar el valor de la columna city, de la tabla stores: UPDATE stores SET city = 'Toledo' WHERE stor_id = 'prue' En esta sentencia hemos cambiado el valor de una sola columna, pero podemos cambiar varias columnas a la vez: UPDATE stores SET city = 'Toledo', state = 'CM' WHERE stor_id = 'prue' Pero los cambios pueden afectar a grupos de registros que cumplan una condicin. Por ejemplo vamos a probar una sentencia Select en la que aplicamos el operador Like: SELECT title_id, price FROM titles WHERE title_id LIKE 'BU%' Al ejecutarla vemos que muestra todos los ttulos que empiezan por BU, sin tener en consideracin ms valores dentro de la cadena. Ahora, viendo el resultado, vamos a aplicar una sentencia Update usando el operador Like para cambiar el precio en los libros que coincidan en la consulta: UPDATE titles SET price = price * 1.1 WHERE title_id LIKE 'BU%' Este ejemplo actualiza los valores de la columna precio, incrementando su valor en un 10%, para todos aquellos libros cuyo campo title_id empiecen por BU. Si volvemos a realizar un Select para ver los resultados, observaremos que cada elemento tiene un nmero variable de decimales. Si quisiramos ajustarlo podemos utilizar una funcin de redondeo. UPDATE titles SET price = ROUND(price * 1.1, 2) WHERE title_id LIKE 'BU%'

4.2.4. La instruccin DELETE La instruccin Delete puede que sea de las que hemos visto hasta ahora de las ms sencillas. No incorpora listas de campos, ya que la posibilidad de borrar es a toda la fila y no a una parte de ella. Sintaxis: DELETE [WHERE ] La clusula Where funciona como hemos venido viendo hasta ahora.

Captulo 4. Programacin en ADO.

Pgina 16

Ejemplo: DELETE stores WHERE stor_id = 'prue' Puede ocurrir que en una operacin Delete aparezca un mensaje como el que aparece a continuacin: Instruccin DELETE en conflicto con la restriccin REFERENCE "FK__sales__stor_id__0AD2A005". El conflicto ha aparecido en la base de datos "pubs", tabla "dbo.sales", column 'stor_id'. Este error se produce porque la tabla stores, tiene su campo clave y est relacionado con la tabla sales, columna stor_id. No nos deja borrar la fila porque si lo hace dejara hurfanos registros en otras tablas. Se perdera la integridad referencial. Para poder borrar el registro, es necesario borrar antes los que dependen de l.

4.2.5. La clusula JOIN En las bases de datos relacionales las tablas grandes se suelen dividir en tablas ms pequeas para evitar la redundancia de datos, ahorrar espacio, mejorar el rendimiento y aumentar la integridad de datos. Cuando una base de datos est normalizada es cuando se han aplicado tcnicas de diseo que permiten tener las tablas grandes en tablas ms pequeas. Esto hace que al final los datos se tengan que tomar de ms de una tabla. El proceso de combinacin de tablas en un conjunto de resultados requiere el uso de la clusula JOIN, que incluye: INNER JOIN OUTER JOIN (tanto LEFT como RIGHT) FULL JOIN CROSS JOIN

Usamos JOIN para combinar la informacin de dos o ms tablas en un solo conjunto de resultados. El conjunto de resultados puede ser tratado como una tabla virtual. Tiene columnas, tipos de datos y valores. A JOIN hay que indicarle como queremos que se una la informacin. En el siguiente esquema podemos ver un ejemplo del uso de JOIN

Captulo 4. Programacin en ADO.

Pgina 17

Tabla ModelosIDCoche 1 2 3 4 Modelo Coche Xara Picaso Megant C5 Ibiza IDFabricante 1 3 1 2

Campo ClaveEl campo IDFabricante Relaciona ambas tablas.

Tabla FabricantesIDFabricante 1 2 3 Nombre Fabricante Citroen Seat Renault

Tabla Resultado de aplicar una sentencia JOINIDFabricante 1 1 Nombre Fabricante Citroen Citroen IDCoche 1 3 Modelo Coche Xara Picaso C5

Como podemos ver la tabla Fabricantes tiene un campo clave llamado IdFabricante que vincula esta tabla con la tabla Modelos. Al usar una sentencia JOIN en una consulta con ambas tablas, obtenemos una tabla de resultados, en la que se unen los registros que coinciden con el campo, IDFabricante en la tabla modelos, con el registro seleccionado de la tabla fabricante, cuyo IDFabricante sea el mismo. En el ejemplo obtenemos los modelos para Citroen. Sintaxis: SELECT FROM [ON ]

Captulo 4. Programacin en ADO.

Pgina 18

INNER JOIN Esta clusula es la ms conocida de JOIN. Empareja los registros basndose en uno o ms campos comunes, como la mayora de clusulas JOIN, pero INNER JOIN devuelve slo los registros que se corresponden con el campo (o campos) que hayamos especificado en JOIN. En el siguiente ejemplo usamos la base de datos Northwind: SELECT * FROM Products INNER JOIN Suppliers ON Products.SupplierID = Suppliers.SupplierID Si nos fijamos en el resultado de la consulta, descubriremos que la columna SupplierID (ID Proveedor) aparece dos veces, pero no se sabe qu columna proviene de que tabla. Adems, podemos observar que se han devuelto todas las columnas de ambas tablas y, por ltimo, las primeras columnas son de la primera tabla. Aparecen todas las columnas porque en el Select le hemos indicado con el * que ponga todas. Esto no es muy recomendable en una sentencia Join, debido a los problemas de lectura que acarrea. Supongamos que lo que queramos era el nombre del proveedor, de todos nuestros productos, entonces la consulta podra quedarnos as: Vamos a realizar la misma consulta pero esta vez usando un alias para el nombre de la tabla. Para crear un alias, justo detrs del nombre de la tabla va el alias: SELECT tp.*, companyname FROM Products tp INNER JOIN Suppliers ON tp.SupplierID = Suppliers.SupplierID Si usamos un alias, hay que usar el alias en todas las apariciones del nombre de la tabla en la consulta. Supongamos otro ejemplo: SELECT tp.productid, ts.supplierid, tp.productname, ts.companyname FROM Products tp INNER JOIN Suppliers ts ON tp.SupplierID = ts.SupplierID En este ejemplo, usamos el alas tp para la tabla productos y el alias ts para la tabla suppliers. En el select hemos especificado que columnas y en qu orden queremos que aparezcan en la tabla de respuesta. Un JOIN del tipo INNER JOIN es una unin exclusiva, es decir, excluye todos los registros que no tienen un valor en ambas tablas. Vamos a ver otro ejemplo. Imaginemos que nos piden cuales son los clientes que nos han hecho algn pedido. Para ello necesitamos la tablaCaptulo 4. Programacin en ADO. Pgina 19

Customers(Clientes) y Orders(Pedidos). El campo CustomerID de la tabla Customers, es la relacin existente entre ambas tablas. Para que un pedido sea vlido necesitamos dar de alta el ID del cliente en el pedido. Por tanto, la sentencia podra ser: SELECT DISTINCT tc.customerid, tc.companyname FROM Customers tc INNER JOIN Orders tod ON tc.customerid = tod.customerid Hemos usado la palabra clave DISTINCT porque slo queremos conocer que clientes han hecho algn pedido, no todos los pedidos. Probemos un ejemplo que combina dos JOIN sobre la base de datos Pubs, utilizando tres tablas. Buscamos una consulta que devuelva todos los autores que han escrito libros y los ttulos de dichos libros. Lo primeo que podemos observar es que en la tabla authors, tenemos el autor y en la tabla titles, los ttulos. En principio no tenemos nada que los una, pero hay una tabla llamada titleauthor, que es una tabla que resuelve las relaciones de varios a varios. Tambin se las conoce como tablas unin o asociadas. SELECT ta.au_lname + ', ' + ta.au_fname AS "Autor", tl.title FROM authors ta INNER JOIN titleauthor tt ON ta.au_id = tt.au_id INNER JOIN titles tl ON tl.title_id = tt.title_id El operador + utilizado en el Select, permite ver el contenido del campo Lname y Fname en uno solo. La coma que aparece entre los dos es por un tema visual, pudindose colocar cualquier smbolo o carcter. Como en cualquier lenguaje que maneje string, el operador + concatena los string en uno slo. Esta concatenacin deja en una columna a la que llamamos Autor, el contenido de los dos campos separados por una coma. OUTER JOIN Este tipo de clusula es ms bien una excepcin, no una regla y no porque no tenga su uso, sino por lo siguiente: Normalmente deseamos la exclusividad proporcionada por INNER-JOIN. A veces es un desconocimiento por parte de los programadores. Normalmente existen otros mtodos para conseguir lo mismo. Una clusula INNER JOIN es exclusiva, mientras que OUTER JOIN y FULL JOIN son inclusivas. Pueden resultar muy tiles desde el punto de vista del rendimiento cuando se utilizan en lugar de subconsultas anidadas. JOIN tiene lados (uno izquierdo y otro derecho). La primera tabla con nombre se considera que est a la izquierda y la segunda que est a la

Captulo 4. Programacin en ADO.

Pgina 20

derecha. INNER JOIN trata a los dos lados de la misma forma. En las clusulas OUTER JOIN, es muy importante saber cul es nuestro izquierdo y derecho. El tema es que la tabla que aparece antes del OUTER JOIN es la izquierda y la que aparece a continuacin es la derecha. Esto es muy importante cuando especificamos con Left o Right. Si decimos LEFT OUTER JOIN le estamos diciendo agrega toda la informacin de la tabla que est a la izquierda y, con RIGHT OUTER JOIN, le estamos diciendo que tome toda la informacin de la tabla que est a la derecha. Supongamos que necesitamos saber cules son nuestros descuentos, la cantidad total de cada uno y las tiendas que los utilizan. Si examinamos nuestra base de datos pubs, podremos ver que tenemos la siguiente tabla sobre descuentos (discounts) y tiendas (stores). Podemos unir estas dos tablas basndonos en el ID de tienda, stor_id. Si lo hicisemos con INNER JOIN, la consulta resultara: SELECT discounttype, discount, ts.stor_name FROM discounts td JOIN stores ts ON td.stor_id = ts.stor_id El resultado sera de slo una fila. Buscamos los descuentos que tenemos, los que existen actualmente. Pero esta consulta slo nos proporciona los descuentos para los que existen tiendas correspondientes. Buscamos todos los descuentos y las tiendas donde se aplican: SELECT discounttype, discount, ts.stor_name FROM discounts td LEFT OUTER JOIN stores ts ON td.stor_id = ts.stor_id Podemos comprobar que nos ha devuelto todas las filas de discounts. Cuando se ejecuta, en la tabla de la derecha si una fila de la tabla discounts no tiene una coincidencia con la tabla stores, muestra un null. En nuestro caso de los tres registros que salen, dos son null y el tercero es el nombre de una tienda. Qu ocurre si cambiamos el LEFT por RIGHT: SELECT discounttype, discount, ts.stor_name FROM discounts td RIGHT OUTER JOIN stores ts ON td.stor_id = ts.stor_id Aunque parece un cambio pequeo cambia totalmente la salida de la consulta. Una de las ventajas que nos puede ofrecer OUTER JOIN es la posibilidad de encontrar registros hurfanos o no coincidentes. Siguiendo con el ejemplo anterior, veamos como lo podemos aplicar para buscar tiendas que no tengan asignados ningn tipo de descuento.

Captulo 4. Programacin en ADO.

Pgina 21

Una clusula OUTER JOIN nos devuelve un valor null en las columnas basadas en los descuentos siempre que no exista una correspondencia. Ejemplo: SELECT ts.stor_name AS 'Nombre de la Tienda' FROM discounts td RIGHT OUTER JOIN stores ts ON td.stor_id = ts.stor_id WHERE td.stor_id IS NULL El resultado de esta consulta son cinco filas afectadas donde la tienda no tiene asignado ningn tipo de descuento. Si analizamos la consulta comprobamos lo siguiente: Si la columna stores.stor_id tiene un valor distinto de NULL, entonces, segn el operador ON de la clusula JOIN, si existen registros en discounts, entonces discounts.stor_id tambin tiene que tener el mismo valor que stores.stor_id (ON td.stor_id = s.stor_id) Si la columna stores.stor_id tiene un valor distinto de NULL, entonces, segn el operador ON de la clusula JOIN, si no existe ningn registro en discounts, entonces discounts.stor_id se devolver como NULL. Si stores.stor_id tiene un valor NULL y discounts.stor_id tambin tiene un valor NULL, no existira ninguna unin y discounts.stor_id devolver NULL porque no existe ningn valor coincidente. Un valor NULL nunca es igual a otro valor NULL. Nota: A partir de la versin SQL server 7.0, un valor null nunca es igual a otro valor null. Pero puede ocurrir que mantenga el servidor de SQL compatibilidad con la versin 6.5, teniendo desactivados los ANSI_NULLS a travs de las opciones de servidor o de una instruccin SET. El tener desactivado los ANSI_NULLS es una infraccin al estndar ANSI y ya no es compatible con la configuracin actual de SQL Server. FULL JOIN Esta clusula tambin es conocida como FULL OUTER JOIN, hace corresponder los datos de ambos lados de JOIN, independientemente del lado JOIN que sea. Aunque al principio parece una muy buena eleccin, luego casi nunca se usa. Con FULL JOIN podremos obtener todos los registros coincidentes basndonos en el campo (o campos) de JOIN. Tambin podremos obtener cualquier registro existente en la parte de la izquierda, devolvindose todas las columnas con valores NULL de la parte derecha. Pero tambin podemos obtener cualquier registro existente slo en la parte derecha, devolviendo los valores NULL de las columnas de la parte izquierda. Usamos la base de datos Pubs. Ejemplo:Captulo 4. Programacin en ADO. Pgina 22

SELECT ta.au_fname, ta.au_lname, tp.pub_name FROM authors ta FULL OUTER JOIN publishers tp ON ta.city = tp.city ORDER BY tp.pub_name En este ejemplo podemos ver que ha obtenido los registros coincidentes de ambos lados, colocando NULL cuando en la otra tabla no haba valores. CROSS JOIN Es una clusula bastante extraa en su funcionamiento y su uso bastante restringido. Se sabe que para aplicaciones matemticas, se suele aplicar, ya que lo que hace en realidad es generar tablas cartesianas. No dispone del operador ON, a diferencia de las otras instrucciones JOIN. Vemos un ejemplo de su aplicacin: SELECT a.au_fname, a.au_lname, p.pub_name FROM authors a CROSS JOIN publishers p Como podemos ver en los resultados, obtiene todas las filas de authors, a las que le aade el equivalente de publishers, y todas las filas de publishers a las que le aade el equivalente de authors. Es decir, multiplicando el nmero de registros de una tabla por otra, sabremos cuantos registros obtendr la consulta. 4.2.6. Create Create se aplica tanto a bases de datos como a tablas. El comando Create soporta dos variantes en funcin de si creamos una Base de Datos, o creamos una tabla dentro de la Base de Datos. Crear la Base de Datos: CREATE DATABASE Crear la tabla: CREATE TABLE [nombrebasedatos] nombretabla( ) Estructura de los tipos de datos:Tipo SQL Integer Real Float Char Varchar Binary DATE Tipo MS Access Nmero entero largo Nmero simple Nmero doble Texto Texto Binario Fecha/Hora Tipo SQL Framework SqlInt32 SqlSingle SqlDouble SqlString SqlString SqlBinary SqlDateTime de .NET

Captulo 4. Programacin en ADO.

Pgina 23

La diferencia entre el tipo char y Varchar, radica en que el primero (longitud fija) rellena con espacios en blanco la longitud de texto que no se haya usado y el segundo no (longitud variable). Es decir, al final el char debe obligatoriamente grabar un nmero concreto de bytes definidos por su tamao, mientras que Varchar, podr almacenar cualquier valor de bytes que no exceda su longitud mxima. Adems de Varchar, existe en SQL el tipo NVarchar. La diferencia entre ambos radica en que cualquier tipo de datos de SQl que empiece por N, utiliza la codificacin Unicode que implica que para guardar un carcter utiliza dos bytes y por tanto, usa un juego de caracteres mucho mayor. Estos ltimos no se suelen usar a no ser que se use por problemas de compatibilidad con aplicaciones o, por que se usa en idiomas como el japons. Cuando se crean columnas en la base de datos, es posible especificar si una columna concreta es la clave principal de la tabla (PRIMARY KEY). Esto significa que una columna del tipo Primary Key, no puede tener ni valores del tipo null, ni valores duplicados (unique). Este campo ser el punto de acceso de la base de datos a los datos de la tabla. Tambin podemos hacer que un campo, sin ser Primary Key, contenga datos que no sean duplicados. Para ello, usaremos la clusula UNIQUE. Esto hace que sea el propio sistema de bases de datos, el que verifique si existe el dato en la tabla y no sea necesario realizar por programa una comprobacin. La clusula NOT NULL permite que no se pueda dejar un campo sin informacin, es decir, que el campo contenga el valor de tipo null (sin datos). Ejemplo de creacin de una tabla: CREATE TABLE Empleados(Nombre VARCHAR(30) NOT NULL, Apellidos VARCHAR(50) NOT NULL, Direccion VARCHAR(100) NOT NULL, Departamento VARCHAR(30) NOT NULL)

4.2.7. La instruccin DROP Esta instruccin permite borrar una base de datos o una tabla. Su sintaxis es la siguiente: Borrar la Base de Datos: DROP DATABASE Crear la tabla: DROP TABLE

Captulo 4. Programacin en ADO.

Pgina 24

4.3. El objeto DataTableEl objeto DataTable, al igual que el objeto DataSet que veremos ms adelante, existen desde las primeras versiones de Net Framework. Son tan importantes para el conjunto de datos, que han ido aumentando en prestaciones e importancia con las distintas versiones. El DataSet ha sido siempre el ncleo de ADO .Net, proporcionando una representacin en memoria interna de datos relacionales, incluidos claves, restricciones e incluso capacidad de consulta. Muchas veces se trabaja con una sola tabla, y el uso del DataSet era casi obligado, dado que el objeto DataTable fuera de l no tena muy buena funcionalidad. A partir de la versin de Net Framework 2.0, se mejor notablemente la clase DataTable, convirtindola en un elemento muy importante y con una funcionalidad propia que hace que ya no sea dependiente del objeto DataSet. Un DataTable es en realidad un representacin de una tabla de datos, donde encontramos otros dos objetos: el DataColumn, que permite especificar y manejar las columnas; y el objeto DataRow, que permite acceder a las filas de la tabla. Adems podemos aplicar restricciones usando el objeto Constrains, as como relaciones entre tablas usando el objeto DataRelations. ADO, por mediacin del DataTable y el DataSet, proveen de todos los elementos necesarios para desarrollar una base de datos sin necesidad de contar con un proveedor especfico. El DataTable, incluye la coleccin DataRowCollection de objetos DataRow (filas de la tabla), la coleccin DataColumnCollectiom de objetos DataColumn (columna de datos) y la coleccin ConstraintCollection de objetos Constraint (restricciones).

4.3.1. Cargar valores en una tabla. El objeto DataColumn y DataRow 4.3.1.1. El objeto DataColumn. Para crear una tabla, es necesario empezar por definir las columnas que contendrn la tabla. Una columna tiene dos valores importantes a definir: el nombre de la columna y el tipo de dato que contiene. Podemos declarar la columna de dos formas: Podemos aadir columnas a la coleccin de columnas del objeto DataTable, especificando el nombre de la columna y el tipo de datos que guarda:Captulo 4. Programacin en ADO. Pgina 25

TablaDatos.Columns.Add("Producto", typeof(string));

Una variante de esta forma podra ser esta:Type Cadena = typeof(string); TablaDatos.Columns.Add("Producto", Cadena);

En ambos casos declaramos la columna con su nombre y su tipo. Pero si lo que queremos es utilizar ms funcionalidades de las columnas, como son los valores autoincrementados, campos clave y dems, la forma sera:DataColumn ColumnaIdentidad = new DataColumn(); ColumnaIdentidad.AutoIncrement = true; ColumnaIdentidad.AutoIncrementSeed = 1; ColumnaIdentidad.AutoIncrementStep = 1; ColumnaIdentidad.DataType = typeof(int); ColumnaIdentidad.Unique = true;

En este ejemplo, hemos creado una columna que ser una columna del tipo autoincrementado, cuyo valor inicial es 1 (AutoIncrementSeed) y los incrementos sern de uno en uno (AutoIncrementStep). La propiedad Unique a true indica que la columna es de valores nicos, lo que significa que no puede contener valores repetidos. Una vez declarada la columna, la forma de agregarla a la coleccin de columnas del objeto DataTable sera:TablaDatos.Columns.Add(ColumnaIdentidad);

Cuando cargamos las distintas columnas en el objeto DataTable, lo que tenemos, es la estructura de la tabla. Pero ahora es el momento de empezar a dar valores utilizando para ello el objeto DataRow. 4.3.1.2. El objeto DataRow. Este objeto tiene la finalidad de crear una fila que cumpla con la estructura de la tabla, para posteriormente, dar de alta los valores que contendr la tabla. Podemos crear una fila, especificando manualmente las columnas que contendr, pero dado que usaremos el objeto DataRow para dar de alta una fila sobre un objeto DataTable ya creado, lo razonable sera crear una fila nueva a partir del objeto DataTable:DataRow FilaInsertar = TablaDatos.NewRow();

En este ejemplo, hemos creado una fila con la estructura que tiene el objeto DataTable, TablaDatos. Suponiendo que la tabla sea una tabla que contenga las siguientes columnas: Nombre, Apellidos y DNI, la forma de dar valores sera:Captulo 4. Programacin en ADO. Pgina 26

FilaInsertar[0] = "Alvaro"; FilaInsertar[1] = "Snchez Snchez"; FilaInsertar[2] = 5746565-K;

En este ejemplo, cmo podemos observar, utilizamos el nombre del objeto DataRow facilitando entre corchetes el nmero de columna al que deseamos dar valores. Se comporta como una matriz o coleccin y el ndice comienza en cero. Tambin es posible dar el nombre de la columna en lugar del ndice. Por ltimo, para aadir los valores al DataTable:TablaDatos.Rows.Add(FilaInsertar);

DataRow, incluye la propiedad RowState, que permite saber si la fila cambi y cal fue el motivo del cambio, pudiendo conocer cualquier de estos estados: Added (aadir), Deleted (borrar), Modified (modificar) y Unchanged (sin cambios). Existe adems el DataView, que representa una vista personalizada que puede enlazar datos de un DataTable para ordenacin, filtrado, bsqueda, edicin y exploracin.

4.3.2. Recorrer los valores de un DataTable Las filas de un objeto DataTable son una coleccin y por tanto podemos recorrerla con un bucle for o con un bucle foreach:for (int i = 0; i < TablaDatos.Rows.Count; i++) { DataRow Fila = TablaDatos.Rows[i]; richTextBox1.Text += Fila[1]; }

En este ejemplo, obtenemos del objeto DataRow, Fila, el valor de la columna 1 (Fila[1]). Si en lugar de usar un bucle for usamos un bucle foreach:foreach (DataRow Fila in TablaDatos.Rows) richTextBox1.Text += Fila[1];

Como podemos observar, es ms cmodo utilizar un bucle foreach que un bucle for. 4.3.3. Recorrer los valores de un DataTable usando un DataReader. Por mediacin del objeto DataTableReader, podemos implementar un DataReader, con un funcionamiento similar a un ADO Conectado (este punto se ver ms adelante en este mismo captulo).Captulo 4. Programacin en ADO. Pgina 27

DataTableReader Lector = TablaDatos.CreateDataReader(); while (Lector.Read()) { MessageBox.Show(Lector[2].ToString()); }

En este ejemplo hemos implementado un objeto DataTableReader que nos permite recorrer el DataTable como si fuera una consulta realizada en modo ADO Conectado. Las filas del DataTable son volcadas a Lector y, al igual que si fuera un objeto DataRow, podemos sacar el valor de la columna, bien sea por su ndice o por su nombre. Las columnas del lector son de tipo object. Ver Uso DataTable-01

4.3.4. Cargar un fichero XML en un DataTable. El XML se ha convertido en un estndar para el intercambio de informacin entre proveedores de datos. En .Net disponemos de la posibilidad de cargar un DataTable desde un fichero en XML. A partir de la versin de Net Framework 2.0, se mejor notablemente la clase DataTable, convirtindola en un elemento muy importante y con una funcionalidad propia que hace que sea muchas veces til sin necesidad de contar con un objeto DataSet. Dentro de las nuevas funcionalidades que se dieron al objeto DataTable, est la posibilidad de leer y cargar un fichero XML en el objeto. Implementa los mtodos ReadXml y WriteXml, similar al uso que tienen en el DataSet. El mtodo ReadXml permite leer un fichero XML a un objeto DataTable:DataTable objDataTable = new DataTable("MisClientes"); objDataTable.ReadXml("Clientes.xml");

En este ejemplo, cuando creamos el DataTable, le damos un nombre a la tabla, en este caso: MisClientes. A continuacin, usando el mtodo ReadXml, cargamos el fichero clientes.xml dentro del DataTable. Automticamente, se generan las columnas y las filas dentro del mismo.

4.3.5. Grabar un DataTable en un fichero XML. Otra de las posibilidades es escribir el contenido de un DataTable dentro de un fichero XML, lo que nos permite un fcil intercambio de informacin con los actuales sistemas de bases de datos y aplicaciones. Para poder realizar una escritura del DataTable en el fichero XML, utilizamos el mtodo WriteXML.Captulo 4. Programacin en ADO. Pgina 28

DataTable objDataTable = new DataTable(); objDataTable.Columns.Add("IDCliente", typeof(int)); objDataTable.Columns.Add("NombreCliente", typeof(string)); objDataTable.Columns.Add("ApellidosCliente", typeof(string)); objDataTable.Rows.Add(new object[] { 1, "Pedro", "Lpez Snchez" }); objDataTable.Rows.Add(new object[] { 2, "Mara Jos", "Martnez" }); objDataTable.Rows.Add(new object[] { 3, "Jesus", "Snchez Alpino" }); objDataTable.Rows.Add(new object[] { 4, "Ana", "Moreno Lpez" }); objDataTable.WriteXml("clientes.xml", XmlWriteMode.WriteSchema);

En este ejemplo, usamos el mtodo WriteXml de los DataTable para grabar el fichero XML con los datos contenidos dentro del DataTable, objDataTable. A pesar de que en la documentacin de MSDN indica que la inferencia de esquemas es posible en un DataTable desde datos XML, el hecho de inferir esquemas en tiempo de ejecucin desde XML provoca una excepcin que indica que no es compatible con la clase DataTable. Para evitar esto, en el ejemplo Uso DataTableXML, se usa la opcin XmlWriteMode.WriteSchema para incluir el esquema en la parte superior del documento. Ejemplo Uso DataTableXML

Captulo 4. Programacin en ADO.

Pgina 29

4.4. El objeto DataSetEl DataSet representa una cache de memoria con datos y es el eje de la arquitectura ADO.NET. Cada DataSet puede contener varios objetos DataTable, y cada DataTable contiene datos de un solo origen, como SQL Server o Access. Igualmente y, como hemos visto anteriormente, podemos crear un DataTable con datos locales sin necesidad de conectar a ningn origen de datos en SQL. Este DataTable, evidentemente, tambin puede ser cargado dentro del DataSet. Es decir, el DataSet puede mantener mltiples datos que pertenecen a distintos orgenes de datos. El DataSet, incluye la coleccin DataTableCollection de objetos DataTable (que son las tablas de datos) y la coleccin DataRelationCollection de objetos DataRelation (relaciones entre las tablas). Para conectar datos a un DataSet podemos usar un objeto DataAdapter (se estudiar ms adelante), que almacena los datos ledos del origen de datos en un conjunto de datos. Cuando deseamos modificar ese origen de datos desde nuestra aplicacin, volver a realizar la conexin con el origen de datos, suministrndole la nueva informacin desde el conjunto de datos que se encuentra en nuestra mquina. Podramos acceder directamente al origen de datos por mediacin de comandos de SQL o procedimientos almacenados. 4.4.1. Cargar objetos DataTable en el DataSet El elemento bsico de informacin dentro de un DataSet es el DataTable. Por tanto, no tiene sentido crear un DataSet si luego no vamos a cargar en su interior objetos DataTable. Para cargar un DataTable dentro del DataSet disponemos de la coleccin Tables del DataSet. Por ejemplo://Damos nombres a las tablas. objDataTable1.TableName = "Empleados"; objDataTable2.TableName = "Categorias"; //Agregamos las tablas al DataSet. objDataSet.Tables.Add(objDataTable1); objDataSet.Tables.Add(objDataTable2);

En este ejemplo, aadimos a la coleccin Tables del DataSet el objeto objDataTable1 y el objetoDataTable2, ambos del tipo DataTable. Previamente, usando la propiedad TableName, hemos asignado un nombre a cada Tabla. 4.4.2. Relacionar objetos DataTable Una funcin muy importante de los DataSet es la de manejar los DataTable como si de una Base de Datos Relacional se tratara. Esto nos permite crear DataTables dentro del DataSet, para despus vincularlos entre sCaptulo 4. Programacin en ADO. Pgina 30

y aumentar las prestaciones de los datos. En la siguiente figura podemos ver el diseador de DataSet con varias tablas y las relaciones entre ellas.

Diseador de DataSetRelaciones entre DataTables

Nombre del DataTable

Columnas del DataTable. Objeto DataColumn

Objetos DataTable

Figura: Imagen del Diseador de DataSet.

Ver Uso DataSet-ADO. Si usamos el diseador de DataSet definiremos las relaciones con las herramientas visuales que para ello tiene definido el objeto. Pero en el caso de que necesitemos desarrollar todo el trabajo desde el cdigo, los pasos a seguir son: Definir las columnas que actuaran como campos clave dentro del DataTable, especificando incluso las caractersticas de unicidad, campo clave y dems caractersticas que usaramos en una tabla dentro de un gestor de bases de datos relacional. Ejemplo://Creamos una columna que ser columna clave del DataTable. //Ser una columna de autoincremento y valores nicos. DataColumn IdEmpleado = new DataColumn("IdEmpleado", typeof(int)); IdEmpleado.AutoIncrement = true; IdEmpleado.AutoIncrementSeed = 1; IdEmpleado.AutoIncrementStep = 1; IdEmpleado.Unique = true; //Agregamos la columna a la coleccin de columnas del DataTable objDataTable1.Columns.Add(IdEmpleado); //Creamos una matriz de columnas con la columna o columnas que sern //Columna clave en la tabla. DataColumn[] Claves = { IdEmpleado }; //Especificamos que columna o columnas son la clave del DataTable. objDataTable1.PrimaryKey = Claves;

Captulo 4. Programacin en ADO.

Pgina 31

A continuacin creamos las relaciones que pudieran existir entre las distintas tablas dentro del DataSet, tal y como podemos ver en este ejemplo://Existe una columna que es la clave principal y otra que es la clave //fornea. //Definimos dos objetos DataColumn con los nombres de las dos columnas //que vamos a relacionar. DataColumn ClavePrincipal = objDataSet.Tables["Categorias"].Columns["IdCategoria"]; DataColumn ClaveForanea = objDataSet.Tables["Empleados"].Columns["IdCategoria"]; //A Continuacin aplicamos la relacin. DataRelation relacionClaves = new DataRelation("RelacionCategoria", ClavePrincipal, ClaveForanea); objDataSet.Tables["Empleados"].ParentRelations.Add(relacionClaves);

4.4.3. Obtener objetos DataTable. Para obtener un DataTable que se encuentra dentro de un DataSet, accedemos por mediacin de la coleccin Tables, igual que cuando guardamos el DataTable. Ejemplo:DataTable objTabla = objDataSet.Tables["Empleados"];

En este ejemplo hemos accedido al DataTable Empleados y colocado una copia en objTabla. Tambin podemos acceder por el ndice del DataTable dentro de la coleccin de Tables del DataSet. Por ejemplo, si sabemos que el DataTable Empleados es el cero dentro del ndice, podemos recuperarlo de la siguiente forma:DataTable objTabla = objDataSet.Tables[0];

4.4.3.1. El mtodo Select de los DataTable. Podemos obtener datos de un objeto DataTable usando el mtodo Select. En este caso, la informacin es volcada sobre un objeto del tipo matriz de DataRow. El mtodo Select se comporta de una forma muy similar a la instruccin Select del T-SQL. Un ejemplo de aplicacin del mtodo Select sera:DataRow[] Filas = objDataSet.Tables["Empleados"].Select("IdCategoria = 2");

En este ejemplo obtenemos todas las filas del DataTable Empleados cuyo valor de IdCategoria sea 2. Las filas coincidentes son guardadas en la matriz del tipo DataRow Filas.Captulo 4. Programacin en ADO. Pgina 32

Otro ejemplo sera:DataRow[] Filas = objDataSet.Tables["Empleados"].Select("IdCategoria = 2 AND NombreEmpleado = 'Miguel Angel'");

En este otro ejemplo, la bsqueda se realizar por el IdCategoria igual a 2 y, por el NombreEmpleado igual a Miguel Angel. Si deseamos obtener los datos ordenados, podemos incluir el parmetro Sort del mtodo Select:DataRow[] Filas = objDataSet.Tables["Empleados"].Select("IdCategoria = 2", "NombreEmpleado DESC");

Este ejemplo ordena los resultados por la columna NombreEmpleado y de formas descendente (DESC). Por defecto es ascendente. Otra posibilidad de ordenacin sera:DataRow[] Filas = objDataSet.Tables["Empleados"].Select("IdCategoria = 2", "ApellidosEmpleado ASC, NombreEmpleado ASC");

En este otro caso el resultado es ordenado primeramente por la columna ApellidosEmpleado de forma ascendente y por la columna NombreEmpleado de forma tambin ascendente. Otra posibilidad es obtener filas que cumplan un criterio basado en si han sido borradas, modificadas u obtener sus valores originales. Para este punto disponemos del miembro enumerable DataViewRowState:DataRow[] Filas = objDataSet.Tables["Empleados"].Select(null, null, DataViewRowState.Added);

En este ejemplo obtiene todas las filas que fueron aadidas al DataTable. Las distintas posibilidades del DataViewRowState son: Valor de DataViewRowState Added CurrentRows Deleted ModifiedCurrent ModifiedOriginal OriginalRows Unchanged None Significado Fila nueva Las filas actuales, incluyendo las agregadas, modificadas y sin modificar. Fila eliminada La versin actual, que es una modificacin de los datos actuales. La versin original de todas las filas modificadas. Las filas originales, incluyendo las filas que fueron eliminadas. Fila sin modificar. Ninguno

Captulo 4. Programacin en ADO.

Pgina 33

Parmetros y expresiones vlidas en el mtodo Select de los DataTable:Para utilizar una columna denominada "Column#" en una expresin, se deber escribir "[Column#]". Ejemplo: Total * [Column#] Puesto que los corchetes son caracteres especiales, se debe utilizar una barra diagonal ("\") para crear un carcter de escape para el corchete, si forma parte de un nombre de columna. Por ejemplo, una columna denominada "Column[ ]" se escribir: Total * [Column[\]] Slo se debe crear un carcter de escape para el segundo corchete. Valores Definidos por el Usuario Los valores definidos por el usuario se pueden utilizar en expresiones para compararlos con valores de columnas. Los valores de cadena se deben escribir entre comillas sencillas. Los valores de fecha se deben poner entre signos de libra esterlina (#) o comillas simples (') dependiendo del proveedor de datos. Se permiten decimales y notaciones cientficas para los valores numricos. Por ejemplo: "FirstName = 'John'" "Precio