11 de diciembre de 2006

Leer y modificar valores de cabecera de tabla para un campo autoincrementado

A partir de VFP 8 podemos usar campos enteros autoincrementados automáticamente, aún en tablas libres. (Siempre está la opción de hacer uso de los triggers en tablas vinculadas a una DB, pero hay que armarlo...)

VFP nos informa en que lugar de la cabecera de la tabla coloca el próximo valor y el del incremento a usar en este tipos de campos. En esta oportunidad acerco una rutina que permite leer / modificar los valores en la cabecera de la tabla para un campo autoincrementado.

El programa de ejemplo, que tomé ex-profeso de una versión que alguien ofreció para indicar como modificar el valor y/o el incremento a través del comando SQL ALTER TABLE, es válido y funciona Ok si la tabla puede abrirse en modo exclusivo.

Si por algún motivo (lo más común en un entorno multiusuario) tenemos la tabla abierta en modo compartido y queremos modificar el próximo valor y/o el incremento, esta rutina lo permite (así como leer los valores actuales).
Nota: Para que el ejemplo funcione correctamente se debe descargar la librería LeeIncPtr.dll (incluida en el archivo comprimido junto al programa autoincrement_altera.prg) haciendo clic en el siguiente enlace: AutoIncrement.zip (8,77 KB).
******************************************
* AutoIncrement_Altera.prg
******************************************
Declare Long LEEINCRE In "LeeIncPtr.DLL" ;
  String @ Nom_tabla, String  @ Paso, ;
  String @ Campo_autoinc
Declare Long PONEINCRE In "LeeIncPtr.DLL" ;
  String @ Nom_tabla, Long @ Valor_prox, ;
  String  @ Paso, String @ Campo_autoinc

* La que sigue es la rutina "casi original",
* modificada para forzar una apertura compartida
#Define CRLF Chr(13)+Chr(10)
Local Proximo As Long, Paso As String
Set Exclusive Off
Local lcStr As String
Local lnSelect As Integer

* Save environment and erase auto increment table.
lnSelect = Select()
Select 0
Erase AI_Table.Dbf

* Create Auto Increment table setting the
* 'iID' column as an auto increment field
* with the starting value set to 1 and the
* increment value set to 1.
Create Table AI_Table Free ;
  ( iID i Autoinc Nextvalue 1 Step 1, ;
  CustName c(30))
Close Database All && Agregado
Use In 0 "AI_Table" Shared  && Agregado
* Insert three records into the table.
* You do not assign any values to
* the auto increment field.
Insert Into AI_Table (CustName) Values ("Jane Smith")
Insert Into AI_Table (CustName) Values ("John Doe")
Insert Into AI_Table (CustName) Values ("Greg Jones")
Go Top

* Browse the table.
Browse Nowait

lcStr = "Auto Increment Table created with the " + ;
  "starting value set to 1 and the increment set to 1"
Messagebox(lcStr)

* Alter the table to set the next auto increment value
* inserted to be 100 and incrementing step to be 10.

* Se agregó rutina de error y uso de la librería
Ok = .T.
Try
  Alter Table AI_Table Alter Column iID i Autoinc Nextvalue 100 Step 10
Catch To oErr
  Messagebox("Catch: " + Transform(oErr.ErrorNo) + ;
    Chr(10) + oErr.Message + Chr(10) + ;
    "No puede usar en este modo la sentencia: " + ;
    Chr(10) + oErr.LineContents + Chr(10) + ;
    "Se intentará modificar con la librería", ;
    48,"Error")
  Ok = .F.
Finally
Endtry
If !Ok
  Tbl = Dbf()
  Proximo = 100
  Paso = Chr(10)
  Campo = "iID"
  If PONEINCRE(@Tbl, @Proximo, @Paso, @Campo) <> 1
    Messagebox("Error procesando con PONEINCRE", 48, "Error")
    Return
  Endif
  * Debemos cerrar y volver a abrir la tabla,
  * para que VFP actualice internamente el Step
  Use In ("AI_Table")
  Use In 0 "AI_Table" Shared
Endif
* Insert three more records into the table.
Insert Into AI_Table (CustName) Values ("Jay Lewis")
Insert Into AI_Table (CustName) Values ("Steve Appleton")
Insert Into AI_Table (CustName) Values ("Ken Garvy")
Go Top

* Browse the table.
Browse Nowait

lcStr = "Auto Increment Table was altered to set " + ;
  "the next auto increment value " + ;
  "to 100 and the increment step to 10"
Messagebox(lcStr)

* Leemos como quedó ahora la tabla
Tbl = Dbf()
Campo = "iID"
Prox = LEEINCRE(@Tbl, @Paso, @Campo)
If Prox > 0
  Messagebox("Próximo valor: " + Transform(Prox) + ;
    Chr(10) + "Step: " + Transform(Asc(Paso)), ;
    64, "Estado autoincremento")
Endif

* Restore environment.
Use
Select (lnSelect)

Return
Espero pueda serles de utilidad.

Gustavo Devincenzi

No hay comentarios. :

Publicar un comentario