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
¿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.
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
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
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
En los siguientes artículos veremos más sobre cómo usar esta tabla, especialmente con procedimientos almacenados.