Clarion y SQL (VII)

SQL, mySQL, postgreSQL y otros motores
Responder
Avatar de Usuario
Mauricio
Desarrollador de Clarion
Mensajes: 1125
Registrado: Dom Feb 06, 2011 9:34 am
Ubicación: España
Contactar:

Clarion y SQL (VII)

Mensaje por Mauricio » Lun Sep 12, 2011 10:33 am

Hace algunos años leí una serie de artículos de Dan Pressnell llamados A better SQL. Los artículos hoy se pueden encontrar en la página de Icetips, acá les dejo el enlace para el primero de ellos. http://www.icetips.com/showarticle.php? ... productID=. La lectura es imprescindible para todo aquel que se inicia con Clarion y SQL así que se los recomiendo. El único inconveniente puede ser que están en inglés pero el esfuerzo vale la pena.

Me voy a permitir robar una comparación que hace Pressnell en uno de sus artículos para explicar lo que es la arquitectura cliente-servidor. Imaginemos que vamos a un McDonald y queremos comer unas papas fritas. Vamos al mostrador, hacemos la cola y cuando el empleado del mes nos toma el pedido le decimos UNA (1) papa frita. Una vez servidos nos vamos a la mesa, nos sentamos y comemos nuestra única papa frita. Obviamente no nos tapamos ni una muela así que nos levantamos nuevamente, volvemos a hacer la cola, volvemos a pedir una papa frita, nos sentamos y la comemos. Y así hasta que estemos llenos (en mi caso serán muchos viajes al mostrador). Ridículo, ¿no?. Sin embargo, por más tonto que parezca, cuando empezamos a pasar nuestras aplicaciones a SQL cometemos ese error muchas veces. Por ejemplo en este código:

Código: Seleccionar todo

set(ARTICULOS, ART:PK_ART)
LOOP UNTIL Access:ARTICULOS.Next()
    ART:PRECIO = ART:PRECIO * 1.05
    PUT(ARTICULOS)
END !LOOP
estamos viajando al servidor por cada artículo que tengamos, incrementando su precio un 5%. Si son varios los usuarios que realizan procesos como ese al mismo tiempo el servidor estará muy ocupado atendiendo los pedidos y nuestro sistema en SQL, que debería ser más rápido que uno en TPS, se vuelve extremadamente lento. Y luego viene la queja de nuestros clientes, con preguntas como ¿y para esto me cobraste la actualización del sistema a SQL diciéndome que era mejor?. Evitemos ese tipo de cuestionamiento.

¿Cómo resolvemos eso? La respuesta obvia, al igual que con las papas fritas, es ir al servidor una sola vez y listo, que se encargue él de resolver todo. Pero para hacer esto vamos a necesitar la ayuda invalorable de la nunca bien ponderada (al menos en el nombre) tabla estúpida.

Una de las injusticias más grande en el mundo Clarion haber llamado a la tabla de esa manera, así que vamos a tratar de revindicarla. Es una tabla particular dado que va a actuar como un buffer de memoria pero NUNCA tendrá registros. Para que quede claro, JAMÁS haremos un add o put a esa tabla, no tiene registros. Es más, ni siquiera hace falta que exista en el motor. Esto último queda a gusto de uds. pero enumeraré las alternativas:
  • 1) La tabla existe físicamente en el motor como cualquier otra tabla. La creamos a través de un script o dejamos que Clarion lo haga (aunque esto no es una buena idea)
    2) Usamos la opción TURBOSQL= TRUE del driver, lo cual no verificará que los campos de la tabla existan
    3) Definimos la tabla apuntando a una tabla existente, lo mismo que para sus campos.
Particularmente prefiero esta última técnica dado que empecé a usar la tabla estúpida antes que existiera la opción TURBOSQL. Por ejemplo, mi definición de la tabla es la siguiente:

Código: Seleccionar todo

