24 de marzo de 2020

Agregar un campo Memo a un cursor

Como agregar un campo Memo a un cursor resultado de un comando SELECT-SQL fue preguntado varias veces en el Grupo de Noticias de Visual FoxPro en Español, veamos como hacerlo.

Hugo Ranea nos indica que partir de VFP9 disponemos de la función CAST() que nos hace muy fácil la tarea en una sola línea de código:

OPEN DATABASE (HOME(2) + "\Data\TestData")

SELECT Company, CAST("" as Memo) AS CampoMemo ;
  FROM Customer ;
  INTO CURSOR curVFP9

BROWSE

En versiones anteriores de VFP también podemos añadir un campo Memo a un cursor mediante un pequeño truco que es crear un cursor temporal con un campo Memo y un solo registro; y combinarlo con nuestra consulta:

OPEN DATABASE (HOME(2) + "\Data\TestData")

CREATE CURSOR Temporal (CampoMemo M)
APPEND BLANK IN Temporal

SELECT Customer.Company, Temporal.* ;
  FROM Customer, Temporal ;
  INTO CURSOR curVFPx

BROWSE

Sobre este mismo tema hay artículos en este Blog que vale la pena leerlos y recordarlos:

-- Agregar Columnas a Cursores VFP --

-- Agregar columnas en sentencias SELECT SQL --

 

10 de marzo de 2020

Truco: Agregar Columnas a Cursores VFP

A partir de VFP7 han cambiado algunas cosas, por ejemplo, no es posible utilizar la función ALTER TABLE < TuCursor > ADD COLUMN si es que tu cursor en cuestión tiene algún campo cuyo nombre tiene mas de 10 caracteres, aquí te mostramos como darle solución...

Veamos un ejemplo clásico, tienes un cursor generado por un SELECT-SQL, el cual, además de que deseas que sea editable, poder agregarle una columna para anotaciones, bueno, me podrás decir, en el mismo cursor agregale el campo... Pero que pasaría si deseo que dicho campo sea de tipo Memo??

La solución aparente podría ser utilizar el comando ALTER TABLE.... Pero esto, ya no es posible...

**** Creamos el cursor, nombres largos...
SELECT * FROM (HOME(2)+"NorthwindEmployees") ;
    INTO CURSOR MiCursor READWRITE
ALTER TABLE MiCursor ADD COLUMN CampoMemo M 

El código anterior generaría un error 1115 : Invalid operation for the cursor.

Esto se debe a que supuestamente no es posible hacer este tipo de operación cuando, el cursor generado por SELECT-SQL (o cualquier otro cursor, no tablas DBFs contenidas en DBCs) contiene algún campo con un nombre de mas de 10 caracteres. Esto según la documentación del producto

"... ALTER TABLE puede no producir los resultado esperados al ser utilizado con cursores creados por el comando CREATE CURSOR. Particularmente, puede crear cursores Visual FoxPro con características como, nombres largos de tablas, que normalmente están disponibles sola para las tablas que son parte de un contenedor de base de datos. ALTER TABLE guarda temporalmente una copia del cursor, que se apliquen las reglas a las tablas libres, y que cualquier característica soportada por la base de datos se pierda o cambie de manera impredecible. Por lo tanto, debe evitar utilizar ALTER TABLE con cursores Visual FoxPro, a menos que haya comprobado o entendido el resultado ...."

Otro ejemplo de esto sería algo tan sencillo como esto:

**** Con esto no obtenemos error ****
CREATE CURSOR cTest (iid int)
ALTER TABLE cTest ADD COLUMN CampoMemo M

**** Pero si intentamos esto  ******
CREATE CURSOR cTest2 (Masde10letras int)
ALTER TABLE cTest2 ADD COLUMN CampoMemo M 

Bueno, ya hemos demostrado cuándo y cómo falla, ahora iremos directo a una solución... La cual es, hacer una proyección de tu cursor, junto con otro cursor que tenga nada mas que el o los campos que deseas agregar, esto a través de una cláusula SELECT-SQL, como se muestra a continuación:

**** Creamos el cursor, nombres largos...
SELECT * FROM (HOME(2)+"NorthwindEmployees") ;
    INTO CURSOR MiCursor 
**** Creamos un cursor Dummie con el tipo de datos buscado, por ejemplo, un campo Memo  ****
**** e insertamos un registro en blanco ****
CREATE CURSOR Dummie (CampoMemo M)
APPEND BLANK  IN "Dummie"
**** Juntamos los dos cursores forzando su unión ****
SELECT * FROM MiCursor, Dummie ;
      INTO CURSOR MiCursor READWRITE
BROW

Con esto ya tenemos lo que deseabamos, aunque quizás sea un poco mas laborioso, al final, se llega al objetivo deseado.

Además, esta misma técnica puede ser utilizada para simplificar el agregar varias columnas, con sólo tres instrucciones, considerando que de otra manera se tendrían que utilizar varias instrucciones ALTER TABLE (cuando fuere posible) :

**** Creamos un cursor de prueba ****
CREATE CURSOR miEjemplo (iid int)
**** Creamos el cursor con los campos a agregar ****
CREATE CURSOR cAgregar (cName char(80), cEmail char(60), cNotes M)
APPEND BLANK IN "cAgregar"
SELECT * FROM MiEjemplo, cAgregar ;
     INTO CURSOR miEjemplo READWRITE

Espero les sea de utilidad.

Esparta Palma