Manual de ASP PÁGINAS DINÁMICAS CONCEPTO DE PÁGINAS DINÁMICAS Muy probablemente, estimado lector, seas una persona más o menos familiarizada con el lenguaje HTML y con toda seguridad hayas desarrollado algún sitio basado en esta herramienta. En realidad el HTML no es lenguaje de programación sino, más bien, se trata de un lenguaje descriptivo que tiene como objeto dar formato al texto y las imágenes que pretendemos visualizar en el navegador. A partir de este lenguaje somos capaces de introducir enlaces, seleccionar el tamaño de las fuentes o intercalar imágenes, todo esto de una manera prefijada y en ningún caso inteligente. En efecto, el HTML no permite el realizar un simple cálculo matemático o crear una página de la nada a partir de una base de datos. A decir verdad, el HTML, aunque muy útil a pequeña escala, resulta bastante limitado a la hora de concebir grandes sitios o portales. Es esta deficiencia del HTML la que ha hecho necesario el empleo de otros lenguajes accesorios mucho más versátiles y de un aprendizaje relativamente más complicado, capaces de responder de manera inteligente a las demandas del navegador y que permiten la automatización de determinadas tareas tediosas e irremediables como pueden ser las actualizaciones, el tratamiento de pedidos de una tienda virtual... Estos lenguajes capaces de recrear a partir de ciertos "scripts" un sinfín de páginas automatizadas son los protagonistas de este concepto de páginas dinámicas. Este manual, que no es mas que una introducción a otros manuales en curso de redacción, esta destinado a aquellos que sienten que el HTML se les queda corto para realizar sus proyectos y que, sin tener ni idea de programar, desean dar el paso y darle un nuevo aire a sus páginas sin por ello pasar por experiencias traumáticas debidas a su poca afinidad con los lenguajes informáticos. El contenido ha sido, por lo tanto, deliberadamente simplificado y será ampliado posteriormente a partir de anexos y artículos de mayor nivel para que pueda ser también utilizado por aquellos que ya están familiarizados con este tipo de lenguajes. PÁGINAS DINÁMICAS VS HTML A pesar de que las páginas dinámicas nos puedan en un principio limitar a causa de su mayor complejidad con respecto al HTML, todas las ventajas que nos ofrecen compensan con creces este esfuerzo inicial. No obstante, hay que ser consciente del posible interés que pueda tener para uno el lanzarse en esta aventura de aprender un nuevo lenguaje y volver a rediseñar su propio sitio. Si la página en la que estamos pensando o que queremos rediseñar es relativamente pequeña, no necesita estar al día continuamente sino que sus contenidos son perennes y no hemos previsto el pagar por mantenerla, el empleo de páginas dinámicas puede quedarse grande y resultar a todas luces improductivo. Por el contrario, si el sitio es extenso y sus contenidos cambian rápidamente, nos interesa el automatizar en la medida de lo posible todas las tareas de tal forma que podamos gestionar su explotación de la manera más óptima. Para dejar más claro hasta que punto resulta útil utilizar páginas dinámicas lo mejor será ejemplificarlo a partir de un sitio web modelo. Supongamos que hemos decidido realizar un portal de televisión donde una de las informaciones principales a proveer podría ser la programación semanal. Efectivamente, esta información suele ser dada por las televisiones con meses de antelación y podría ser muy fácilmente almacenada en una base de datos. Si trabajásemos con páginas HTML, tendríamos que construir una página independiente para cada semana en la cual introduciríamos "a mano" cada uno de los programas de cada una de las cadenas. Asimismo, cada semana nos tendríamos que acordar de descolgar la página de la semana pasada y colgar la de la anterior. Todo esto podría ser fácilmente resuelto mediante páginas dinámicas. En este caso, lo que haríamos sería crear un programa (solo uno) que se encargaría de recoger de la base de datos de la programación aquellos programas que son retransmitidos en las fechas que nos interesan y de confeccionar una página donde aparecerían ordenados por cadena y por hora de retransmisión. De este modo, podemos automatizar un proceso y desentendernos de un aspecto de la página por unos meses. Este hecho lo podríamos aplicar a otras situaciones: podemos preparar el horóscopo de todos los días, las promociones de un sitio de e-comercio... Además, tampoco resultaría complicado el introducir una pequeña caja de búsqueda que nos permitiera dar rápidamente con el programa que queremos ver, saber a qué hora y en qué cadena se emite. Volviendo a nuestro portal de televisión, en él hay una sección en la cual presentamos todas las series actualmente emitidas con comentarios sobre ella, fotos, etc. Podríamos, en lugar de hacer una página HTML por serie, hacer una única página dinámica en contacto con una base de datos en la cual visualizamos las fotos y comentarios relativos a la serie que nos interesa. Asimismo, si lo que buscamos DGH Informática y Logística -1- Manual de ASP es modificar el formato del texto de dicha sección, podemos automatizar este proceso sin necesidad de cambiar a mano cada una de las etiquetas font y sin hacer uso de la hojas de estilo las cuales no son reconocidas por la totalidad de los navegadores. Otra serie de aspectos tales como la gestión de las lenguas, podrían ser fácilmente resueltos sin para ello duplicar el número de páginas y buscar los textos a traducir penosamente entre el código HTML. En realidad, a partir de estas herramientas, podemos plantearnos cuantas cosas queramos. El único límite... nuestra imaginación LENGUAJES DE LADO SERVIDOR O CLIENTE El navegador es una especie de aplicación capaz de interpretar las órdenes recibidas en forma de código HTML fundamentalmente y convertirlas en las páginas que son el resultado de dicha orden. Cuando nosotros pinchamos sobre un enlace hipertexto, en realidad lo que pasa es que establecemos una petición de un archivo HTML residente en el servidor (un ordenador que se encuentra continuamente conectado a la red) el cual es enviado e interpretado por nuestro navegador (el cliente). Sin embargo, si la página que pedimos no es un archivo HTML, el navegador es incapaz de interpretarla y lo único que es capaz de hacer es salvarla en forma de archivo. Es por ello que, si queremos emplear lenguajes accesorios para realizar un sitio web, es absolutamente necesario que sea el propio servidor quien los ejecute e interprete para luego enviarlos al cliente (navegador) en forma de archivo HTML totalmente legible por él. De modo que, cuando pinchamos sobre un enlace a una pagina que contiene un script en un lenguaje comprensible unicamente por el servidor, lo que ocurre en realidad es que dicho script es ejecutado por el servidor y el resultado de esa ejecucion da lugar a la generacion de un archivo HTML que es enviado al cliente. Así pues, podemos hablar de lenguajes de lado servidor que son aquellos lenguajes que son reconocidos, ejecutados e interpretados por el propio servidor y que se envían al cliente en un formato comprensible para él. Por otro lado, los lenguajes de lado cliente (entre los cuales no sólo se encuentra el HTML sino también el Java y el JavaScript los cuales son simplemente incluidos en el código HTML) son aquellos que pueden ser directamente "digeridos" por el navegador y no necesitan un pretratamiento. Cada uno de estos tipos tiene por supuesto sus ventajas y sus inconvenientes. Así, por ejemplo, un lenguaje de lado cliente es totalmente independiente del servidor, lo cual permite que la página pueda ser albergada en cualquier sitio sin necesidad de pagar más ya que, por regla general, los servidores que aceptan páginas con scripts de lado servidor son en su mayoría de pago o sus prestaciones son muy limitadas. Inversamente, un lenguaje de lado servidor es independiente del cliente por lo que es mucho menos rígido respecto al cambio de un navegador a otro o respecto a las versiones del mismo. Por otra parte, los scripts son almacenados en el servidor quien los ejecuta y traduce a HTML por lo que permanecen ocultos para el cliente. Este hecho puede resultar a todas luces una forma legítima de proteger el trabajo intelectual realizado. LENGUAJES DE LADO SERVIDOR Existe una multitud de lenguajes concebidos o no para Internet. Cada uno de ellos explota más a fondo ciertas características que lo hacen más o menos útiles para desarrollar distintas aplicaciones. La versatilidad de un lenguaje está íntimamente relacionada con su complejidad. Un lenguaje complicado en su aprendizaje permite en general el realizar un espectro de tareas más amplio y más profundamente. Es por ello que a la hora de elegir el lenguaje que queremos utilizar tenemos que saber claramente qué es lo que queremos hacer y si el lenguaje en cuestión nos lo permite o no. En el dominio de la red, los lenguajes de lado servidor más ampliamente utilizados para el desarrollo de páginas dinámicas son el ASP, PHP y PERL. El ASP (Active Server Pages) es un lenguaje derivado del Visual Basic desarrollado por Microsoft. Evidentemente su empleo se realiza sobre plataformas funcionando bajo sistema Windows NT. El PHP podría ser considerado como el lenguaje análogo al ASP utilizado en plataformas Unix y Linux. Estos dos lenguajes resultan bastante útiles para la explotación de bases de datos y su aprendizaje resulta accesible para una persona profana de la programación. Cualquiera de ellos resultaría la opción ideal a la hora de hacer evolucionar un sitio web realizado en HTML. Por otra parte, el PERL es un lenguaje más rápido y potente que requiere obviamente un aprendizaje más largo y resulta más reservado para personas ya familiarizadas con la verdadera programación. ALGUNOS ASPECTOS PRÁCTICOS PREVIOS DGH Informática y Logística -2- Manual de ASP Antes de lanzarnos en las consideraciones teóricas relativas a la programación, resultaría interesante aclarar algunas dudas que puede presentarse referentes a cómo escribir y publicar páginas dinámicas. Para escribir una página dinámica podemos hacerlo del mismo modo que si lo hiciésemos en HTML. En realidad, el código está constituido exclusivamente de texto y lo único que tenemos que hacer por lo tanto es guardar el archivo texto con una extensión que pueda ser reconocida posteriormente por el servidor. Así, por ejemplo, las páginas de ASP son reconocidas por su extensión "asp" del mismo modo que las de PHP lo son a partir de extensiones "php" u otras en las que se especifica la versión utilizada ("php3" o "php4"). En muchos casos el servidor nos permite seleccionar qué tipo de extensión debe ser reconocida para un determinado lenguaje por lo que estas extensiones no están totalmente generalizadas aunque son sin duda las más utilizadas. Dado que se trata únicamente de archivos texto, es posible crear páginas dinámicas a partir del Bloc de Notas o cualquier otro procesador de texto plano (Texto ASCII, sin códigos raros como los que pone MS Word). También podemos utilizar los editores clásicos empleados para el HTML aunque en este caso, estamos obligados a trabajar en modo editar y no en modo gráfico. Esta última posibilidad resulta tanto menos aconsejable cuanto que la mayoría de estos editores no están preparados para la programación en estos lenguajes y algunos de ellos (Frontpage en sus versiones anteriores a la 2000, sin ir más lejos) están dispuestos a borrar aquellos textos que no es capaz de interpretar. Existen sin embargo algunos editores de HTML que si ofrecen ventajas al editar scripts. Tal es el caso del Homesite que muestra coloraciones diferentes en función de la sintaxis del programa lo cual permite una lectura más fácil. Además, hay otra serie de editores más pensados para páginas dinámicas en general o para algún lenguaje en particular. Una vez el programa realizado, el paso inmediato es el de ejecutarlo. Como ya ha sido explicado, los lenguajes de lado servidor ejecutan los scripts en el propio servidor y envían el resultado en forma de código HTML al cliente (navegador). Resulta obvio que para probar entonces el programa es necesario colgar por FTP los archivos que lo componen en el servidor y hacer la petición desde el navegador. En principio, no es por tanto posible el trabajar offline a partir de archivos alojados en el disco duro tal y como hacíamos con el HTML. Esto en realidad no es completamente cierto ya que existe la posibilidad de convertir nuestro propio ordenador en servidor web personal de manera que podemos trabajar en local sin necesidad de estar conectados continuamente lo cual podría representar un problema para aquellos que tengan que pagar una factura telefónica al estar conectados por modem además de resultar más juicioso puesto que un servidor no es el sitio ideal para hacer nuestros pinitos en un lenguaje que no controlamos suficientemente. Bucles infinitos, variables no cerradas y otra serie de irregularidades pueden estar consumiendo recursos importantes en perjuicio de los usuarios que estén accediendo a otras paginas albergadas por este servidor. Como puede verse, la forma de operar resulta casi análoga a lo que hacíamos para nuestro sitio estático y no presenta ninguna complicación aparente. Cabe destacar que, como ya se ha dicho anteriormente, para poder servirse de estos lenguajes de lado servidor, es imprescindible que el servidor esté preparado para leer las páginas programadas en un lenguaje no comprendido por el navegador. Dichos servidores son en su gran mayoría de pago lo cual añade ciertas limitaciones económicas al proyecto. CONCEPTOS BÁSICOS DE PROGRAMACIÓN I Antes de abordar en detalle las particularidades de estos lenguajes, es importante guardar en espíritu toda una serie de nociones básicas comunes. Estos aspectos son sin duda conocidos por aquellos que hayan programado alguna vez y pueden ser muy rápidamente asimilados por todos los que estén familiarizados con las matemáticas. Teniendo en cuenta esto, hemos querido acercar estos conceptos a cualquier persona proponiendo definiciones poco rigurosas y carentes de detalles pero que en contrapartida permiten ser digeridas con más facilidad. Así pues, aquellos sugerimos el pasar directamente al siguiente capítulo a todos aquellos que consideren conocer perfectamente los conceptos de variable y función aunque siempre puede resultar interesante volver a recordarlo visto desde el prisma de otra definición. Variable Una variable consiste en un elemento al cual le damos un nombre y le atribuimos un determinado tipo de información. Las variables pueden ser consideradas como la base de la programación. De este modo podríamos escribir en un lenguaje ficticio: a="perro" b="muerde" DGH Informática y Logística -3- Manual de ASP La variable que nosotros llamamos "a" posee un elemento de información de tipo texto que es "perro". Asimismo, la variable "b" contiene el valor "muerde". Podríamos definir una tercera variable que fuese la suma de estas dos: c=a+b Si introdujésemos una petición de impresión de esta variable en nuestro lenguaje ficticio: imprimir(c) El resultado podría ser: perro muerde Podríamos de la misma forma trabajar con variables que contuviesen números y construir nuestro programa: a=3 b=4 c=a+b imprimir(c) El resultado de nuestro programa sería: 7 La utilidad de estas variables quedará de relieve en el transcurso de los siguientes capítulos. CONCEPTOS BÁSICOS DE PROGRAMACIÓN II Funciónes y procedimientos La función podría ser definida como un conjunto de instrucciones que permiten procesar las variables para obtener un resultado. Puede que esta definición resulte un poco vaga si no nos servimos de un ejemplo para ilustrarla. Supongamos que queremos calcular el valor total de un pedido a partir de la simple suma de los precios de cada uno de los artículos. Podríamos definir una función suma en nuestro lenguaje ficticio: definir funcion suma(art1,art2,art3) suma=art1+art2+art3 imprimir(suma) fin funcion Este supuesto programa nos permitiría calcular la suma de tres elementos e imprimir el resultado en pantalla. Lo interesante de utilizar este tipo de funciones es que ellas nos permiten su utilización sistemática tantas veces como queramos sin necesidad de escribir las instrucciones tantas veces como veces queremos utilizarla. Por supuesto, podemos prescindir de esta declaración de función e introducir una línea del siguiente tipo: imprimir(art1+art2+art3) Evidentemente, cuanto más complicada sea la función y más a menudo la utilicemos en nuestros scripts más útil resulta definirlas. Esta función suma podría ser utilizada en cualquier lugar de nuestro script haciendo una llamada del siguiente tipo: ejecuta suma(4,6,9) Cuyo resultado sería: 19 Del mismo modo, los procedimientos son parecidos a las funciones. La diferencia consiste tan solo en que en estos últimos el interés no radica en el resultado obtenido sino más bien en las operaciones realizadas al ejecutarla (creación de un archivo, reenvío a otra página,...). En lenguajes como el PHP las funciones y los procedimientos son considerados como la misma cosa y para definirlos se hace usando los mismos comandos. DGH Informática y Logística -4- Manual de ASP Tanto las variables como las funciones y los procedimientos deben ser nombradas sin servirse de acentos, espacios ni caracteres especiales para no correr riesgos de error . Estos conceptos son básicos para una comprensión de la programación. No obstante, es posible que si es la primera vez que oímos hablar de ellos, su asimilación puede resultar parcial o nula. En realidad esto no es preocupante ya que a partir de los ejemplos de los capítulos siguientes y con la práctica de uno mismo se irán consolidando poco a poco. DGH Informática y Logística -5- Manual de ASP PROGRAMACIÓN EN ASP INTRODUCCIÓN A LA PROGRAMACIÓN EN ASP Tal como hemos explicado, ASP (Active Server Pages) es la tecnología para la creación de páginas dinámicas del lado del servidor desarrollada por Microsoft. Las páginas ASP comienzan a ejecutarse cuando un usuario solicita un archivo .ASP al servidor Web a través del explorador. El servidor web llama a ASP, que lee el archivo solicitado, ejecuta las secuencias de comandos que encuentre y envía los resultados al explorador del cliente. Puesto que las secuencias de comandos se ejecutan en el servidor, y NO en el cliente, es el servidor el que hace todo el trabajo necesario para generar las paginas que se envían al explorador. Las secuencias de comandos quedan ocultas a los usuarios, estos solo reciben el resultado de la ejecución en formato HTML. Desaparece por tanto el problema de si el cliente puede o no ejecutar sentencias de comandos, el servidor Web solo envía el resultado en código HTML estandard interpretable por cualquier explorador. Un archivo .ASP puede contener texto, código HTML, código ASP o cualquier combinación de estos. Si no contiene código ASP se comporta como un archivo .HTML normal. Nota: todos los archivos .asp requieren una parte de proceso por el servidor, por lo cual no es conveniente convertir a .asp los archivos que no contengan código. El tipo de servidores que emplean este lenguaje son aquellos que funcionan con sistema operativo de la familia de Windows NT. Afortunadamente, también podemos visualizar páginas ASP sobre Windows 95/98, pero esto lo veremos más adelante. Para escribir páginas ASP utilizamos un lenguaje de scripts, que se colocan en la misma página web junto con el código HTML. Comúnmente este lenguaje de scripts es Visual Basic Script, que deriva del conocido Visual Basic, aunque también se pueden escribir los scripts ASP en otro lenguaje: JScript, que deriva a su vez del conocido Javascript. Existe una versión de Visual Basic Script en el lado cliente y otra en el lado del servidor. En los dos casos, como su nombre indica, el lenguaje de base es Visual Basic por lo que su aprendizaje puede ser perfectamente coordinado, ya que las sentencias y las sintaxis son prácticamente las mismas. En ASP, al estar programando páginas del lado del servidor, utlizaremos Visual Basic Script del lado del servidor y en este manual nos centraremos en este punto. Este manual va destinado a aquellos que quieren comenzar de cero el aprendizaje de este lenguaje y que buscan en él la aplicación directa a su proyecto de sitio o a la mejora de su sitio HTML. Los capítulos son extremadamente simples, sino simplistas, buscando ser accesibles a la mayoría. Ellos serán complementados posteriormente con otros artículos de mayor nivel destinados a gente más experimentada. PASOS PREVIOS I: INSTALACIÓN DEL PWS En capítulos anteriores hemos explicado que, dada la naturaleza de los lenguajes de lado servidor, nos es imposible trabajar offline como hacíamos para el caso de las páginas HTML que almacenábamos en nuestro disco duro. También dijimos que esto no era completamente cierto ya que podíamos resolver este eventual problema instalándonos en nuestro PC un servidor propio. Este servidor distribuido por Microsoft tiene dos versiones diferentes que son utilizadas dependiendo del equipo que estemos utilizando. Para los usuarios de W95 o W98, la versión disponible se llama Personal Web Server (PWS). Si trabajamos bajo sistema Windows NT, o las versiones Profesional y Server de Windows 2000 y XP, el servidor a instalar es el Internet Information Server (IIS). Existe también la posibilidad de trabajar en plataformas UNIX empleando en este caso el ChilisoftASP. Los usuarios de W95 tienen varias posibilidades para hacerse con el PWS: Descargarlo del sitio Microsoft , a partir de una antigua versión de Frontpage 98, instalándolo desde la opción pack de W-NT 4.0 o desde el CD de instalación de W98 (directorio add-ons/pws). DGH Informática y Logística -6- Manual de ASP Por otro lado, los usuarios de Windows 2000 deben utilizar IIS 5.0, que se encuentra en la instalación. Es recomendable que leáis también las notas de los visitantes al pie de página, porque encontraréis muchos más datos sobre problemas en distintas versiones y compatibilidades con otros sistemas que van apareciendo. Algunas versiones del PWS anteriores a la 4.0 requieren un archivo adicional asp.exe para poder reconocer páginas ASP. PWS podría ser considerado como una versión "light" del IIS4. En realidad en PWS no es suficientemente versátil para ejercer de servidor de un sitio de un tamaño mediano aunque si que podría en un momento dado hacerse cargo de un sitio de tamaño reducido y no muy concurrido. De todas formas, la utilidad del PWS radica sobre todo en que nos permite realizar las pruebas del sitio que vayamos a desarrollar en "local" sin necesidad de colgar nuestros archivos en el servidor que alberga nuestro sitio cada vez que queramos hacer una prueba sobre una pequeña modificación introducida. Esto resulta a todas luces práctico sobre todo para principiantes que necesitan hacer pruebas con una relativa frecuencia permitiendo el ahorro de mucho tiempo. Dado que la mayoría de los posibles lectores de este manual trabajan en entorno W95 y 98, en este capítulo nos limitaremos a la descripción del PWS dejando el IIS4 para futuros capítulos. Sin embargo, las explicaciones que damos pueden ser igualmente útiles para quienes tengan que utilizar este último el cual presenta un funcionamiento básico análogo. El uso del PWS es extremadamente fácil. Una vez instalado, podemos observar la introducción de un nuevo icono en la barra de tareas así que en el menú de inicio correspondientes a la aplicación. A partir de cualquiera de ellos podemos tener acceso a la página principal o gestionario. El siguiente paso es crear un directorio virtual dentro del cual alojaremos nuestra página. Hablamos de directorio virtual debido a que nuestra página puede estar alojada en cualquier parte de nuestro disco duro, donde a nosotros nos plazca y con un nombre de directorio que tampoco tiene por qué parecerse al que incluiremos en la URL cuando queramos ejecutar la página. De hecho, la URL que debemos introducir en el navegador para visualizar nuestra página ASP es del tipo: http://localhost/nombre_del_directorio virtual/archivo.asp Como se puede observar, en este tipo de dirección no se especifica el camino en el disco duro donde se encuentran nuestros archivos. Volviendo a la creación de nuestro directorio virtual, para hacerlo debemos pinchar sobre el icono "Avanzado" el cual nos da acceso a las opciones avanzadas del PWS. Una vez ahí, el siguiente paso es "Agregar" un directorio virtual. Una ventana en la que tendremos que introducir el nombre de dicho directorio virtual y especificar en qué carpeta del disco duro tenemos guardados los archivos y carpetas de la página aparecerá. Como puede verse, la cosa es fácil. Ahora no queda más que introducir en el navegador el tipo de URL mencionada anteriormente para ejecutar los scripts creados. Una opción interesante en el menú avanzado es la selección del tipo de archivo que será ejecutado por defecto. Aquí podríamos poner archivos con nombre index.html o index.asp o bien con el nombre default o home... DGH Informática y Logística -7- Manual de ASP PASOS PREVIOS II: CONEXIÓN A BD El siguiente paso, una vez instalado el servidor que nos permite trabajar en local, es crear los vínculos con las bases de datos que explotaremos en nuestros scripts. En efecto, la utilización de páginas dinámicas está muy frecuentemente asociada con el empleo de bases de datos. Una base de datos es sencillamente un conjunto de tablas en las que almacenamos distintos registros (artículos de una tienda virtual, proveedores o clientes de una empresa, películas en cartelera en el cine...). Estos registros son catalogados en función de distintos parámetros que los caracterizan y que presentan una utilidad a la hora de clasificarlos. Así, por ejemplo, los artículos de una tienda virtual podrían catalogarse a partir de distintos campos como puede ser un número de referencia, nombre del artículo, descripción, precio, proveedor... Las bases de datos son construidas sirviéndose de aplicaciones tales como el Microsoft Access o el MySQL las cuales resultan bastante sencillas de utilizar con unos conceptos mínimos. Nuestro objeto aquí no es explicar la forma de explotarlas sino cómo establecer una conexión entre la base de datos, almacenada en cualquier lugar del disco duro y nuestra página web alojada también en cualquier parte y reconocida por nuestro servidor personal a partir del directorio virtual. Para crear este vínculo, nos servimos de los conectores ODBC (Open DataBase Connectivity) los cuales establecen el enlace con la base de datos. El primer paso para crear esta conexión es ir al panel de configuración y abrir el icono ODBC 32bits. Dentro de él, deberemos crear un DSN (Data Source Name) de tipo sistema o usuario. Para ello nos colocamos en la solapa correspondiente (DSN sistema o DSN usuario) y seleccionamos "Añadir". A continuación se nos pedirá seleccionar los controladores de la aplicación que hemos utilizado para crear la base de datos, el nombre que le queremos asignar (aquel que empleemos en nuestros scripts) y el camino para encontrarla en el disco duro. Esta DSN permite en realidad definir la base de datos que será interrogada sin necesidad de pasar por la aplicación que hayamos utilizado para construirla, es decir, con simples llamadas y órdenes desde nuestros archivos ASP podremos obtener los datos que buscamos sin necesidad de ejecutar el Access o el MySQL los cuales, evidentemente, no tendrán por qué encontrarse en el servidor donde trabajemos. FUENTES DE DATOS ODBC La administración de orígenes de datos ODBC (Open Database Connectivity) es una utilidad general de Windows NT. Permite que las aplicaciones accedan a los datos a través usando SQL como lenguaje estándar. Se administran a través de la ventana ODBC del Panel de Control. Se pueden configurar tres diferente fuentes de datos ODBC, la forma más interesante es la de DSN del sistema, que presenta la ventaja de poder ser accedida por cualquier usuario, siendo el tipo usado en aplicaciones ASP. DGH Informática y Logística -8- Manual de ASP CONFIGURACIÓN DE UNA FUENTE DE DATOS En este ejemplo declaramos una base de datos Access, el procedimiento es prácticamente igual para cualquier otra tecnología de bases de datos. Para declarar una base de datos ODBC haremos doble clik en el icono Fuentes de Datos ODBC que encontraremos en el panel de control de Windows (Inicio->Configuración->Panel de Control), una vez abierto el programa nos situaremos en la pestaña DSN deSistema. Pulsaremos el botón AGREGAR para añadir una nueva fuente de datos, lo que nos llevara a la pantalla de controladores. En esta ventana elegiremos el driver adecuado para la tecnología de la base de datos que queremos tratar desde nuestras páginas ASP y pulsaremos finalizar. La siguiente pantalla que se nos muestra nos pedirá la ubicación física de nuestra base de datos y el nombre ODBC con el que queremos acceder a ella. Nombre de origen de datos: Es el nombre simbólico de nuestra base de datos, será el queutilicemos desde ASP para referirnos a ella. DGH Informática y Logística -9- Manual de ASP Descripción: Es una descripción de la base de datos Base de datos: Es el camino físico de la base de datos, para establecerlo pulsaremos el botón SELECCIONAR y mediante un explorador elegiremos nuestra fuente de datos. Una vez hecho esto pulsaremos el botón ACEPTAR y ya tendremos nuestra base de datos disponible para su uso desde nuestras aplicaciones Web. NOTA: Si nuestro sistema operativo es NT y declaramos una base de datos ACCESS debemos de tener en cuenta que ACCESS crea en el mismo directorio de la base de datos un fichero con extensión .ldb cuando cualquier usuario interactúa con la base de datos. Ello nos obliga a dar derechos suficientes al usuario de IIS (IUSR_Nombre del equipo) para manipular el directorio de la base de datos. INICIO A LA PROGRAMACIÓN EN ASP A lo largo de los capítulos precedentes nos ha quedado claro que el ASP es un lenguaje orientado a las aplicaciones en red creado por Microsoft que funciona del lado servidor. Es en efecto el servidor quien se ocupa de ejecutarlo, interpretarlo y enviarlo al cliente (navegador) en forma de código HTML. ASP es principalmente utilizado sirviéndose del lenguaje Visual Basic Script que no es más que una versión light del Visual Basic. Sin embargo, es posible programar páginas ASP en Java Script. Lo único que hay que hacer es especificar en la propia página qué tipo de lenguaje estamos utilizando. Dado que el lenguaje ASP está muy frecuentemente embebido dentro del código HTML, es importante poder marcar al servidor qué partes están escritas en un lenguaje y cuáles en otro. Es por ello que todas las partes del archivo que están escritas en ASP estarán siempre delimitadas por los símbolos: <% y %>. De este modo, cuando realicemos nuestros scripts, lo primero que debemos definir es el tipo de lenguaje utilizado, lo cual se hace del siguiente modo: <% @ LANGUAGE="VBSCRIPT" %> Para el caso en el que programemos en Visual Basic Script <% @ LANGUAGE="JSCRIPT" %> Si nos servimos del Java Script en servidor para programar en ASP Los scripts que serán presentados en este manual estarán basados en el VBS, el cual presenta toda una serie de prestaciones que lo hacen sin duda más accesible y apto para ASP. No es por nada que es el propio Microsoft quien ha creado ambos. Con los elementos que hemos presentado hasta ahora, ya estamos en situación de poder escribir nuestro primer programa en ASP. Vamos a crear un programa que calcule el 20% de impuestos que habría que añadir a una serie de artículos. Para plasmar el concepto de función, explicado en el manual de páginas dinámicas, vamos a definir una función "impuesto" que emplearemos sucesivas veces. El programa podría resultar algo así (VBScript no distingue entre mayúsculas y minúsculas): <% @ LANGUAGE="VBSCRIPT" %> DGH Informática y Logística - 10 - Manual de ASP <HTML> <HEAD> <TITLE>Funcion impuesto</TITLE> </HEAD> <BODY> <%Function impuesto(precio_articulo) precio_final=precio_articulo+precio_articulo*20/100 Response.Write precio_final End Function%> Un libro de 3500 ptas. se quedará en un precio de <% impuesto(3500) %> <br> Una camisa de 6000 ptas. tendrá un precio final de <% impuesto(6000) %> <br> Un CD de música de 2000 ptas. costaría <% impuesto(2000) %> ptas. </BODY> </HTML> Como puede verse, el script contiene dos partes fundamentales: Una primera en la que definimos la función que llamamos impuesto que depende únicamente de una variable (precio_articulo). Impuesto permite añadir un 20% al precio del artículo e imprimir el resultado en pantalla (Response.Write). En la segunda parte nos servimos de la función para realizar los cálculos necesarios y mostrarlos en pantalla acompañados de texto. Resulta muy interesante, una vez ejecutado el script, ver el código fuente. Como puede verse, el código HTML que muestra el browser no coincide con el que nosotros hemos escrito. Algo que no debe sorprendernos ya que, como ya hemos explicado, el servidor se encarga de procesarlo y hacerlo comprensible al navegador. BUCLES Y CONDICIONES I La programación exige en muchas ocasiones la repetición de acciones sucesivas o la elección de una determinada secuencia y no de otra dependiendo de las condiciones específicas de la ejecución. Como ejemplo, podríamos hacer alusión a un script que ejecute una secuencia diferente en función del día de la semana en el que nos encontramos. Este tipo de acciones pueden ser llevadas a cabo gracias a una paleta de instrucciones presentes en la mayoría de los lenguajes. En este capítulo describiremos someramente algunas de ellas propuestas por el VBS y que resultan de evidente utilidad para el desarrollo de páginas ASP. Las condiciones: IF Cuando queremos que el programa, llegado a un cierto punto, tome un camino determinado en determinados casos y otro diferente si las condiciones de ejecución difieren, nos servimos del conjunto de instrucciones If, Then y Else. La estructura de base de este tipo de instrucciones es la siguiente: IF condición THEN Instrucción 1 Instrucción 2 ... ELSE Instrucción A Instrucción B ... END IF Llegados a este punto, el programa verificará el cumplimiento o no de la condición. Si la condición es cierta las instrucciones 1 y 2 serán ejecutadas. De lo contrario (Else), las instrucciones A y B serán llevadas a cabo. Una vez finalizada la estructura, deberemos cerrar con un End If. Esta estructura de base puede complicarse un poco más si tenemos cuenta que no necesariamente todo es blanco o negro y que muchas posibilidades pueden darse. Es por ello que otras condiciones pueden plantearse dentro de la condición principal. Hablamos por lo tanto de condiciones anidadas que tendrían una estructura del siguiente tipo: IF condición THEN DGH Informática y Logística - 11 - Manual de ASP Instrucción 1 Instrucción 2 ... ELSE IF condición2 THEN Instrucción A Instrucción B ... ELSE Instrucción X ... END IF END IF De este modo podríamos introducir tantas condiciones como queramos dentro de una condición principal. En este tipo de estructuras es importante cerrar correctamente cada uno de los IF con sus END IF correspondientes. De gran ayuda es la instrucción ELSE IF que permite en una sola línea y sin necesidad de añadir un END IF introducir una condición anidada. El uso de esta herramienta resultará claro con un poco de práctica. Pongamos un ejemplo sencillo de utilización de condiciones. El siguiente programa permitiría detectar la lengua empleada por el navegador y visualizar un mensaje en dicha lengua. <% @ LANGUAGE="VBSCRIPT" %> <HTML> <HEAD> <TITLE>Detector de Lengua</TITLE> </HEAD> <BODY> <% 'Antes de nada introducimos mensajes en forma de variables espanol="Hola" ingles="Hello" frances="Bonjour" 'Ahora leemos del navegador cuál es su lengua oficial idioma=Left(Request.ServerVariables("HTTP_ACCEPT_LANGUAGE"),2) 'Formulamos las posibilidades que se pueden dar If idioma="es" Then Response.Write espanol ElseIf idioma="fr" Then Response.Write frances Else Response.Write ingles End If %> </BODY> </HTML> Para poder ver el funcionamiento de este script es necesario cambiar el idioma preferido lo cual puede ser realizado a partir del menú de opciones del navegador. Como puede verse, las variables que contienen texto son almacenadas entre comillas. Para leer la lengua aceptada por el navegador lo que hacemos es definir una variable (idioma) que recoge las dos primeras letras empezando por la izquierda del idioma aceptado por el navegador ("HTTP_ACCEPT_LANGUAGE"). Este idioma aceptado puede ser requerido como una variable del objeto ServerVariables. Por el momento dejaremos esto tal cual, ya nos encargaremos de verlo más detenidamente en otros capítulos. La tercera parte de script se encarga de ver si el navegador está en español (es), francés (fr) o en cualquier otro idioma que no sea ninguno de estos dos y de imprimir cada uno de los mensajes que proceda en cada caso. DGH Informática y Logística - 12 - Manual de ASP Otro punto a comentar es el hecho de poder comentar los programas. Como puede observarse, dentro del script hemos introducido unos mensajes que nos sirven para leerlo más fácilmente. Estos mensajes no ejercen ninguna influencia en el desarrollo del mismo. Para introducirlos es necesario escribirlos detrás de un apóstrofe: ' Los comentarios son de gran utilidad cuando tratamos con programas muy extensos y complicados los cuales. En estos casos, resultan de gran ayuda a la hora de depurar fallos o introducir modificaciones. Es altamente aconsejable el acostumbrarse a utilizarlos. Bucles y condiciones II Los bucles FOR En muchas ocasiones resulta necesario el ejecutar un conjunto de instrucciones un número definido de veces. Esto puede ser llevado a cabo a partir de la instrucción FOR/NEXT. La estructura clásica: FOR contador=número inicial to número final STEP incremento Instrucción 1 Instrucción 2 ... NEXT A partir de este tipo de estructuras ejecutamos las instrucciones contenidas entre el FOR y el NEXT un cierto número de veces definido por el número inicial, final y el incremento. El incremento resulta de 1 por defecto. Pongamos un ejemplo: <% @ LANGUAGE="VBSCRIPT" %> <HTML> <HEAD> <TITLE>Bucle for/next</TITLE> </HEAD> <BODY> <%For i=1 to 5%> <font size=<%Response.Write i%>>Vuelta número <%Response.Write i%></font><br> <%Next For i=5 to 1 Step -1%> <font size=<%Response.Write i%>>Contamos atrás: <%Response.Write i%></font><br> <%Next%> </BODY> </HTML> Este script compuesto de dos bucles cuenta primero de 1 a 5. La variable i toma por lo tanto todos los valores enteros comprendidos entre estos dos números y puede ser utilizada dentro del bucle como lo hacemos en este caso para aumentar el tamaño de la letra. El segundo bucle realiza el proceso inverso (el incremento es negativo) produciendo una disminución del tamaño de la letra. Lo que puede resultar interesante para ver hasta qué punto el programar páginas dinámicas puede ahorrarnos texto con respecto a la misma página programada en código HTML, es mirar el código fuente de la página a partir del navegador. Bucles y condiciones III Los bucles DO WHILE/LOOP Otra forma de realizar este tipo de secuencias bucle es a partir de la instrucción DO WHILE. En este caso lo que especificamos para fijar la extensión del bucle no es el número de vueltas sino el que se cumpla o no una condición. La estructura de este tipo de bucles es análoga a la de los bucles FOR/NEXT: DO WHILE condición Instrucción 1 Instrucción 2 ... DGH Informática y Logística - 13 - Manual de ASP LOOP El bucle se dará mientras la condición propuesta siga siendo válida. Como se verá en ejemplos posteriores, este tipo de bucles resulta muy práctico para la lectura de bases de datos. Todo este tipo de controladores de flujo (condiciones y bucles) pueden ser matizados y optimizados a partir del uso de operadores lógicos. Así, podemos exigir que sean dos las condiciones que se den para llevar a cabo un conjunto de instrucciones: IF condición 1 AND condición 2 THEN ... También podemos requerir que sea una de las dos: IF condición 1 OR condición 2 THEN... Del mismo modo, es posible exigir que la condición de un bucle DO sea la inversa a la enunciada: DO WHILE NOT condición He aquí, en conclusión, un conjunto de recursos básicos para controlar el desarrollo de programas. Su utilidad resultará más que patente y su uso irá haciéndose intuitivo a medida que nos familiaricemos con el lenguaje. LOS OBJETOS ASP El ASP es un lenguaje diseñado para la creación de aplicaciones en internet. Esto quiere decir que existen toda una serie de tareas bastante corrientes a las cuales debe dar un tratamiento fácil y eficaz. Nos referimos por ejemplo al envío de e-mails, acceso a archivos, gestión de variables del cliente o servidor como pueden ser su IP o la lengua aceptada... El lenguaje VB propiamente dicho no da una solución fácil y directa a estas tareas sino que invoca a los denominados objetos que no son más que unos módulos incorporados al lenguaje que permiten el desarrollo de tareas específicas. Estos objetos realizan de una manera sencilla toda una serie de acciones de una complejidad relevante. A partir de una llamada al objeto este realizará la tarea requerida. En cierta forma, estos objetos nos ahorran el tener que hacer largos programas para operaciones sencillas y habituales. Algunos de estos objetos están incorporados en el propio ASP, otros deben de ser incorporados como si se tratase de componentes accesorios. Por supuesto, no podríamos ejecutar correctamente un script en el cual tuviésemos que llamar a un objeto que no estuviese integrado en el servidor. Este tipo de "plug-in" son generalmente comprados por el servidor a empresas que los desarrollan. Como todo objeto del mundo real, los objetos del mundo informático tienen sus propiedades que los definen, realizan un cierto numero de funciones o métodos y son capaces de responder de una forma definible ante ciertos eventos. Dado el nivel de esta obra, la descripción de la totalidad de objetos con sus métodos y propiedades resulta ciertamente fuera de lugar. Nos contentaremos pues con ir describiendo los más frecuentemente utilizados y ejemplificarlos de la manera más práctica dejando la enumeración exhaustiva en forma de apéndice. OBJETO APPLICATION El objeto Application se utiliza para compartir información entre todos los usuarios de una aplicación (entendemos por una aplicación ASP todos los archivos .asp de un directorio virtual y sus subdirectorios. Como varios usuarios pueden compartir un objeto Application, existen los métodos Lock y Unlock para asegurar la integridad del mismo (varios usuarios no puedan modificar una misma propiedad al mismo tiempo). Lock El método Lock asegura que sólo un cliente puede modificar o tener acceso a las variables de Application al mismo tiempo. Application.Lock Unlock El método Unlock desbloquea el objeto Application para que pueda ser modificado por otro cliente después de haberse bloqueado mediante el método Lock. Si no se llama a este método de forma explícita, DGH Informática y Logística - 14 - Manual de ASP el servidor Web desbloquea el objeto Application cuando el archivo .asp termina o transcurre su tiempo de espera. Application.Unlock Ejemplo: <% Application.Lock Application("visitas") = Application("visitas")+1 Application.Unlock %> Eres el visitante numero <%= Application("visitas") %> En el ejemplo anterior el método Lock impide que más de un cliente tenga acceso a la variable Visitas al mismo tiempo. Si la aplicación no se hubiera bloqueado, dos clientes podrían intentar incrementar simultáneamente el valor de la variable Visitas. El método Unlock libera el objeto bloqueado de forma que el próximo cliente puede incrementar la variable. Nota Importante: En el objeto Application pueden almacenarse matrices, pero estas son almacenadas como un objeto, es decir, no podemos almacenar o recuperar un solo elemento de la matriz, si no que cargaremos o recuperaremos la variable con la matriz completa Ejemplo: <%Dim parametros(2) parametros(0) = "verde" parametros(1) = 640 parametros(2) = 480 Application.Lock Application("Param") =parametros Application.UnLock%> con estas instrucciones almacenaríamos TODA la matriz en la variable de aplicación "Param". Para recuperar los valores de la matriz primero recuperamos esta en una variable normal <%Apliparam=Application("Param")%> Ahora podremos operar con los valores de la tabla en las variables Apliparam(0),Apliparam(1) y Apliparam(2) OBJETO REQUEST I Bucles y condiciones son muy útiles para procesar los datos dentro de un mismo script. Sin embargo, en un sitio internet, las páginas vistas y los scripts utilizados son numerosos. Muy a menudo necesitamos que nuestros distintos scripts estén conectados unos con otros y que se sirvan de variables comunes. Por otro lado, el usuario interacciona por medio de formularios cuyos campos han de ser procesados para poder dar una respuesta. Todo este tipo de factores dinámicos han de ser eficazmente regulados por un lenguaje como el ASP. Como veremos, todo este tipo de aspectos interactivos pueden ser gestionados a partir del objeto Request. El objeto Request nos devuelve informaciones del usuario que han sido enviadas por medio de formularios, por URL o a partir de cookies (veremos de qué se tratan seguidamente). También nos informa sobre el estado de ciertas variables del sistema como pueden ser la lengua utilizada por el navegador, el número IP del cliente... Transferir variables por URL Para pasar las variables de una página a otra lo podemos hacer introduciendo dicha variable en la dirección URL de la página destino dentro del enlace hipertexto. La sintaxis sería la siguiente: <a href="destino.asp?variable1=valor1&variable2=valor2&..."></a> Para recoger la variable en la página destino lo hacemos por medio del objeto Request con el método Querystring: Request.querystring("variable1") Request.querystring("variable2") Las dos páginas serían así: <HTML> <HEAD> DGH Informática y Logística - 15 - Manual de ASP <TITLE>Página origen.asp</TITLE> </HEAD> <BODY> <a href="destino.asp?saludo=hola&texto=Esto es una variable texto">Paso variables saludo y texto a la página destino.asp</a> </BODY> </HTML> <HTML> <HEAD> <TITLE>destino.asp</TITLE> </HEAD> <BODY> Variable saludo: <%Response.Write Request.Querystring("saludo")%><br> Variable texto: <%Response.Write Request.Querystring("texto")%><br> </BODY> </HTML> OBJETO REQUEST II Transferir variables por formulario El proceso es similar al explicado para las URLs. Primeramente, presentamos una primera página con el formulario a rellenar y las variables son recogidas en una segunda página que las procesa: <HTML> <HEAD> <TITLE>formulario.asp</TITLE> </HEAD> <BODY> <FORM METHOD="POST" ACTION="destino2.asp"> Nombre<br> <INPUT TYPE="TEXT" NAME="nombre"><br> Apellidos<br> <INPUT TYPE="TEXT" NAME="apellidos"><br> <INPUT TYPE="SUBMIT"> </FORM> </BODY> </HTML> <HTML> <HEAD> <TITLE>destino2.asp</TITLE> </HEAD> <BODY> Variable nombre: <%=Request.Form("nombre")%><br> Variable apellidos: <%=Request.Form("apellidos")%> </BODY> </HTML> Otras utilidades de Request: las ServerVariables El objeto Request nos da acceso a otras informaciones relativas al cliente y el servidor las cuales pueden resultar de una gran utilidad. Estas informaciones son almacenadas como variables las cuales son agrupadas en una colección llamada ServerVariables. Dentro de esta colección tenemos variables tan interesantes como: HTTP_ACCEPT_LANGUAGE Nos informa de la lengua preferida por el navegador HTTP_USER_AGENT Indica cuál es el navegador utilizado. PATH_TRANSLATED Nos devuelve el path físico del disco duro del servidor en el que se encuentra nuestro script SERVER_SOFTWARE Nos dice qué tipo de software utiliza el servidor DGH Informática y Logística - 16 - Manual de ASP Para visualizar en pantalla alguna de estas variables, debemos escribir algo como: Response.write request.servervariables("nombre de la variable") Una forma rápida de visualizar todas estas variables es a partir de un script con esta secuencia: <% For Each elemento in Request.ServerVariables Response.Write elemento&" : "&Request.ServerVariables(elemento)& "<br>" Next %> Esto nos daría por un lado el nombre de la variable y del otro su valor. Este tipo de bucle For Each/Next se parece a otros ya vistos. En este caso, el bucle se realiza tantas veces como elementos tiene la colección (ServerVariables) que no es más que el conjunto de elementos comprendidos en la extensión del objeto (Request). Este tipo de bucle es aplicable a otras colecciones de éste y otros objetos como por ejemplo los Request.Form o Request.Querystring o las cookies. De esta forma seríamos capaces de visualizar el nombre y contenido de tales colecciones sin necesidad de enunciarlas una por una. OBJETO RESPONSE Tal y como se ha visto, el objeto Request gestiona todo lo relativo a entrada de datos al script por parte del usuario (formularios), provenientes de otra URL, del propio servidor o del browser. Nos queda pues por explicar cómo el script puede "responder" a estos estímulos, es decir, cómo, después de procesar los debidamente los datos, podemos imprimir estos en pantalla, inscribirlos en las cookies o enviar al internauta a una u otra pagina. En definitiva, queda por definir la forma en la que ASP regula el contenido que es enviado al navegador. Esta función es tomada en cargo por el objeto Response el cual ha sido ligeramente mencionado en capítulos precedentes concretamente en asociación al método Write. En efecto, sentencias del tipo: <%Response.Write "Una cadena de texto"%> o bien, <%Response.Write variable%> Tienen como cometido imprimir en el documento HTML generado un mensaje o valor de variable. Este método es tan comúnmente utilizado que existe una abreviación del mismo de manera a facilitar su escritura: <% = variable %> es análogo a <%response.write variable%> Es importante precisar el hecho que imprimir en el documento HTML no significa necesariamente visualizar en pantalla ya que podríamos servirnos de estas etiquetas para crear determinadas etiquetas HTML. He aquí un ejemplo de lo que se pretende decir: <% path="http://www.misitio.com/graficos/imagen.gif" %> <img src="<% =path %>"> Este fragmento de script nos generaría un código HTML que sería recibido en el navegador del siguiente modo: <img src="http://www.misitio.com/graficos/imagen.gif"> Otro elemento interesante de este objeto Response es el método Redirect. Este método nos permite el enviar automáticamente al internauta a una página que nosotros decidamos. Esta función, a todas luces práctica, puede ser empleada en scripts en los que enviamos al visitante de nuestro sitio a una u otra página en función del navegador que utiliza o la lengua que prefiere. También es muy útil para realizar páginas "escondidas" que realizan una determinada función sin mostrar ni texto ni imágenes y nos envían a continuación a otra página que es en realidad la que nosotros recibimos en el navegador. Aquí se puede ver una secuencia de script que nos permitiría usar este método para el caso en el que tengamos páginas diferentes para distintas versiones de navegadores. En ella emplearemos un objeto que nos debe parecer familiar ya que lo acabamos de ver (Request.ServerVariables): <% tipo_navegador = Request.ServerVariables("HTTP_USER_AGENT") DGH Informática y Logística - 17 - Manual de ASP If Instr(1, tipo_navegador, "MSIE 3", 1) <> 0 then Response.Redirect "MSIE3.asp" ElseIf Instr(1, tipo_navegador, "MSIE 4", 1) <> 0 then Response.Redirect "MSIE4.asp" ElseIf Instr(1, tipo_navegador, "MSIE 5", 1) <> 0 then Response.Redirect "MSIE5.asp" ElseIf Instr(1, tipo_navegador, "Mozilla/4", 1) <> 0 then Response.Redirect "Netscape4.asp" Else Response.Redirect "cualquiera.asp" %> Por supuesto, acompañando este script, debemos tener los correspondientes archivos MSIE3.asp, MSIE4.asp, MSIE5.asp... Cada uno de ellos con las particularidades necesarias para la buena visualización de nuestra página en tales navegadores. LAS FAMOSAS COOKIES Sin duda este término resultara familiar para muchos. Algunos lo habrán leído u oído pero no saben de qué se trata. Otros sin embargo sabrán que las cookies son unas informaciones almacenadas por un sitio web en el disco duro del usuario. Esta información es almacenada en un archivo tipo texto que se guarda cuando el navegador accede al sitio web. Es posible, por supuesto, ver estos archivos. Para abrirlos hay que ir al directorio C:\Windows\Cookies para los usuarios de IE 4+ o a C:\...\Netscape\Users\defaultuser para usuarios de Netscape. Como podréis comprobar, en la mayoría de los casos la información que se puede obtener es indescifrable. La utilidad principal de las cookies es la de poder identificar al navegador una vez éste visita el sitio por segunda vez y así, en función del perfil del cliente dado en su primera visita, el sitio puede adaptarse dinámicamente a sus preferencias (lengua utilizada, colores de pantalla, formularios rellenados total o parcialmente, redirección a determinadas páginas...). Para crear un archivo cookies, modificar o generar una nueva cookie lo podemos hacer a partir del objeto Response con una sintaxis como la siguiente: Response.Cookies("nombre de la cookie") = valor de la cookie El valor de la cookie puede ser una variable, un numero o una cadena delimitada por comillas. Es importante saber que las cookies tienen una duración igual a la sesión, es decir, a menos que lo especifiquemos, el archivo texto generado se borrará desde el momento en que el usuario haya abandonado el sitio por un tiempo prolongado (generalmente unos 20 minutos) o que el navegador haya sido cerrado. Podemos arreglar este supuesto inconveniente mediante la propiedad Expires: Response.Cookies("nombre de la cookie").expires = #01/01/2002# Esto nos permite decidir cual es la fecha de caducidad de la cookie. Hay que tener en cuenta que esto no es más que hipotético ya que el usuario es libre de borrar el archivo texto cuando le plazca. Por otra parte, es interesante señalar que el hecho de que definir una cookie ya existente implica el borrado de la antigua. Del mismo modo, el crear una primera cookie conlleva la generación automática del archivo texto. Para leer las cookies, nada más fácil que usando el objeto Request de la siguiente forma: variable = Request.Cookies("nombre de la cookie") Si por ejemplo quisiéramos recuperar del archivo txt la cookie correspondiente a la lengua del cliente y almacenarlo en nuestro script para futuros usos, podríamos escribir: lengua=Request.Cookies("lengua") Las cookies son una herramienta fantástica para personalizar nuestra página pero hay que ser cautos ya que, por una parte, no todos los navegadores las aceptan y por otra, se puede deliberadamente impedir al navegador la creación de cookies. Es por ello que resultan un complemento y no una fuente de variables infalible para nuestro sitio. Nota: Cuando usamos Response para escribir uan cookie, si esa ya existía, se sobreescribe. OBJETO SERVER DGH Informática y Logística - 18 - Manual de ASP El objeto Server nos proporciona acceso a métodos y propiedades del servidor. Propiedades ScriptTimeout Especifica la cantidad maxima de tiempo que puede tardar la ejecución de una secuencia de comandos (Tiempo maximo que puede tardar en ejecutarse una página dada). Server.ScriptTimeout= nº de segundos Ejemplo: <% Server.ScriptTimeout=120 %> La página puede ejecutarse durante 120 segundos antes de que el servidor la termine. Metodos CreateObject Crea una instancia de un componente ActiveX en el servidor. Server.CreateObject (IdProg) IdProg es el identificativo del tipo de componente que queremos crear, nos viene suministrado por el fabricante del componente. Ejemplo: <% set Mitabla = CreateObject("ADODB.Recordset") %> Instancia un objeto de tipo recordset y lo asigna a la variable "Mitabla". OBJETO SESSION En los programas que hemos visto hasta ahora, hemos utilizado variables que solo existían en el archivo que era ejecutado. Cuando cargábamos otra página distinta, los valores de estas variables se perdían a menos que nos tomásemos la molestia de pasarlos por la URL o inscribirlos en las cookies o en un formulario para su posterior explotación. Estos métodos, aunque útiles, no son todo lo prácticos que podrían en determinados casos en los que la variable que queremos conservar ha de ser utilizada en varios scripts diferentes y distantes los unos de los otros. Podríamos pensar que ese problema puede quedar resuelto con las cookies ya que se trata de variables que pueden ser invocadas en cualquier momento. El problema, ya lo hemos dicho, es que las cookies no son aceptadas ni por la totalidad de los usuarios ni por la totalidad de los navegadores lo cual implica que una aplicación que se sirviera de las cookies para pasar variables de un archivo a otro no sería 100% infalible. Nos resulta pues necesario el poder declarar ciertas variables que puedan ser reutilizadas tantas veces como queramos dentro de una misma sesión. Imaginemos un sitio multilingüe en el que cada vez que queremos imprimir un mensaje en cualquier página necesitamos saber en qué idioma debe hacerse. Podríamos introducir un script identificador de la lengua del navegador en cada uno de los archivos o bien declarar una variable que fuese valida para toda la sesión y que tuviese como valor el idioma reconocido en un primer momento. Estas variables que son válidas durante una sesión y que luego son "olvidadas" son definidas con el objeto Session de la siguiente forma: Session("nombre de la variable") = valor de la variable Una vez definida, la variable Session, será almacenada en memoria y podrá ser empleada en cualquier script del sitio web. En el objeto Session pueden almacenarse matrices, pero estas son almacenadas como un objeto, es decir, no podemos almacenar o recuperar un solo elemento de la matriz, si no que cargaremos o recuperaremos la variable con la matriz completa Ejemplo: <%Dim cestacompra(2) cestacompra(0) = 1 cestacompra(1) = 8 cestacompra(2) = 22 DGH Informática y Logística - 19 - Manual de ASP Session("Cesta") =cestacompra%> Con estas instrucciones almacenaríamos TODA la matriz en la variable de sesión "Cesta". Para recuperar los valores de la matriz primero recuperamos esta en una variable normal: <%Micesta=Session("Cesta")%> Ahora podremos operar con los valores de la tabla en las variables Micesta(0), Micesta(1) y Micesta(2). La duración de una sesión viene definida por defecto en 20 minutos. Esto quiere decir que si en 20 minutos no realizamos ninguna acción, el servidor dará por finalizada la sesión y todas las variables Session serán abandonadas. Esta duración puede ser modificada con la propiedad Timeout: Session.Timeout = n° de minutos que queramos que dure Una forma de borrar las variables Session sin necesidad de esperara que pase este plazo es a partir del método Abandon: Session.Abandon De este modo todas las variables Session serán borradas y la sesión se dará por finalizada. Este método puede resultar practico cuando estemos haciendo pruebas con el script y necesitemos reinicializar las variables. Lo que se suele hacer es crear un archivo en el que se borran las cookies y se abandona la sesión. Este archivo será ejecutado cuando queramos hacer borrón y cuenta nueva: <% @ LANGUAGE="VBSCRIPT" %> <HTML> <HEAD> <TITLE>Puesta a cero</TITLE> </HEAD> <BODY> <% For Each galleta in Response.Cookies Galleta="" Next Session.Abandon %> Borrón y cuenta nueva!!<br> <a href="url de la página de inicio">Volver al principio</a> </BODY> </HTML> TRABAJAR CON BASES DE DATOS EN ASP Una de las principales ventajas que presenta el trabajar con páginas dinámicas es el poder almacenar los contenidos en bases de datos. De esta forma, podemos organizarlos, actualizarlos y buscarlos de una manera mucho más simple. ASP nos ofrece una forma muy eficaz de interaccionar con estas bases de datos gracias al uso del componente ADO (ActiveX Data Objects) el cual permite acceder a dichas bases de una forma sencilla. Este ADO no es más que un conjunto de objetos que, utilizados en conjunto, nos permiten explotar de una forma muy versátil las bases de datos de nuestra aplicación. No entraremos por el momento en consideraciones teóricas al respecto. Por otra parte, lo scripts ASP deben establecer un dialogo con la base de datos. Este dialogo se lleva a cabo a partir de un idioma universal: el SQL (Structured Query Language) el cual es común a todas las bases de datos En este manual de ASP nos limitaremos a utilizar las instrucciones básicas que serán aprendidas a medida que explicamos las diferentes formas de actuar sobre una base de datos a partir de páginas ASP. La base de datos que ha sido utilizada en estos ejemplos es MS Access. No es por supuesto la única si bien es la más corriente en pequeños PCs y resulta absolutamente operativa siempre que las tablas no sean astronómicamente grandes. Esperamos poder ofreceros próximamente también un pequeño curso de Access en el que explicar los principios rudimentarios necesarios para poder servirnos de él. No obstante, esta aplicación resulta suficientemente fácil e intuitiva como para poder prescindir de dicho curso por el momento. DGH Informática y Logística - 20 - Manual de ASP Así pues, para sumergirnos en estos capítulos siguientes, hemos de cumplir los siguientes requisitos técnicos: -Instalar el PWS -Enlazar la base de datos con ODBC -Instalar el MS Access (viene dentro del pack Office) -Disponer de un browser y un editor (MS IE y Home Site son nuestras humildes recomendaciones) Selecciones en una tabla Dentro de una base de datos, organizada por tablas, la selección de una tabla entera o de un cierto numero de registros resulta una operación rutinaria. A partir de esta selección se puede posteriormente efectuar toda una serie de cambios o bien realizar una simple lectura. El siguiente script nos permite realizar la lectura de la tabla clientes contenida en nuestra base de datos. A primera vista todo nos puede parecer un poco complejo, pero nada más lejos de la realidad. <HTML> <HEAD> <TITLE>Lectura de registros de una tabla</TITLE> </HEAD> <BODY> <h1><div align="center">Lectura de la tabla</div></h1> <br> <br> <% 'Antes de nada hay que instanciar el objeto Connection Set Conn = Server.CreateObject("ADODB.Connection") 'Una vez instanciado Connection lo podemos abrir y le asignamos la base de datos donde vamos a efectuar las operaciones Conn.Open "Mibase" 'Ahora creamos la sentencia SQL que nos servira para hablar a la BD sSQL="Select * From Clientes Order By nombre" 'Ejecutamos la orden set RS = Conn.Execute(sSQL) 'Mostramos los registros%> <table align="center"> <tr> <th>Nombre</th> <th>Teléfono</th> </tr> <% Do While Not RS.Eof %> <tr> <td><%=RS("nombre")%></td> <td><%=RS("telefono")%></td> </tr> <% RS.MoveNext Loop 'Cerramos el sistema de conexion Conn.Close %> </table> <div align="center"> DGH Informática y Logística - 21 - Manual de ASP <a href="insertar.html">Añadir un nuevo registro</a><br> <a href="actualizar1.asp">Actualizar un registro existente</a><br> <a href="borrar1.asp">Borrar un registro</a><br> </div> </BODY> </HTML> Antes de nada, si lo que deseamos es interrogar una base de datos, lo primero que hay que hacer es obviamente establecer la conexión con ella. Esto se hace a partir del objeto Connection el cual es "invocado" o más técnicamente dicho instanciado por medio de la primera instrucción en la cual el objeto toma el nombre arbitrario de la variable Conn . El paso siguiente es abrir el objeto y asignarle la base de datos con la que debe contactar. En este caso, la base la hemos llamado Mibase. Este debe de ser el mismo nombre con el que la hemos bautizado cuando hemos configurado los conectores ODCB, además, este nombre no tiene por qué coincidir necesariamente con el nombre del archivo. Una vez creada la conexión a nuestra base de datos, el paso siguiente es hacer nuestra petición. Esta petición puede ser formulada primeramente y almacenada en una variable (sSQL) para, a continuación, ser ejecutada por medio de la instrucción siguiente. La petición que hemos realizado en este caso es la de seleccionar todos los campos que hay en la tabla clientes (* es un comodín) y ordenar los resultados por orden alfabético con respecto al campo nombre. El resultado de nuestra selección es almacenado en la variable RS en forma de tabla. Para ver la tabla lo que hay que hacer ahora es "pasearse" por esta tabla "virtual" RS la cual posee una especie de cursor que, a menos que se especifique otra cosa, apunta al primer registro de la selección. El objetivo ahora es hacer desplazarse al cursor a lo largo de la tabla para poder leerla en su totalidad. La forma de hacerlo es a partir de un bucle Do While el cual ya ha sido explicado anteriormente y que lo único que hace es ejecutar las instrucciones comprendidas entre el Do y el Loop siempre que la condición propuesta (Not RS.Eof) sea verdadera. Esto se traduce como "Ejecutar este conjunto de instrucciones mientras que la tabla de resultados (RS) no llegue al final (Eof, End of File). Las instrucciones incluidas en el bucle son, por un lado, la impresión en el documento de los valores de determinados campos ( =RS("nombre del campo")) y por otro, saltar de un registro al otro mediante la instrucción RS.MoveNext. Todo este conjunto de instrucciones ASP viene en combinación con un código HTML que permite su visualización en forma de tabla. Además, se han incluido unos enlaces que apuntan hacia otra serie de scripts que veremos más adelante y que formaran en conjunto una aplicación. Es interesante ver el código fuente resultante de este script. En este caso el código que ve el cliente resulta sensiblemente más sencillo. Creación de un nuevo registro En este caso lo que buscamos es crear, a partir de los datos recibidos de un formulario, un nuevo registro en nuestra tabla clientes. Tendremos pues dos archivos diferentes, uno que podría ser un HTML puro en el que introducimos el formulario a rellenar y que nos envía al segundo, un script muy parecido al previamente visto para realizar una selección. He aquí los dos scripts: <HTML> <HEAD> <TITLE>Insertar.html</TITLE> </HEAD> <BODY> <div align="center"> <h1>Insertar un registro</h1> <br> <FORM METHOD="POST" ACTION="insertar.asp"> Nombre<br> <INPUT TYPE="TEXT" NAME="nombre"><br> Teléfono<br> <INPUT TYPE="TEXT" NAME="telefono"><br> <INPUT TYPE="SUBMIT" value="Insertar"> </FORM> </div> </BODY> DGH Informática y Logística - 22 - Manual de ASP </HTML> <HTML> <HEAD> <TITLE>Insertar.asp</TITLE> </HEAD> <BODY> <% 'Recogemos los valores del formulario nombre=Request.Form("nombre") telefono= Request.Form("telefono") 'Instanciamos y abrimos nuestro objeto conexion Set Conn = Server.CreateObject("ADODB.Connection") Conn.Open "Mibase" 'Ahora creamos la sentencia SQL sSQL="Insert Into Clientes (nombre,telefono) values ('" & nombre & "','" & telefono & "')" 'Ejecutamos la orden set RS = Conn.Execute(sSQL) %> <h1><div align="center">Registro Insertado</div></h1> <div align="center"><a href="lectura.asp">Visualizar el contenido de la base</a></div> <% 'Cerramos el sistema de conexion Conn.Close %> </BODY> </HTML> Como puede verse, la forma de operar es idéntica a la vista anteriormente para el display de una tabla. En este caso hemos introducido un enlace a este primer script de lectura para ver cómo los cambios se han hecho efectivos. La construcción de la sentencia SQL se hace por fusión de los distintos elementos constitutivos. La forma de fusionarlos mediante el símbolo &. Todo lo que sea texto tiene que ir entre comillas. Sería interesante introducir una línea suplementaria en vuestro código para imprimir la sSQL formada. La línea sería del siguiente tipo: Response.Write sSQL Esta línea iría situada evidentemente después de haber construido la sentencia. Actualización de un registro existente Para mostrar cómo se actualiza un registro presente en nuestra base de datos, vamos a hacerlo a partir de un caso un poco más complejo para que empecemos a familiarizarnos con estas operaciones. Realizaremos un par de scripts que permitan cambiar el numero de teléfono de las distintas personas presentes en nuestra base. El nombre de estas personas, así como el nuevo numero de teléfono, serán recogidos por medio de un formulario. El archivo del formulario va a ser esta vez un script ASP en el que efectuaremos una llamada a nuestra base de datos para construir un menú desplegable donde aparezcan todos los nombres. La cosa quedaría así: <HTML> <HEAD> <TITLE>Actualizar1.asp</TITLE> </HEAD> DGH Informática y Logística - 23 - Manual de ASP <BODY> <div align="center"> <h1>Actualizar un registro</h1> <br> <% 'Instanciamos y abrimos nuestro objeto conexion Set Conn = Server.CreateObject("ADODB.Connection") Conn.Open "Mibase" %> <FORM METHOD="POST" ACTION="actualizar2.asp"> Nombre<br> <% 'Creamos la sentencia SQL y la ejecutamos sSQL="Select nombre From clientes Order By nombre" set RS = Conn.Execute(sSQL) %> <select name="nombre"> <% 'Generamos el menu desplegable Do While not RS.eof%> <option><%=RS("nombre")%> <%RS.movenext Loop %> </select> <br> Teléfono<br> <INPUT TYPE="TEXT" NAME="telefono"><br> <INPUT TYPE="SUBMIT" value="Actualizar"> </FORM> </div> </BODY> </HTML> La manera de operar para construir el menú desplegable es la misma que para visualizar la tabla. De nuevo empleamos un bucle Do While que nos permite mostrar cada una de las opciones. El script de actualización será muy parecido al de inserción: <TITLE>Actualizar2.asp</TITLE> </HEAD> <BODY> <% 'Recogemos los valores del formulario nombre=Request.Form("nombre") telefono= Request.Form("telefono") 'Instanciamos y abrimos nuestro objeto conexion Set Conn = Server.CreateObject("ADODB.Connection") Conn.Open "Mibase" 'Ahora creamos la sentencia SQL sSQL="Update Clientes Set telefono='" & telefono & "' Where nombre='" & nombre & "'" 'Ejecutamos la orden set RS = Conn.Execute(sSQL) %> <h1><div align="center">Registro Actualizado</div></h1> DGH Informática y Logística - 24 - Manual de ASP <div align="center"><a href="lectura.asp">Visualizar el contenido de la base</a></div> <% 'Cerramos el sistema de conexion Conn.Close %> </BODY> </HTML> Nada que comentar al respecto salvo la estructura de la sentencia SQL que en este caso realiza un Update en lugar de un Insert. Aconsejamos, como para el caso precedente imprimir el valor de sSQL de manera a ver cómo queda la sentencia una vez construida. Borrado de un registro Otra de las operaciones elementales que se pueden realizar sobre una base de datos es el borrar un registro. Para hacerlo, SQL nos propone sentencias del tipo Delete. Veámoslo con un ejemplo aplicado a nuestra agenda. Primero, crearemos un menú desplegable dinámico como para el caso de las actualizaciones: <HTML> <HEAD> <TITLE>Borrar1.asp</TITLE> </HEAD> <BODY> <div align="center"> <h1>Borrar un registro</h1> <br> <% 'Instanciamos y abrimos nuestro objeto conexion Set Conn = Server.CreateObject("ADODB.Connection") Conn.Open "Mibase" %> <FORM METHOD="POST" ACTION="borrar2.asp"> Nombre<br> <% 'Creamos la sentencia SQL y la ejecutamos sSQL="Select nombre From clientes Order By nombre" set RS = conn.execute(sSQL) %> <select name="nombre"> <% 'Generamos el menu desplegable Do While not RS.eof%> <option><%=RS("nombre")%> <%RS.movenext Loop %> </select> <br> <INPUT TYPE="SUBMIT" value="Borrar"> </FORM> </div> </BODY> </HTML> El siguiente paso es hacer efectiva la operación a partir de la ejecución de la sentencia SQL que construimos a partir de los datos del formulario: <HTML> DGH Informática y Logística - 25 - Manual de ASP <HEAD> <TITLE>Borrar2.asp</TITLE> </HEAD> <BODY> <% 'Recogemos los valores del formulario nombre=Request.Form("nombre") 'Instanciamos y abrimos nuestro objeto conexion Set Conn = Server.CreateObject("ADODB.Connection") Conn.Open "Mibase" 'Ahora creamos la sentencia SQL sSQL="Delete From Clientes Where nombre='" & nombre & "'" 'Ejecutamos la orden set RS = Conn.Execute(sSQL) %> <h1><div align="center">Registro Borrado</div></h1> <div align="center"><a href="lectura.asp">Visualizar el contenido de la base</a></div> <% 'Cerramos el sistema de conexion Conn.Close %> </BODY> </HTML> DGH Informática y Logística - 26 - Manual de ASP REDIRIGIR AL NAVEGADOR A UNA URL CON ASP AL DETALLE MÉTODO REDIRECT Es un método del objeto response y sirve para mandar al navegador a una página que debe indicarse como parámetro. Un ejemplo de utilización sería: response.redirect "tu_pagina.html" Esto haría que nuestro navegador se situara en la página tu_pagina.html. El redirect se realiza enviando en las cabeceras del HTTP la orden de redirección. El caso es que no se puede enviar nada en las cabeceras del HTTP si ya se ha empezado a escribir texto de la página web, aunque sea un simple espacio. Por tanto, este código es incorrecto: <head> <title>Hola</title> </head> <% response.redirect "xxx.asp" %> Es incorrecto porque antes de hacer el redirect se ha escrito dentro de la página web, en este caso es información de cabecera, pero esta cabecera del documento HTML no es la mencionada cabecera del HTTP, que la mandan los servidores internamente sin que el programador participe activamente, salvo para introducir información como un redirect o un refresh a partir de funciones ASP. ALMACENAMIENTO EN BUFFER DE LA PÁGINA En instalaciones de ASP a partir de la 3.0 se utiliza un buffer de almacenamiento de la página que tiene como misión ir recogiendo el código HTML resultante de la ejecución de la página ASP, antes de mandarlo al cliente. El buffer se va llenando y cuando termina de ejecutarse la página se manda definitivamente por Internet hasta el ordenador del usuario. La utilización del buffer en ASP 3.0 (IIS 5.0) se encuentra predeterminada, mientras que en otras versiones de ASP, como la del Personal Web Server (PWS), está predeterminado para no utilizarse. Según se apunta entonces, en ASP 2.0 y anteriores se va enviando la página al cliente a medida que se va ejecutando y en ASP 3.0 hasta que no se termina de ejecutar entera, la página no se envía al cliente. Así pues, el código anterior, donde se escribía en la página antes de ejecutar un redirect, aunque está mal diseñado en cualquier caso, puede dar error o puede no dar ningún error. Todo depende de si se había o no enviado texto al cliente previamente a la realización del redirect. Todo esto tiene mucho que ver con el buffer, pues, si se está utilizando, no se envía nada al cliente y el redirect se realiza sin haber enviado texto, aunque sí se haya escrito en la página. Si no se utiliza el buffer el texto colocado antes del redirect sí se hubiese enviado al cliente y al ejecutar el redirect aparecería el error que nos comentaba nuestro lector. Utilización o no del buffer Para indicar que se desea utilizar el buffer hay que escribir esta sentencia al principio del código ASP. response.buffer = true Si se coloca en ASP 3.0 no sirve para nada, porque esa opción ya estaba predeterminada. Pero, en cualquier caso, no molesta y nos aseguramos que se utilizará el buffer si las páginas se trasladan a un servidor con ASP 2.0. Si deseamos hacer un redirect después de haber escrito texto en el buffer, lo correcto sería ejecutar estas dos sentencias juntas: response.clear response.redirect "http://www.loquesea.com" La primera línea indica que se debe vaciar el buffer, con lo que se elimina lo que se haya escrito en la página, y la segunda indica que se haga la redirección. Insisto, esto sólo es posible si se está utilizando el buffer. DGH Informática y Logística - 27 - Manual de ASP DGH Informática y Logística - 28 - Manual de ASP COMPONENTE ADROTATOR El componente ADRotator automatiza la rotación de imágenes de anuncio en una página Web. Cada vez que un cliente abre o recarga la página este componente presenta una nueva imagen según las definiciones especificadas en un archivo. Archivos necesarios Archivo Rotator Schedule: Es un archivo de texto que contiene la agenda de presentación de los anuncios. Archivo de redirección: Es un archivo .asp que implementa la redirección a la URL anunciante. Creación del objeto AdRotator <% Set Rotacion=Server.CreateObject("MSWC.AdRotator") %> Propiedades Border Permite especificar si los anuncios se presentan enmarcados. <% objeto.border=tamaño %> Clickable Permite especificar si los anuncios se presentan como hipervinculos. <% objeto.clickable= True o False %> TargetFrame Permite especificar el marco de destino del hipervinculo. <% objeto.TargetFrame= nombre del marco destino %> Metodos GetAdvertisement Recupera el siguiente anuncio del fichero Schedule. Objeto.GetAdvertisement (url del fichero Shedule) Estructura del fichero Schedule El fichero Schedule esta dividido en 2 secciones separadas por un asterisco "*". La primera sección es la especifica los parámetros comunes para todas las imágenes que se muestren; la segunda los ficheros, localizaciones y parametros propios de cada una de las imagenes. Primera sección: REDIRECT Especifica la url que se encargara de hacer la redirección, generalmente una página .asp. WIDTH Ancho en píxel del anuncio HEIGHT Alto en píxel del anuncio BORDER Ancho en píxel del borde del anuncio DGH Informática y Logística - 29 - Manual de ASP Segunda sección: Url de la imagen a mostrar Url de la pagina a redireccionar Texto alternativo de la imagen Ponderación de apariciones del anuncio con respecto del total Ejemplo: REDIRECT /util/redirect.asp WIDTH 300 HEIGHT 50 BORDER 2 * /imagenes/logo1.gif http://www.transcontinental.com El viaje de tus sueños 20 /imagenes/logo5.jpg http://www.pastelito.fr Dulces de calidad 30 Ejemplo de fichero de redirección <% response.redirect (request.querystring("url")) %> Ejemplo de una página completa <html> <head><title>Uso de AdRotator</title></head> <body><h2>Uso de AdRotator</h2> <% Set Rotacion=Server.CreateObject("MSWC.AdRotator") %> <=% Rotacion.GetAdvertisement("adrot.txt") %> </body> </html> DGH Informática y Logística - 30 - Manual de ASP COMPONENTE FILESYSTEMOBJECT El componente FSO nos permite abrir y crear ficheros de texto en el servidor. Este componente consta de 22 métodos, de los cuales podemos seleccionar 2 que son los que nos van a permitir leer o escribir en archivos de texto existentes en el servidor o crear dichos archivos. Para crear un objeto FSO la sintaxis es la misma que para cualquier otro componente ActiveX: <% Set MiFSO=Server.CreateObject("Scripting.FileSystemObject") %> Cuando abrimos o creamos un fichero de texto mediante FSO este nos devuelve una instancia del objeto TextStream que es la que representa el archivo físico y con la cual trabajaremos. Metodos CreateTextFile Crea un archivo físico y devuelve la instancia de TextStream con la cual trabajaremos. <% Set MiFichero=MiFSO.CreateTextFile("Nombre Fichero",Sobreescribir") %> Nombre Fichero Sobreescribir Nombre del fichero a crear. Admite los valores TRUE o FALSE, si el fichero ya existe y el valor dado es TRUE se crea de nuevo, si no , devuelve un error. OpenTextFile Abre un archivo físico y devuelve la instancia de TextStream con la cual trabajaremos. <% Set MiFichero=MiFSO.OpenTextFile("Nombre Fichero",modo,crear") %> Nombre Fichero Nombre del fichero a abrir. Modo Indica si queremos abrir el fichero para lectura (1) , para escritura (2) o para escribir nuevos registros al final del fichero(8) Crear Admite los valores TRUE o FALSE, si el fichero no existe y el valor dado es TRUE se crea. Ejemplo: Apertura de fichero para lectura: <% Set MiFichero=MiFSO.OpenTextFile("c:\Fichero_nuevo.txt",1,true") %> OBJETO TEXTSTREAM El objeto TextStream nos sirve para manejar ficheros de texto en el servidor. La creación de este objeto se realiza a partir de un componente FileSystemObject y gracias a alguno de sus métodos. Una vez creado, disponemos de un objeto TextStream que representa un archivo físico abierto, ya sea para lectura o escritura. Este objeto dispone de 9 métodos: Metodos Close Cierra el archivo. <% MiFichero.close%> Re a d Lee y devuelve un numero especifico de caracteres. <% MiFichero.read(numero de caracteres) %> ReadAll Lee y devuelve un archivo completo. <% MiFichero.ReadAll %> DGH Informática y Logística - 31 - Manual de ASP ReadLine Lee y devuelve una línea completa de un archivo de texto. <% MiFichero.ReadLine%> Skip Salta un numero determinado de caracteres al leer un archivo. <% MiFichero.Skip(numero de caracteres) %> SkipLine Salta una línea al leer un archivo. <% MiFichero.SkipLine %> Write Escribe una cadena de caracteres en un archivo. <% MiFichero.Write("texto_entre_comillas") %> WriteLine Escribe una cadena de caracteres en un archivo añadiendo al final un carácter de fin de linea. <% MiFichero.WriteLine("texto_entre_comillas") %> WriteBlankLines Escribe un numero especifico de caracteres de nueva línea. <% MiFichero.WriteBlankLines(numero_de_lineas) %> Ejemplo de escritura en un archivo <HTML> <HEAD><TITLE>Ejemplo de FSO y TextStream</TITLE></HEAD> <BODY> <% Set Mfso=Server.CreateObject("Scripting.FileSystemObject") Set MArchivo=Mfso.OpenTextFile("c:\fecha.txt",2,true) MArchivo.writeline "Hola Mundo, hoy es:" MArchivo.write date() MArchivo.close %> Creado archivo en C:\fecha.txt con la fecha de hoy </BODY> </HTML> DGH Informática y Logística - 32 - Manual de ASP OBJETO FOLDER EN ASP En el esquema de funcionamiento del File System Object (FSO) llegamos al objeto Folder, que sirve para trabajar con carpetas o directorios y a partir del cual podemos acceder al contenido de las unidades. Propiedades de Folder Attributes Indica los atributos de la carpeta. Devuelve un número de donde se pueden calcular los atributos a partir de la descomposición en potencias de 2. El valor 0 es para un archivo normal. El valor 1 (2 elevado a 0) es para archivos de solo lectura. El valor 2 (2 elevado a 1) es para archivos ocultos. 4 para sistema, 8 para volumen, 16 indica directorio, 32 archivo, 64 alias, 128 comprimido. Da t e Cr e a t e d Indica la fecha y hora de la creación de la carpeta. DateLastAccessed Día y hora del último acceso al directorio. DateLastModified El día y la hora de la última modificación de la carpeta. Drive Indica la unidad, en este caso la letra, donde reside la carpeta. Files Colección de objetos archivo (File, que veremos más adelante) que residen en esa carpeta. IsRootFolder Devuelve un boleano que indica si es o no el directorio raiz. Name Indica el nombre de una carpeta. También se puede fijar a través de esta propiedad. ParentFolder Es una referencia al objeto Dolder (directorio) padre. Pa th Indica el camino absoluto para llegar a la carpeta. ShortName Es el nombre corto de la carpeta, tal como se nombraría en MS-DOS. ShortPath Es la ruta, a base de nombres cortos. Size Tamaño de esa carpeta, contando tanto sus ficheros como los subdirectorios que contenga. SubFolders Contiene un array o colección con todos los objetos Folder (carpetas) que contiene la carpeta. DGH Informática y Logística - 33 - Manual de ASP Type Devuelve una descripción del tipo de carpeta. Métodos de Folder Veamos ahora la lista de los métodos disponibles para el objeto Folder de ASP. Copy (destino, sobrescribe) Copia la carpeta y todo su contenido a la carpeta destino. Sobrescribe sirve para indicar si se desea reemplazar los archivos o no. Delete (protegido) Borra la carpeta y todo su contenido. Si el parámetro opcional protegido es true se borra aunque esté protegida contra escritura. Move (destino) Mueve la carpeta con todo su contenido a la carpeta indicada como destino. CreateTextFile (nombre, sobrescribe, unicode) Crea un nuevo archivo en la carpeta con el nombre indicado como parámetro. Si sobrescribe es true se crea reemplazando uno que pudiera existir. Si unicode es true lo crea con juego de caracteres unicode. Devuelve el objeto TextStream de ese fichero de texto, con el que podríamos escribir en el archivo. LISTAR LOS SUBDIRECTORIOS DE UN DIRECTORIO Vamos a hacer un ejemplo de acceso al directorio raíz de nuestro disco duro para listar cada una de las carpetas que contiene y alguna de sus propiedades. <% ' Conecto con el sistema de archivos set FSO = server.createObject("Scripting.FileSystemObject") ' creo el objeto disco C: set discoC = FSO.GetDrive("c") 'Tomo el directorio raiz set raiz = discoC.rootFolder 'extraigo la coleccion de carpetas set coleccionCarpetas = raiz.subFolders ' Para cada carpeta imprimo su nombre y su camino completo desde la raiz for each carpeta in coleccionCarpetas response.write "<b>Carpeta " & carpeta.name & "</b>:<br>" response.write "Path: " & carpeta.path response.write ", Nombre corto: " & carpeta.ShortName response.write ", Atributos: " & carpeta.Attributes response.write "<p>" next %> El ejemplo se realiza accediendo a través del método GetDrive() del FSO, para obtener la unidad C. Luego, de la unidad obtenida se extrae el directorio raíz, a través de la propiedad RootFolder del objeto Drive. RootFolder es ya un objeto Folder y como tal tiene una colección de subcarpetas en su propiedad SubFolders. A la colección de subcarpetas de nuestro directorio raíz se le hace un recorrido con un bucle FOR EACH. Para cada carpeta se escribe su nombre, seguido de la ruta completa hasta la carpeta, el nombre corto que tendría en un sistema MS-DOS y sus atributos. La numeración de los atributos es a base de potencias de dos, así, el atributo 17 quiere decir que tiene los atributos 16 y 1 (2 elevado a 4 y 2 elevado a 0). En castellano: un directorio de solo lectura. En este ejemplo ya se empieza a ver la navegación por el sistema de ficheros, aunque sólo nos hayamos quedado a nivel de carpetas. El esquema es el comentado anteriormente: DGH Informática y Logística - 34 - Manual de ASP FSO > GetDrive() (para obtener una unidad) > RootFolder (para obtener la carpeta raíz de una unidad > Subfolders (para obtener la lista de subcarpetas del directorio, en este caso el raíz). NAVEGAR POR LA ESTRUCTURA DE DIRECTORIOS EN ASP Vamos a ver un nuevo ejemplo de trabajo con el sistema de archivos, en concreto con el objeto Folder (carpeta). Se trata de una página que nos muestra todos los directorios de nuestro disco principal (C:) y nos permita seleccionar cualquier carpeta para explorar también todos sus subcarpetas. En cada página que muestra una carpeta se puede volver al directorio padre (excepto en la raíz, que no tiene padre) y entrar en una subcarpeta. Este script, si no recibe ninguna carpeta por parámetro en el formulario, muestra el contenido de la carpeta padre. Al pulsar sobre una carpeta se envía por formulario la ruta del directorio al que se desea acceder y entonces el script, como sí ha recibido una carpeta por formulario mostrará un botón para volver a la carpeta padre y una serie de botones para meterse en un subdirectorio de la carpeta que se visualiza. El código es el siguiente: <form action=navegardirectorios.asp method=post> <% 'Conecto con el sistema de archivos set FSO = server.createObject("Scripting.FileSystemObject") dim carpeta 'Compruebo si recibo una carpeta desde el formulario if (request.form="") then ' Si no recibo carpeta, tomo la raiz ' Creo el objeto disco C: set discoC = FSO.GetDrive("c") ' Tomo el directorio raiz set carpeta = discoC.rootFolder ' Indico en la carpeta que estoy response.write "Accediendo a la Raiz<p>" else ' Si recibo carpeta, la extraigo strCarpeta = request.form("carpeta") set carpeta = FSO.getFolder(strCarpeta) ' Indico en la carpeta que estoy response.write "Accediendo a la carpeta: " & strCarpeta & "<p>" ' Si no es la carpeta raiz, coloco el enlace para ir al padre if (not carpeta.isRootFolder) then 'coloco un enlace para ir a la carpeta padre carpeta_padre = carpeta.parentFolder.path response.write "Volver a: <input type=submit name=carpeta value='" & carpeta_padre & "'><p>" end if end if ' Extraigo la colección de carpetas set coleccionCarpetas = carpeta.subFolders ' Para cada carpeta coloco un botón para ir a ella. for each carpeta in coleccionCarpetas response.write "<input type=submit name=carpeta value='" & carpeta.path & "'><br>" next %> </form> El primer enunciado IF comprueba si se está recibiendo datos por formulario o no. Si no se reciben datos se crea un objeto Folder que llamamos carpeta, que corresponde con la el directorio raíz (propiedad DGH Informática y Logística - 35 - Manual de ASP rootFolder de la unidad). Si se estaban recibiendo datos del formulario se crea el objeto Folder a partir del valor de la variable carpeta, recibida por formulario, mediante el método GetFolder(). Nota: El método GetFolder(), y otros de los relacionados con el sistema de archivos, tiene un problema con algunos antivirus, pues es considerado como susceptible de pertenecer a un script malicioso. Así pues, si utilizamos un antivirus, se nos puede quedar parada la página que utilice ese método, sin originar respuesta alguna, ni siquiera de error. La solución pasa por detener la función de bloqueo de scripts del antivirus. En el caso de recibir datos por el formulario se entiende que se está recibiendo un directorio del sistema y para que se pueda volver al directorio padre se pone un botón de formulario. Puede haber un problema si el directorio que se ha recibido es el raíz, pues este no tiene directorio padre y fallaría el script, por eso está el segundo IF, que comprueba que no sea el directorio raíz antes de poner el botón al padre. Una vez ya se ha creado el objeto carpeta, por cualquier rama de las dos que tiene el primer IF, podemos hacer un recorrido a su colección de subFolders (subdirectorios), colocando un botón para cada uno de los subdirectorios, que al pulsarse se enviará su valor a la página para mostrar dicho subdirectorio. Fijémonos que todos los botones son de tipo submit. Todos están nombrados como name="carpeta" y eso sirve para que al pulsar cualquier botón de submit se envíe en una variable de formulario (con el nombre "carpeta") el value asociado al botón de submit que se ha pulsado. DGH Informática y Logística - 36 - Manual de ASP BASES DE DATOS EN LA WEB INTRODUCCIÓN El sistema de acceso a bases datos a través de la web utilizando la tecnología Microsoft, se denomina ADO (ActiveX Data Objects). Aquí se expone una introducción comprensiva en castellano. Para ver una completa referencia acerca de todo el sistema de bases de datos de Microsoft, consulte en www.microsoft.com/data. La referencia completa de métodos y propiedades de los objetos está también en la biblioteca online de MSDN (msdn.microsoft.com). Ahí verá múltiples ejemplos en los que comprobará la flexibilidad del sistema ADO (al mismo resultado se puede llegar por vías distintas). Por motivos pedagógicos, aquí se expone una utilización más rígida. TERMINOLOGÍA ADO: ActiveX Data Objects. Es una familia de objetos componentes dedicados a facilitar el acceso a bases de datos. El ProgID de cada uno de ellos se forma combinando ADODB. con el nombre del objeto (por ejemplo ADODB.Recordset, ADODB.Connection, ADODB.Command, etc). Por tanto, en VBScript los objetos se crean con sentencias tipo Set mirst = Server.CreateObject("ADODB.Recordset"), etc. LOS OBJETOS COMPONENTES DE ADO Todo el sistema ADO se basa en una serie de objetos cuyas propiedades y métodos hay que utilizar. Estos objetos están registrados en el sistema, sin embargo no están predefinidos. Es decir, hay que crearlos utilizando Server.CreateObject. Como valores de muchas de las propiedades de los objetos ADO se utilizan constantes, como adOpenForwardOnly, adOpenKeySet, etc. Todas estas constantes empiezan por ad y están definidas en un archivo llamado adovbs.inc para Visual Basic script y adojavas.inc para Javascript. Estos archivos los podrá encontrar en su instalación local de ADO. Para incluirlos en las páginas ASP es necesario utilizar un código de este tipo al comienzo de cada página ASP que use las constantes: <!--#INCLUDE FILE="adovbs.inc"--> Para que esta inclusión funcione el archivo adovbs.inc debe estar en el mismo directorio que la página ASP que lo incluye. CONNECTION Representa una conexión a una base de datos. Este es el primer objeto que debemos crear para poder conectar con la base de datos. Tanto el objeto ADO que nos permite acceder a los datos (Recordset) como el que nos permite realizar consultas (Command) disponen de una propiedad llamada ActiveConnection que es una referencia al objeto connection que enlaza con la base de datos a la que queremos atacar. De ahí que el primer paso sea crear la conexión. Establecer conexión: <%Set conexión=Server.CreateObject(“ADODB.Connection”)%> Una vez establecida la instancia del objeto pasamos a configurarlo mediante sus disntintas propiedades y métodos. Propiedades y métodos más relevantes ConnectionString Es una cadena de caracteres con la información necesaria para establecer una conexión con la fuente de datos. Por tanto, es la propiedad básica de este objeto. Aunque hay hasta 7 argumentos distintos que se pueden suministrar en esta cadena, los básicos son el DSN que identifica al archivo de base de datos y el login y password si existen. Los argumentos se separan con punto y coma. Ejemplo: <%conexión.ConnectionString="DSN=midsn; UID=milogin; PWD=micontraseña"%> Los valores que podemos asignar son: Data Source: DSN=Nombre ODBC de la Base de Datos Usuario: User=Nombre de Usuario DGH Informática y Logística - 37 - Manual de ASP Password: Password=Password del usuario para la base de datos Ejemplo: <% conexion.ConnectionString="DSN=MIOdbc;User=pepe;Password=1234" %> Mode Especifica los permisos de la conexión. Algunos de los valores mas habituales que podemos asignar son: 1 Establece permiso solo de Lectura 2 Establece permiso solo de Escritura 3 Establece permiso de Lectura/Escritura Ejemplo: <% conexion.Mode=3 %> BeginTrans Abre una transacción; todas las operaciones que realicemos a partir de ese momento no serán efectivas hasta que no cerremos la transacción. Ejemplo: <% conexion.BeginTrans %> CommitTrans Cierra una transacción haciendo efectivos los cambios efectuados dentro de ella. Ejemplo: <% conexion.CommitBeginTrans %> RollBackTrans Desace todos los cambios efectuados en la base de datos desde el inicio de la transacción. Ejemplo: <% conexion.RollBackTrans %> Execute Ejecuta una sentencia SQL contra la base de datos. Ejemplo: <% Set resultado=conexion.execute (Select * from amigos) %> Open Abre la conexión con la base de datos. Si antes hemos asignado la propiedad ConnectionString, este método no necesita parámetros. Open Sql,conexión Ejemplo: Set Rs=createobject(“ADODB.RecordSet”) Rs.CursorType=1 Rs.LockType=3 SqlTxt=”Select * from libros” Rs.open SqlTxt, “DSN=Biblioteca” Close Cierra la conexión con la base de datos. Ejemplo de uso <% Set miconexion = Server.CreateObject("ADODB.Connection") miconexion.ConnectionString = "DSN=midsn" miconexion.Open ' ....... DGH Informática y Logística - 38 - Manual de ASP '........ miconexion.Close %> ERROR El objeto Error contiene la colección Errors, que es la encargada de almacenar los errores que se pudieran producir durante la ejecución de operaciones contra Bases de Datos. Propiedades Description Descripción del error. Number El numero de error. SQLState Código de error SQL. Metodos Clear Elimina los datos del objeto Error. Ejemplo: Examinando los posibles datos de la colección Errors ....... ....... Miconexion.open If Miconexion.Errors.Count > 0 then For each error in Miconexion.errors then Response.write Error.Number & " = "& Error.Description next End if Nota: Count es una propiedad de la colección Errors. RECORDSET Este es el objeto ADO más importante ya que es con el que accederemos directamente a los datos de las tablas, tanto para leerlos como para modificarlos. Un objeto Recordset representa una tabla, que puede ser una tabla física de la base de datos o bien una obtenida mediante una operación como un filtrado o sentencia SQL. En cualquier caso, el objeto representa a la tabla con todos sus registros, aunque sólo uno de ellos es el activo. El registro activo es en el que podemos leer o modificar los valores de los campos. También se le llama cursor. PROPIEDADES Y MÉTODOS MÁS IMPORTANTES Para una mejor compresión y puesto que son numerosos, los hemos dividido por categorías de utilidad. Propiedades que hacen referencia al origen de los datos: Estas dos propiedades deben ser asignadas a todo Recordset, pues le dicen la base de datos y la tabla de la que obtener sus datos. ActiveConnection Como se ha comentado antes a esta propiedad se le debe asignar un objeto connection que se haya creado previamente. Indicará al Recordset la base de datos en la que buscar su tabla. Source DGH Informática y Logística - 39 - Manual de ASP Indica al objeto Recordset la tabla a la que representará. A la propiedad Source se le asigna normalmente una cadena de caracteres con el nombre de la tabla. Sin embargo, también es posible asignarle una sentencia SQL y entonces el objeto Recordset referenciará al resultado de aplicar dicha sentencia. LockType Indica el tipo de bloqueo que se realiza sobre la base de datos. Por defecto toma el valor adLockReadOnly que como su nombre indica sólo sirve para leer datos. Si deseamos editar o añadir registros, tendremos que cambiar esta propiedad por otro valor. El más usado es adLockOptimistic que permite editar la base de datos o añadir registros realizando un bloqueo optimista (sólo cuando sea estrictamente necesario). CursorType El tipo de cursor que se utiliza para recorrer los registros de un recordset. Por defecto toma el valor adOpenForwardOnly que como su nombre indica sólo permite moverse hacia adelante. Por ello si queremos utilizar libremente todos los métodos de movimiento de un recordset (MoveFirst, MoveTo, MoveNext, MovePrevious, etc) tendremos que cambiar el cursor por uno más potente. Esto puede hacerse asignando a esta propiedad el valor adOpenKeyset (ó adOpenDynamic, adOpenStatic). Ejemplo Aquí creamos en primer lugar un objeto Connection y luego un Recordset al que se asigna dicho objeto. Este ejemplo es una especie de esqueleto para los demás que sigan: Se supone que debe hacerse algo parecido a esto para abrir el Recordset. Es decir, en los restantes ejemplos escribimos sólo el código que iría en el lugar de los puntos suspensivos de este script (NOTA: Recuerde que si hay que añadir registros es necesario cambiar el LockType antes de inicializar el recordset). <% Set miconexion = Server.CreateObject("ADODB.Connection") miconexion.ConnectionString = "DSN=midsn" miconexion.Open Set mirecordset = Server.CreateObject("ADODB.Recordset") mirecordset.ActiveConnection = miconexion mirecordset.Source = "Clientes" mirecordset.Open ........ ' Operaciones con los datos ........' de la tabla Clientes. mirecordset.Close miconexion.Close %> Propiedades que hacen referencia al número de registros: PageSize Establece el número de registros por página del recordset. AbsolutePage Mueve el cursor al primer registro de dicha página (es necesario definir anteriormente el PageSize). PageCount Contiene el número de páginas del RecordSet, tomando como base PageSize. AbsolutePosition Mueve el cursor al número de registro especificado. RecordCount Número de registros de la tabla a la que representa el objeto recordset. Ejemplo: DGH Informática y Logística - 40 - Manual de ASP <h3> Tenemos <%= rstClientes.RecordCount%> clientes registrados en nuestra base de datos </h3> EOF Acrónimo de End Of File. Vale TRUE si estamos en el último registro y FALSE si no. Se usa mucho como condición en bucles while, los cuales se ejecutan hasta llegar al último registro. B OF Acrónimo de Begin Of File. Vale TRUE si estamos en el primer registro y FALSE si no. Métodos para mover el cursor (registro activo): Estos métodos pueden funcionar todos o no dependiendo del tipo de cursor creado. El tipo de cursor se asigna en la propiedad CursorType. Por ejemplo, para asignar un cursor adOpenKeySet que permita moverse hacia adelante o hacia atrás: <% Set miconexion = Server.CreateObject("ADODB.Connection") miconexion.ConnectionString = "DSN=midsn" miconexion.Open Set mirecordset = Server.CreateObject("ADODB.Recordset") mirecordset.ActiveConnection = miconexion mirecordset.Source = "Clientes" mirecordset.CursorType = adOpenKeySet mirecordset.Open ........ ' Operaciones con los datos ........' de la tabla Clientes. mirecordset.Close miconexion.Close %> Nótese que la asignación de propiedades al recordset debe hacerse antes de invocar el método open que es el que lo inicializa con registros. MoveFirst Mueve el cursor al primer registro de la tabla MoveLast Mueve el cursor al último registro de la tabla MoveNext Mueve el cursor al siguiente registro. MovePrevious Mueve el cursor al registro anterior. Ejemplo de un bucle que recorre todos los registros de una tabla <% mirecordset.MoveFirst do while not mirecordset.EOF ..... ' Tratamiento ..... ' de datos mirecordset.MoveNext loop %> Lectura y modificación de los campos del registro activo DGH Informática y Logística - 41 - Manual de ASP La sintaxis para acceder a los datos de un campo del registro activo de un recordset es: mirecordset("Domicilio") Esto se usa tanto para leer como asignar valores. En nuestro ejemplo, el objeto mirecordset representa a una tabla uno de cuyos campos tiene el nombre "Domicilio". Así, con la expresión dom = mirecordset("Domicilio") Leemos el valor del campo domicilio del registro activo y se lo asignamos a la variable dom. Con la expresión mirecordset("Domicilio") = "C/ Bretón de los Herreros 19, 1º M" mirecordset.Update asignamos un valor al campo Domicilio del registro activo. Tras la edición del registro, es necesario llamar al método Update. El motivo es que los cambios en el registro activo se realizan sobre un buffer (espacio de almacenamiento intermedio) y no sobre el registro propiamente dicho. Ejemplo: El recordset rstClientes representa a nuestra tabla de clientes que, entre otros, tiene los campos Provincia e IVA . El siguiente bucle recorre todos los clientes, comprueba su provincia y le asigna el IVA correspondiente: 0 para Canarias y 16 para los demás <% rstClientes.MoveFirst do while not rstClientes.EOF if rstClientes("Provincia") = "Las Palmas" or rstClientes("Provincia") = "Tenerife" Then rstClientes("IVA") = 0 else rstClientes("IVA") = 16 end if rstClientes.Update rstClientes.MoveNext loop %> Métodos para agregar o eliminar registros de la tabla Delete Eliminar el registro activo es muy fácil. Basta con invocar este método. Por ejemplo, este bucle elimina todos los clientes morosos de nuestra base de datos: <% rstClientes.MoveFirst do while not rstClientes.EOF if rstClientes("Deuda") > 0 Then rstClientes.Delete end if rstClientes.MoveNext loop %> AddNew y Update Crear un nuevo registro involucra dos métodos: Primero AddNew crea un nuevo registro en blanco. Después asignamos valores a los distintos campos del registro. Por último invocamos el método Update para que se haga efectiva la incorporación del nuevo registro con los valores asignados. En este ejemplo incorporamos un nuevo cliente a nuestra base de datos <% rstClientes.AddNew rstClientes("Nombre") = "Pepe Gotera" rstClientes("Direccion") = "Rue del Percebe, 13" rstClientes("Localidad") = "Sildavia" rstClientes("Profesion") = "Chapuzas a domicilio" rsClientes.Update %> DGH Informática y Logística - 42 - Manual de ASP Recuerde que para que esto funcione hay que asignar un tipo de bloqueo que permita la edición de la base de datos. Esto se hace asignando a la propiedad LockType del recordset uno de estos valores: adLockOptimistic, adLockPessimistic o adLockBatchOptimistic. COMMAND Este objeto es la representación de un comando que se envía a la base de datos. Este comando puede ser una de estas 3 cosas: Llamada a un procedimiento guardado en la base de datos. El texto de una sentencia SQL. El nombre de una tabla. ActiveConnection Es una referencia al objeto connection que enlaza con la base de datos. es imprescindible asignar esta propiedad antes de invocar el método command.execute para ejecutar el comando. CommandText Este es el texto del comando. Si se trata de una consulta SQL (lo habitual), esta propiedad es simplemente una cadena con el texto de la consulta. Execute El método que ejecuta la consulta. El resultado de la ejecución del comando normalmente será un recordset. En el ejemplo, obtenemos un recorset con un filtrado de la tabla Clientes en el que se toma sólo aquellos clientes cuya provincia es Navarra. <% Set miconexion = Server.CreateObject("ADODB.Connection") miconexion.ConnectionString = "DSN=midsn" miconexion.Open Set SqlCommand = Server.CreateObject("ADODB.Command") SqlCommand.ActiveConnection = miconexion SqlCommand.CommandText = "SELECT * FROM Clientes WHERE Provincia = 'Navarra'" Set rstNavarros = SqlCommand.execute ' ....... '........ miconexion.Close %> EL ARCHIVO GLOBAL.ASA El archivo Global.asa es un fichero de texto situado en el directorio raiz de nuestro servidor Web, es decir, en el directorio de comienzo de nuestras páginas. Es un archivo de comandos que nos permite la automatización de los cuatro eventos básicos de nuestro servidor. La estructura es siempre la misma: <SCRIPT LANGUAGE="VBScript" RUNAT="Server"> Sub Application_OnStart ........ End Sub Sub Application_OnEnd ........ End Sub Sub Session_OnStart ........ End Sub Sub Session_OnEnd DGH Informática y Logística - 43 - Manual de ASP ........ End Sub </SCRIPT> Eventos Application_OnStart El evento Application_OnStart se ejecuta antes de que se cree la primera nueva sesión; es decir justo cuando el primer cliente pide una pagina de nuestro servidor. Application_OnEnd El evento Application_OnEnd se ejecuta cuando la aplicación termina. Session_OnStart El evento Session_OnStart se ejecuta cuando el servidor crea una nueva sesión; esta secuencia de comandos es ejecutada antes de enviar la página solicitada al cliente. Session_OnEnd El evento Session_OnEnd se ejecuta cuando se abandona o se supera el tiempo de espera de una sesión. Ejemplo de Global.asa: <SCRIPT LANGUAGE="VBScript" RUNAT="Server"> Sub Application_OnStart dim mitabla() redim mitabla(9) application("tabla")=mitabla End Sub Sub Application_OnEnd End Sub Sub Session_OnStart paginaInicio="/ appl/index.html" response.redirect paginaInicio End Sub Sub Session_OnEnd End Sub </SCRIPT> DGH Informática y Logística - 44 - Manual de ASP SELECT - SQL (COMANDO) Recupera datos de una o más tablas. SELECT [ALL | DISTINCT] [TOP nExpr [PERCENT]] [Alias.] Select_Item [[AS] Column_Name] [, [Alias.] Select_Item [[AS] Column_Name] ...] FROM [FORCE][DatabaseName!]Table [[AS] Local_Alias] [[INNER | LEFT [OUTER] | RIGHT [OUTER] | FULL [OUTER] JOIN DatabaseName!] Table [[AS] Local_Alias] [ON JoinCondition …] [[INTO Destination] | [TO FILE FileName [ADDITIVE] | TO PRINTER [PROMPT] | TO SCREEN]] [PREFERENCE PreferenceName] [NOCONSOLE] [PLAIN] [NOWAIT] [WHERE JoinCondition [AND JoinCondition ...] [AND | OR FilterCondition [AND | OR FilterCondition ...]]] [GROUP BY GroupColumn [, GroupColumn ...]] [HAVING FilterCondition] [UNION [ALL] SELECTCommand] [ORDER BY Order_Item [ASC | DESC] [, Order_Item [ASC | DESC] ...]] Parámetros SELECT Especifica los campos, constantes y expresiones que se mostrarán en el resultado de la consulta. ALL De forma predeterminada, se muestran todas las filas del resultado de la consulta. DISTINCT Excluye duplicados de cualquier fila del resultado de la consulta. Nota: Puede utilizar DISTINCT únicamente una vez por cada cláusula SELECT. TOP nExpr [PERCENT] Especifica que el resultado de la consulta contenga un número determinado de filas o un porcentaje de filas en el resultado de la consulta. Es necesario incluir una cláusula ORDER BY si incluye la cláusula TOP. La cláusula ORDER BY especifica las columnas en las que la cláusula TOP determinará el número de filas que se va a incluir en el resultado de la consulta. Puede especificar desde 1 a 32.767 filas. Las filas de valores idénticos para las columnas especificadas en la cláusula ORDER BY se incluyen en el resultado de la consulta. Por lo tanto, si especifica 10 para nExpr, el resultado de la consulta podrá obtener más de 10 filas, si hay más de 10 filas con valores idénticos para las columnas especificadas en la cláusula ORDER BY. Si se incluye la palabra clave PERCENT, se redondeará al número entero más alto el número de columnas devuelto en el resultado. Los valores permitidos para nExpr cuando se incluye la palabra clave PERCENT son de 0,01 a 99,99. Alias.Select_Item Califica nombres de elementos coincidentes. Cada elemento que especifique con Select_Item genera una columna de los resultados de la consulta. Si dos o más elementos tienen el mismo nombre, incluya el alias de la tabla y un punto antes del nombre del elemento para impedir la duplicación de las columnas. Select_Item especifica un elemento que se incluirá en el resultado de la consulta. Un elemento puede ser uno de los siguientes: El nombre de un campo de una tabla de la cláusula FROM. Una constante, especificando que el mismo valor constante debe aparecer en cada fila del resultado de la consulta. Una expresión que puede ser el nombre de una función definida por el usuario (FDU). AS Column_Name Especifica el título de una columna en el resultado de la consulta. Esta opción resulta muy útil cuando Select_Item es una expresión o contiene una función de campo y desea dar un nombre significativo a la DGH Informática y Logística - 45 - Manual de ASP columna. Column_Name puede ser una expresión, pero no puede contener caracteres (por ejemplo, espacios) que no estén permitidos para nombres de campos de tablas. F RO M Indica las tablas que contienen los datos que ha obtenido la consulta. Si no hay ninguna tabla abierta, Visual FoxPro muestra el cuadro de diálogo Abrir, donde puede especificar la ubicación del archivo. Una vez abierta, la tabla permanece abierta cuando finaliza la consulta. F O RC E Especifica que las tablas se combinen en el orden de aparición en la cláusula FROM. Si se omite FORCE, Visual FoxPro intentará optimizar la consulta. Sin embargo, es posible que la consulta se ejecute más rápido si se incluye la palabra clave FORCE para desactivar la optimización de consultas de Visual FoxPro. DatabaseName! Table Especifica el nombre de una base de datos inactiva que contiene la tabla. Es necesario incluir el nombre de la base de datos que contiene la tabla en caso de que no sea la base de datos activa. Incluya el delimitador signo de exclamación (!) después del nombre de la base de datos y antes del nombre de la tabla. [AS] Local_Alias Especifica un nombre temporal para la tabla indicada en Table. Si especifica un alias local, debe utilizar el alias local en lugar del nombre de la tabla en toda la instrucción SELECT. INNER JOIN Especifica que el resultado de la consulta contenga sólo filas en una tabla con la que coincidan una o varias filas de otra tabla. LEFT [OUTER] Especifica que el resultado de la consulta contenga todas las filas de la tabla a la izquierda de la palabra clave JOIN y sólo las filas que coincidan procedentes de la tabla a la derecha de la palabra clave JOIN. La palabra clave OUTER es opcional; se puede incluir para resaltar que se ha creado una combinación externa. RIGHT [OUTER] Especifica que el resultado de la consulta contenga todas las filas de la tabla a la derecha de la palabra clave JOIN y sólo las filas que coincidan de la tabla a la izquierda de la palabra clave JOIN. La palabra clave OUTER es opcional; se puede incluir para resaltar que se ha creado una combinación externa. FULL [OUTER] Especifica que el resultado de la consulta contenga todas las filas, coincidan o no, de ambas tablas. La palabra clave OUTER es opcional; se puede incluir para resaltar que se ha creado una combinación externa. ON Join Condition Especifica las condiciones según las cuales se combinan las tablas. INTO Destination Determina donde se almacenan los resultados de la consulta. Si incluye una cláusula INTO y una cláusula TO en la misma consulta, la cláusula TO se pasará por alto. Si no incluye la cláusula INTO, los resultados de la consulta se mostrarán en la ventana Examinar. Los resultados de la consulta pueden dirigirse también a la impresora o a un archivo con la cláusula TO. Destination puede ser uno de los siguientes: DGH Informática y Logística - 46 - Manual de ASP ARRAY ArrayName Que almacena los resultados de la consulta en una matriz de variable de memoria. Si la consulta selecciona 0 registros, la matriz no se creará. CURSOR CursorName [NOFILTER | READWRITE] Que almacena los resultados de una consulta en un cursor. Si especifica el nombre de una tabla abierta, Visual FoxPro generará un mensaje de error. Después de ejecutar SELECT, el cursor temporal permanecerá abierto y estará activo, pero solamente para lectura. Cuando cierre este cursor temporal, se borrará. Los cursores pueden existir como un archivo temporal en la unidad SORTWORK. Incluya NOFILTER para crear un cursor que se pueda usar en consultas posteriores. En versiones anteriores de Visual FoxPro, era necesario incluir una expresión o una constante adicional como un filtro para crear un cursor utilizable en consultas posteriores. Por ejemplo, la adición de un valor lógico verdadero como una expresión de filtro creaba una consulta que podía utilizarse en consultas posteriores: SELECT *, .T. FROM customers INTO CURSOR myquery Si se incluye NOFILTER, es posible que disminuya el rendimiento de la consulta, puesto que se crea una tabla temporal en el disco. Cuando se cierre el cursor se eliminará del disco la tabla temporal. La cláusula READWRITE especifica que el cursor es temporal y se puede modificar. DBF | TABLE TableName[DATABASE DatabaseName [NAME LongTableName]] Almacena los resultados de una consulta en una tabla. Si especifica una tabla que ya esté abierta y SET SAFETY está en OFF, Visual FoxPro sobrescribirá la tabla sin previo aviso. Si no ha especificado ninguna extensión, Visual FoxPro asignará la extensión .DBF a la tabla. La tabla permanecerá abierta y activa después de ejecutar SELECT. Incluya DATABASE DatabaseName para especificar una base de datos a la que se agregará la tabla. Incluya NAME LongTableName para especificar un nombre largo para la tabla. Los nombres largos pueden contener un máximo de 128 caracteres y se pueden utilizar en lugar de nombres de archivo cortos en la base de datos. TO FILE FileName ADDITIVE Si incluye una cláusula TO pero no una cláusula INTO, puede dirigir el resultado de la consulta a un archivo de texto ASCII llamado FileName, a la impresora o a la ventana principal de Visual FoxPro. ADDITIVE anexa los resultados de la consulta al contenido existente del archivo de texto especificado en TO FILE FileName. TO PRINTER [PROMPT] Dirige los resultados de la consulta a una impresora. Utilice la cláusula PROMPT opcional para mostrar un cuadro de diálogo antes de que empiece la impresión. En este cuadro de diálogo puede modificar la configuración de la impresora. Las opciones de configuración de la impresora que puede ajustar dependen del controlador de impresora que tenga instalado actualmente. Coloque PROMPT justo después de TO PRINTER. TO SCREEN Dirige los resultados de la consulta a la ventana principal de Visual FoxPro o a una ventana activa definida por el usuario. PREFERENCE PreferenceName Si el resultado de una consulta se envía a una ventana Examinar, guarda los atributos y opciones de la ventana Examinar para utilizarlos después. PREFERENCE guarda los atributos, o preferencias, por tiempo indefinido en el archivo de recursos FOXUSER. Las preferencias se pueden recuperar en cualquier momento. Ejecutando SELECT con PREFERENCE PreferenceName por primera vez, se crea la preferencia. Ejecutando posteriormente SELECT con el mismo nombre de preferencia, se restaura la ventana Examinar con el mismo estado de preferencia. Cuando se cierre la ventana Examinar, se actualiza la preferencia. Si sale de una ventana Examinar presionando CTRL+Q+W, no se guardarán los cambios de la ventana Examinar en el archivo de recursos. DGH Informática y Logística - 47 - Manual de ASP NOCONSOLE Impide que el resultado de la consulta se envíe a un archivo, a la impresora o a la ventana principal de Visual FoxPro. PLAIN Impide que aparezcan los encabezados de las columnas al mostrar los resultados de la consulta. PLAIN puede utilizarse tanto si está presente una cláusula TO como si no. Si se incluye una cláusula TO, se pasará por alto PLAIN. NOWAIT Continúa la ejecución del programa después de abrir la ventana Examinar y de dirigir a ella los resultados de la consulta. El programa no esperará a que la ventana Examinar se cierre, sino que continuará con la ejecución de la línea de programa inmediatamente siguiente a la instrucción SELECT. Cuando se incluye TO SCREEN para dirigir los resultados hacia la ventana principal de Visual FoxPro o una ventana definida por el usuario, los resultados se detienen cuando la ventana principal de Visual FoxPro o la ventana definida por el usuario se llena con resultados de la consulta. Presione una tecla para ver el siguiente conjunto de resultados de la consulta. Si se incluye NOWAIT, los resultados de la consulta se desplazarán fuera de la ventana principal de Visual FoxPro o de la ventana definida por el usuario sin esperar a que se presione una tecla. NOWAIT se pasa por alto si se incluye con la cláusula INTO. WHERE Especifica que Visual FoxPro sólo debe incluir en los resultados de la consulta los registros que satisfagan los criterios especificados. JoinCondition Especifica los campos que vinculan las tablas en la cláusula FROM. Si incluye más de una tabla en una consulta, deberá especificar una condición de combinación para cada tabla después de la primera. Las condiciones de combinación múltiples deben conectarse mediante el operador AND. Cada condición de combinación tiene la forma siguiente: FieldName1 Comparison FieldName2 FieldName1 es el nombre de un campo de una tabla, FieldName2 es el nombre de un campo de otra tabla y Comparison es uno de los operadores siguientes: Operador Comparación = Igual == Exactamente igual LIKE SQL LIKE <>, !=, # Distinto de > Mayor que >= Mayor o igual que < Menor que <= Menor o igual que Cuando utiliza el operador = con cadenas, actúa de forma distinta dependiendo del ajuste de SET ANSI. Cuando SET ANSI está desactivado, Visual FoxPro trata las comparaciones de cadenas en la forma habitual en Xbase. Cuando SET ANSI está activado, Visual FoxPro sigue las normas ANSI para las comparaciones de cadenas. Vea SET ANSI y SET EXACT para obtener información adicional acerca de cómo realiza Visual FoxPro las comparaciones de cadenas. La cláusula WHERE admite el operador ESCAPE para la JoinCondition, lo que le permite realizar consultas significativas sobre datos que contengan caracteres comodín _ y % de SELECT - SQL. La cláusula ESCAPE le permite especificar que se traten los caracteres comodín de SELECT - SQL como si fueran caracteres literales. En la cláusula ESCAPE se especifica un carácter, que si se coloca inmediatamente antes del carácter comodín, indica que se tratará al carácter comodín como a un carácter literal. FilterCondition Especifica los criterios que deben satisfacer los registros para ser incluidos en los resultados de la consulta. Una consulta puede incluir tantas condiciones de filtro como desee, conectadas con el operador DGH Informática y Logística - 48 - Manual de ASP AND y OR. También puede utilizar el operador NOT para invertir el valor de una expresión lógica o utilizar EMPTY( ) para comprobar si hay campos vacíos. FilterCondition puede adoptar cualquier de las formas de los siguientes ejemplos: Ejemplo 1 En el ejemplo 1 se muestra FilterCondition como FieldName1 Comparison FieldName2 customer.cust_id = orders.cust_id Ejemplo 2 En el ejemplo 2 se muestra FilterCondition como FieldName Comparison Expression payments.amount >= 1000 Ejemplo 3 En el ejemplo 3 se muestra FilterCondition como FieldName Comparison ALL (Subquery) Cuando la condición de filtro incluye ALL, el campo debe cumplir la condición de comparación para todos los valores generados por la subconsulta antes de que se incluya el registro en el resultado de la consulta. company < ALL ; (SELECT company FROM customer WHERE country = "UK") Ejemplo 4 En el ejemplo 4 se muestra FilterCondition como FieldName Comparison ANY | SOME (Subquery) Cuando la condición de filtro incluye ANY o SOME, el campo debe cumplir la condición de comparación en al menos uno de los valores generados por la subconsulta. company < ANY ; (SELECT company FROM customer WHERE country = "UK") Ejemplo 5 En el ejemplo 5 se muestra FilterCondition como FieldName [NOT] BETWEEN Start_Range AND End_Range Este ejemplo comprueba si los valores del campo están dentro de un intervalo de valores especificado. customer.postalcode BETWEEN 90000 AND 99999 Ejemplo 6 En el ejemplo 6 se muestra FilterCondition como [NOT] EXISTS (Subquery) Este ejemplo comprueba si al menos una línea cumple los criterios de la subconsulta. Cuando la condición de filtro incluye EXISTS, la condición de filtro se evalúa como verdadero (.T.) a no ser que la subconsulta sea un conjunto vacío. EXISTS ; (SELECT * FROM orders WHERE customer.postalcode = orders.postalcode) Ejemplo 7 En el ejemplo 7 se muestra FilterCondition como FieldName [NOT] IN Value_Set Cuando una condición de filtro incluye IN, el campo debe contener uno de los valores antes de que el registro se incluya en los resultados de la consulta. customer.postalcode NOT IN ("98052","98072","98034") Ejemplo 8 En el ejemplo 8 se muestra FilterCondition como FieldName [NOT] IN (Subquery) Aquí, el campo debe contener uno de los valores devueltos por la subconsulta antes de que su registro se incluya en los resultados de la consulta. DGH Informática y Logística - 49 - Manual de ASP customer.cust_id IN ; (SELECT orders.cust_id FROM orders WHERE orders.city="Seattle") Ejemplo 9 En el ejemplo 9 se muestra FilterCondition como FieldName [NOT] LIKE cExpression customer.country NOT LIKE "UK" Esta condición de filtro busca cada uno de los campos que coinciden con cExpression. Puede utilizar el signo de porcentaje (%) y subrayado ( _ ) como parte de cExpression. El signo de porcentaje representa a cualquier secuencia de caracteres desconocidos en la cadena. El subrayado representa un solo carácter desconocido en la cadena. GROUP BY GroupColumn [, GroupColumn ...] Agrupa las filas de la consulta basándose en los valores de una o más columnas. GroupColumn puede ser el nombre de un campo normal de una tabla, o un campo que incluya una función de campo SQL o una expresión numérica que indique la posición de la columna en la tabla de resultados (la columna más a la izquierda tiene el número 1). HAVING FilterCondition Especifica una condición de filtro que los grupos deben satisfacer para quedar incluidos en el resultado de la consulta. HAVING debe utilizarse con GROUP BY. Puede incluir tantas condiciones de filtro como desee, conectadas con los operadores AND u OR. También puede utilizar NOT para invertir el valor de una expresión lógica. FilterCondition no puede contener una subconsulta. Una cláusula HAVING sin una cláusula GROUP BY actúa como una cláusula WHERE. Puede utilizar alias locales y funciones de campo en la cláusula HAVING. Utilice una cláusula WHERE para acelerar el rendimiento si la cláusula HAVING no contiene funciones de campo. No olvide que la cláusula HAVING debería de aparecer antes de una cláusula INTO porque de lo contrario se producirá un error de sintaxis. [UNION [ALL] SELECTCommand] Combina el resultado final de un SELECT con el resultado final de otro SELECT. De forma predeterminada, UNION comprueba el resultado combinado y elimina las filas duplicadas. Puede utilizar paréntesis para combinar varias cláusulas UNION. ALL impide que UNION elimine filas duplicadas de los resultados combinados. Las cláusulas UNION siguen las reglas siguientes: No puede utilizar UNION para combinar subconsultas. Los resultados de ambos SELECT deben tener el mismo número de columnas. Cada columna de resultados de la consulta de un SELECT debe tener el mismo tipo de datos y ancho que su columna correspondiente en el otro SELECT. Únicamente el SELECT final puede tener una cláusula ORDER BY, que debe referirse a las columnas de resultados por su número. Si se incluye otra cláusula ORDER BY, afectará al resultado completo. También puede utilizar la cláusula UNION para simular una combinación externa. Al combinar dos tablas en una consulta, sólo se incluirán en los resultados los registros que tengan valores coincidentes en los campos combinados. Si un registro de la tabla primaria no tiene un registro correspondiente en la tabla secundaria, no se incluirá en los resultados. Una combinación externa permite incluir todos los registros de la tabla primaria en los resultados, junto con los registros coincidentes de la tabla secundaria. Para crear una combinación externa en Visual FoxPro, debe utilizar un comando SELECT anidado, como en el siguiente ejemplo: SELECT customer.company, orders.order_id, orders.emp_id ; FROM customer, orders ; WHERE customer.cust_id = orders.cust_id ; UNION ; SELECT customer.company, 0, 0 ; FROM customer ; WHERE customer.cust_id NOT IN ; (SELECT orders.cust_id FROM orders) Nota: Asegúrese de incluir el espacio que precede a cada punto y coma. Si no lo hace así; se producirá un error. DGH Informática y Logística - 50 - Manual de ASP La sección del comando anterior a la cláusula UNION selecciona registros de las dos tablas que tengan valores coincidentes. No se incluirán las compañías de clientes que no tengan facturas asociadas. La sección del comando situada después de la cláusula UNION selecciona registros de la tabla de clientes que no tengan registros coincidentes en la tabla de pedidos. En cuanto a la segunda sección del comando, tenga en cuenta lo siguiente: Se procesará primero la instrucción SELECT escrita entre paréntesis. Esta instrucción realiza una selección de todos los números de cliente de la tabla de pedidos. La cláusula WHERE busca todos los números de cliente de la tabla de clientes que no estén en la tabla de pedidos. Como la primera sección del comando proporcionaba todas las compañías que tuvieran un número de cliente en la tabla de pedidos, ahora se incluirán en el resultado de la consulta todas las compañías de la tabla de clientes. Como las estructuras de las tablas incluidas en una cláusula UNION deben ser idénticas, hay dos marcadores en la segunda instrucción SELECT para representar los parámetros orders.order_id y orders.emp_id de la primera instrucción SELECT. Nota: Los marcadores deben tener el mismo tipo que los campos que representan. Si el campo es un tipo de datos, el marcador debe ser { / / }. Si el campo es un tipo Character, el marcador debe ser la cadena vacía (""). En determinadas circunstancias puede producirse una transformación de datos automática, como en los dos ejemplos siguientes: CREATE CURSOR table1 (field1 c(1)) CREATE CURSOR table2 (field1 c(2)) SELECT field1 FROM table1 UNION SELECT NVL(field1,' ') FROM table2 CREATE CURSOR table1 (field1 n(20,5)) CREATE CURSOR table2 (field1 i) SELECT field1 FROM table1 UNION SELECT field1 FROM table2 ORDER BY Order_Item [ASC | DESC] Ordena el resultado de la consulta basándose en los datos de una o varias columnas. Cada Order_Item debe corresponder a una columna de resultados de la consulta y puede ser uno de los siguientes: Un campo de una tabla FROM que también es un elemento de selección en la cláusula principal SELECT (no en una subconsulta). Una expresión numérica que indica la ubicación de la columna en la tabla de resultados. (La columna de la izquierda es la número 1.) ASC especifica un orden ascendente para los resultados de la consulta, de acuerdo con el elemento o los elementos de orden, y es el valor predeterminado para ORDER BY. DESC especifica un orden descendente para los resultados de la consulta. Los resultados de la consulta aparecerán desordenados si no especifica un orden con ORDER BY. OBSERVACIONES SELECT es un comando SQL incorporado en Visual FoxPro como cualquier otro comando de Visual FoxPro. Cuando utiliza SELECT para componer una consulta, Visual FoxPro interpreta la consulta y recupera los datos especificados de las tablas. Puede crear una consulta SELECT: En la ventana Comandos En un programa de Visual FoxPro (como cualquier otro comando de Visual FoxPro) En el Diseñador de consultas Cuando ejecuta SET TALK ON y ejecuta SELECT, Visual FoxPro muestra la duración de la consulta y el número de registros del resultado. _TALLY contiene el número de registros del resultado de la consulta. SELECT no respeta la condición de filtro actual especificada con SET FILTER. Nota: Una subconsulta, a la que se hace referencia en los argumentos siguientes, es un comando SELECT dentro de otro SELECT y debe incluirse entre paréntesis. Puede tener hasta dos subconsultas al mismo nivel (no anidadas) en la cláusula WHERE (consulte esta sección de los argumentos). Las subconsultas pueden contener condiciones de combinación múltiples. Cuando se obtiene el resultado de una consulta, las columnas se denominan según las siguientes reglas: Si un elemento seleccionado es un campo con un nombre único, el nombre de la columna de resultados es el nombre del campo. Si hay más de un elemento seleccionado con el mismo nombre, se anexarán un signo de subrayado y una letra al nombre de la columna. Por ejemplo, si una tabla llamada Customer tiene un campo llamado DGH Informática y Logística - 51 - Manual de ASP STREET, y una tabla llamada Employees también tiene un campo llamado STREET, las columnas de resultado se llamarán Extension_A y Extension_B (STREET_A y STREET_B). En el caso de un elemento seleccionado con un nombre de 10 caracteres, se truncará el nombre para agregar el símbolo de subrayado y la letra. Por ejemplo, DEPARTMENT se convertiría en DEPARTME_A. Si un elemento seleccionado es una expresión, su columna de resultado se llamará EXP_A. Cualquier otra expresión recibirá el nombre de EXP_B, EXP_C, y así sucesivamente. Si un elemento seleccionado contiene una función de campo como, por ejemplo, COUNT( ), la columna de resultado se llamará CNT_A. Si otro elemento seleccionado contiene SUM( ), su columna de resultado se llamará SUM_B. Funciones definidas por el usuario con SELECT Aunque la utilización de funciones definidas por el usuario en la cláusula SELECT ofrece unas ventajas evidentes, también debería tener en cuenta las siguientes limitaciones: Es posible que la velocidad de las operaciones con SELECT se vea limitada por la velocidad a la que se ejecutan las funciones definidas por el usuario. Las manipulaciones de un gran volumen que impliquen funciones definidas por el usuario se pueden realizar mejor utilizando funciones API y funciones definidas por el usuario escritas en C o en lenguaje ensamblador. No se puede suponer nada acerca de la entrada/salida (E/S) de Visual FoxPro ni del entorno de la tabla en funciones definidas por el usuario invocadas a partir de SELECT. Generalmente no se puede saber qué área de trabajo se ha seleccionado, el nombre de la tabla actual, ni los nombres de los campos que se están procesando. El valor de estas variables depende del lugar específico, en el proceso de optimización, en el que se invoque la función definida por el usuario. En funciones definidas por el usuario invocadas desde SELECT, no es seguro cambiar la E/S de Visual FoxPro ni el entorno de la tabla. En general, los resultados son impredecibles. La única forma segura de pasar valores a funciones definidas por el usuario invocadas desde SELECT es por medio de la lista de argumentos pasada a la función al invocarla. Si prueba y descubre una manipulación teóricamente prohibida que funciona correctamente en una versión determinada de FoxPro, eso no significa que también funcione en versiones posteriores. Fuera de estas limitaciones, las funciones definidas por el usuario son aceptables en la cláusula SELECT. Sin embargo, recuerde que la utilización de SELECT puede reducir el rendimiento. Las siguientes funciones de campo están disponibles para ser utilizadas con un elemento seleccionado que sea un campo o una expresión que incluya a un campo: AVG(Select_Item), que promedia una columna de datos numéricos. COUNT(Select_Item), que cuenta el número de elementos seleccionados en una columna. COUNT(*) cuenta el número de filas en el resultado de la consulta. MIN(Select_Item), que determina el menor valor de Select_Item en una columna. MAX(Select_Item), que determina el mayor valor de Select_Item en una columna. SUM(Select_Item), que proporciona el total de la suma de una columna de datos numéricos. No se pueden anidar las funciones de campo. Combinaciones Visual FoxPro admite sintaxis de combinación de 1992 SQL ANSI, lo que le permite crear consultas que vinculen las filas en dos o más tablas mediante la comparación de los valores de campos especificados. Por ejemplo, una combinación interna selecciona filas procedentes de dos tablas sólo cuando los valores de los campos combinados son iguales. Visual FoxPro admite combinaciones anidadas. Como SQL está basado en la teoría matemática de conjuntos, cada tabla se puede representar como un círculo. La cláusula ON que especifica las condiciones de la combinación determina el punto de intersección, que representa el conjunto de filas que coinciden. En el caso de una combinación interna, la intersección tendrá lugar en el interior o en una parte “interna” de los dos círculos. Una combinación externa incluye tanto las filas coincidentes que se han encontrado en la sección de intersección interna de las tablas, como las filas de la parte externa del círculo, a la izquierda o a la derecha de la intersección. Nota: Tenga presente la siguiente información a la hora de crear condiciones de combinación: Si incluye dos tablas en una consulta y no especifica una condición de combinación, cada registro de la primera tabla se combinará con cada registro de la segunda tabla mientras se cumplan las condiciones del filtro. Una consulta de este tipo puede producir unos resultados muy largos. Sea prudente al utilizar, en condiciones de combinación, funciones como DELETED( ), EOF( ), FOUND( ), RECCOUNT( ) y RECNO( ), que aceptan un área de trabajo o un alias opcional. La inclusión DGH Informática y Logística - 52 - Manual de ASP de un alias o de un área de trabajo en estas funciones puede producir resultados inesperados. SELECT no utiliza sus áreas de trabajo; realiza lo mismo que USE ... AGAIN. Las consultas de una sola tabla que utilizan estas funciones sin un área de trabajo o un alias opcional, devolverán resultados correctos. De todas formas, las consultas de varias tablas que utilicen dichas funciones (incluso sin un área de trabajo o un alias opcional) pueden devolver resultados inesperados. Tenga cuidado al combinar tablas que contengan campos vacíos, ya que Visual FoxPro establece coincidencias entre los campos vacíos. Por ejemplo, si combina CUSTOMER.ZIP e INVOICE.ZIP, y CUSTOMER contiene 100 códigos postales vacíos e INVOICE contiene 400 códigos postales vacíos, el resultado de la consulta contendrá 40.000 registros más, como resultado de los campos vacíos. Use la función EMPTY( ) para eliminar los registros vacíos del resultado de la consulta. El número de combinaciones que puede utilizar está limitado. Por cada instrucción Select se admiten nueve combinaciones como máximo. Si se incluye la función EVALUATE( ) en la cláusula WHERE de una consulta SQL, podrían devolverse datos incorrectos. Ejemplos: Los siguientes ejemplos ilustran la utilización de las funciones definidas por el usuario con SELECT SQL: Ejemplo 1 En el ejemplo 1 se muestran los nombres de todas las compañías en customer (un campo de una tabla). CLOSE ALL CLOSE DATABASES OPEN DATABASE (HOME(2) + 'data\testdata') SELECT customer.company ; FROM customer Ejemplo 2 El ejemplo 2 muestra el contenido de tres campos de dos tablas y combina las dos tablas basándose en el campo cust_id. Utiliza alias locales para ambas tablas. CLOSE ALL CLOSE DATABASES OPEN DATABASE (HOME(2) + 'data\testdata') SELECT x.company, y.order_date, y.shipped_on ; FROM customer x, orders y ; WHERE x.cust_id = y.cust_id Ejemplo 3 El ejemplo 3 muestra únicamente registros con datos únicos en los campos especificados. CLOSE ALL CLOSE DATABASES OPEN DATABASE (HOME(2) + 'data\testdata') SELECT DISTINCT x.company, y.order_date, y.shipped_on ; FROM customer x, orders y ; WHERE x.cust_id = y.cust_id Ejemplo 4 El ejemplo 4 muestra los campos country, postalcode y company en orden ascendente. CLOSE ALL CLOSE DATABASES OPEN DATABASE (HOME(2) + 'data\testdata') SELECT country, postalcode, company ; DGH Informática y Logística - 53 - Manual de ASP FROM customer ; ORDER BY country, postalcode, company Ejemplo 5 El ejemplo 5 almacena el contenido de los campos de dos tablas en una tercera tabla. CLOSE ALL CLOSE DATABASES OPEN DATABASE (HOME(2) + 'data\testdata') SELECT x.company, y.order_date, y.shipped_on ; FROM customer x, orders y ; WHERE x.cust_id = y.cust_id ; INTO TABLE custship.dbf BROWSE Ejemplo 6 El ejemplo 6 muestra únicamente los registros con una fecha de pedido anterior al 16/02/1994. CLOSE ALL CLOSE DATABASES OPEN DATABASE (HOME(2) + 'data\testdata') SELECT x.company, y.order_date, y.shipped_on ; FROM customer x, orders y ; WHERE x.cust_id = y.cust_id ; AND y.order_date < {^1994-02-16} Ejemplo 7 El ejemplo 7 muestra los nombres de todas las compañías de customer con un código postal que coincida con el código postal de la tabla orders. CLOSE ALL CLOSE DATABASES OPEN DATABASE (HOME(2) + 'data\testdata') SELECT company FROM customer x WHERE ; EXISTS (SELECT * FROM orders y WHERE x.postalcode = y.postalcode) Ejemplo 8 El ejemplo 8 muestra todos los registros de customer que tengan un nombre de compañía que comience por una C mayúscula y tenga cualquier longitud. CLOSE ALL CLOSE DATABASES OPEN DATABASE (HOME(2) + 'data\testdata') SELECT * FROM customer x WHERE x.company LIKE "C%" Ejemplo 9 El ejemplo 9 muestra todos los registros de customer que tengan un nombre de país que comience por U mayúscula seguido de un carácter desconocido. CLOSE ALL CLOSE DATABASES OPEN DATABASE (HOME(2) + 'data\testdata') SELECT * FROM customer x WHERE x.country LIKE "U_" DGH Informática y Logística - 54 - Manual de ASP Ejemplo 10 El ejemplo 10 muestra los nombres de todas las ciudades de customer en mayúsculas y llama CityList a la columna de resultados. CLOSE ALL CLOSE DATABASES OPEN DATABASE (HOME(2) + 'data\testdata') SELECT UPPER(city) AS CityList FROM customer Ejemplo 11 El ejemplo 11 muestra cómo se puede realizar una consulta de datos que contengan signos de porcentaje (%). Se colocará una barra inversa (\) antes del signo de porcentaje para indicar que debe ser tratado como un literal, y la barra inversa se especifica como el carácter de escape en la cláusula ESCAPE. Dado que las tablas de ejemplo incluidas con Visual FoxPro no contienen el carácter de signo de porcentaje, esta consulta no devolverá ningún resultado. CLOSE ALL CLOSE DATABASES OPEN DATABASE (HOME(2) + 'data\testdata') SELECT * FROM customer; WHERE company LIKE "%\%%" ESCAPE "\" Ejemplo 12 En el ejemplo 12 se muestra cómo se puede realizar una consulta de datos que contenga signos de subrayado (_). Se coloca una barra inversa (\) antes del signo de subrayado para indicar que debe ser tratado como un literal, y se especifica la barra inversa como el carácter de escape en la cláusula ESCAPE. Dado que las tablas de ejemplo incluidas con Visual FoxPro no contienen el carácter de subrayado, esta consulta no devolverá ningún resultado. CLOSE ALL CLOSE DATABASES OPEN DATABASE (HOME(2) + 'data\testdata') SELECT * FROM customer; WHERE company LIKE "%\_%" ESCAPE "\" Ejemplo 13 En el ejemplo 13, el carácter Escape se utiliza como un literal. El guión es tanto el carácter escape como un literal. La consulta devuelve todas las filas en las que el nombre de la organización contiene un signo de porcentaje seguido de un guión. Dado que las tablas de ejemplo incluidas con Visual FoxPro no contienen el carácter de signo de porcentaje, esta consulta no devolverá ningún resultado. CLOSE ALL CLOSE DATABASES OPEN DATABASE (HOME(2) + 'data\testdata') SELECT * FROM customer; WHERE company LIKE "%-%--%" Escape "-" DGH Informática y Logística - 55 -