SQL_File             FILE,DRIVER('MSSQL'),PRE(SQF),BINDABLE,THREAD,EXTERNAL('')
Record                   RECORD,PRE()
C1                          CSTRING(10001),NAME('PRINTFMT')
C2                          CSTRING(10001),NAME('PRINTFMT')
C3                          CSTRING(10001),NAME('PRINTFMT')
C4                          CSTRING(10001),NAME('PRINTFMT')
C5                          CSTRING(10001),NAME('PRINTFMT')
C6                          CSTRING(10001),NAME('PRINTFMT')
C7                          CSTRING(10001),NAME('PRINTFMT')
C8                          CSTRING(10001),NAME('PRINTFMT')
C9                          CSTRING(10001),NAME('PRINTFMT')
C10                         CSTRING(10001),NAME('PRINTFMT')
C11                         CSTRING(10001),NAME('PRINTFMT')
C12                         CSTRING(10001),NAME('PRINTFMT')
C13                         CSTRING(10001),NAME('PRINTFMT')
C14                         CSTRING(10001),NAME('PRINTFMT')
C15                         CSTRING(10001),NAME('PRINTFMT')
C16                         CSTRING(10001),NAME('PRINTFMT')
C17                         CSTRING(10001),NAME('PRINTFMT')
C18                         CSTRING(10001),NAME('PRINTFMT')
C19                         CSTRING(10001),NAME('PRINTFMT')
C20                         CSTRING(10001),NAME('PRINTFMT')
C21                         CSTRING(10001),NAME('PRINTFMT')
C22                         CSTRING(10001),NAME('PRINTFMT')
C23                         CSTRING(10001),NAME('PRINTFMT')
C24                         CSTRING(10001),NAME('PRINTFMT')
C25                         CSTRING(10001),NAME('PRINTFMT')
C26                         CSTRING(10001),NAME('PRINTFMT')
C27                         CSTRING(10001),NAME('PRINTFMT')
C28                         CSTRING(10001),NAME('PRINTFMT')
C29                         CSTRING(10001),NAME('PRINTFMT')
C30                         CSTRING(10001),NAME('PRINTFMT')
                         END
                     END  
En el FullPathName de la tabla le indico: dbo.SysColumns, que es una tabla de sistema y si se fijan, cada campo tiene como external name "PRINTFMT", que es también es un campo de esta tabla. Una ventaja de usar esta técnica es que al apuntar a una tabla de sistema puedo ejecutar scripts (por ejemplo para crear la base de datos de nuestro sistema durante la instalación del mismo). Otra cosa importante es el uso de usar CSTRING para todos los campos. El CSTRING es como el comodín del Chinchón (o el joker de las cartas de poker), lo podemos usar para cualquier tipo de datos (menos blobs).

Una vez que tengamos nuestra tabla el uso es sencillo. A través de Prop:SQL le enviamos un comando al motor como si interactuáramos directamente con él. Si el comando es un SELECT la tabla se llenará con el resultado del mismo (pero recuerden que no tendrá registros, es como si fuese una cola de memoria) y luego haremos lo que queramos con ellos. Si el comando es un UPDATE el motor ejecutará el mismo. También la podemos usar para llamar a procedimientos almacenados.

Veamos unos ejemplos. Primero resolvamos el problema de actualización de precios, el cual se reduce a lo siguiente:

Código: Seleccionar todo

SQL_FILE{Prop:SQL} = 'UPDATE ARTICULOS SET PRECIO = PRECIO * 1.05'
IF NOT ErrorCode()
    Message('Articulos actualizados')
ELSE
    Message('Revisar el query porque algo está mal')
END !IF
Si queremos saber cuántos artículos pertenecen a un proveedor determinado:

Código: Seleccionar todo

SQL_FILE{Prop:SQL} = 'SELECT COUNT(*) FROM ARTICULOS WHERE ART_PRO_ID = 23'
IF NOT ErrorCode()
   NEXT(SQL)
   Message('Hay ' & SQF:C1 & ' artículos del proveedor 23')
ELSE
   Message('Macho, otra vez le erraste con el query')
END !IF
Observen que, a diferencia del ejemplo anterior, acá fue necesario hacer un NEXT para traer el primer registro y mostrarlo.

En los siguientes artículos veremos más sobre cómo usar esta tabla, especialmente con procedimientos almacenados.
Mauricio, básicamente usando Clarion 6.3
www.tdcsoftware.com y www.clarioneros.com/blog


salvaram
Novato
Mensajes: 47
Registrado: Mar Mar 08, 2011 6:09 pm
Contactar:

Re: Clarion y SQL (VII)

Mensaje por salvaram » Mié Mar 14, 2012 1:23 am

Muy buen aporte Gracias... sigue asi!!! compartiendo.

Responder

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 3 invitados