Cuando se dañan los archivos índices de una tabla, ejecutar el comando REINDEX a veces no es suficiente. Hay casos en que hay que generar nuevamente cada uno de los índices con el comando INDEX ON y/o ALTER TABLE.
El siguiente código lo utilizo como una herramienta para regenerar rápidamente todos los índices de todas las tablas de una base de datos, y aparte me genera un archivo PRG con nombre "REG_CDX_????????.PRG" (donde "????????" es el nombre de la base de datos) que lo puedo ejecutar posteriormente
Si la base de datos contiene relaciones persistentes e integridad referencial NO ejecuten el código publicado, ni el archivo .PRG generado ya que éstos eliminan todas las etiquetas de índices de la tabla (DELETE TAG ALL
) y esta acción también elimina el archivo .CDX y quita las relaciones persistentes entre las tablas y la integridad referencial existentes en la base de datos. Si éste es su caso, puede utilizar la herramienta GenDBC.PRG que está en la carpeta \Tools\Gendbc\ en la carpeta raíz de instalación de Visual FoxPro, que si respalda y restaura las relaciones y la IR.
Usen este código bajo sus propios riesgos. Hagan una copia de seguridad de la base de datos antes de probarlo.
* ----- * Configurando la variable llRegenera en: * .T. = si desea que se regeneren todos los índices al momento de ejecutar el código * .F. = solo genera un archivo PRG con el código para generarlos posteriormente *----- LOCAL laDBF[1], laTag[1], llRegenera, lnI, lnJ, lnTAG LOCAL lcCmd, lcDBC, lcPRG, lcTabla, lnDBF, loExc CLOSE TABLES ALL CLOSE DATABASES ALL CLEAR ALL SET MEMOWIDTH TO 128 SET SAFETY OFF #DEFINE CR_LF CHR(13)+CHR(10) *-- Selecciono DBC m.lcDBC = GETFILE([DBC]) *-- Solo genera PRG o genera PRG y regenera índices m.llRegenera = .F. *-- Nombre del PRG generado m.lcPRG = [REG_CDX_] + FORCEEXT(JUSTFNAME(m.lcDBC), [PRG]) IF EMPTY(m.lcDBC) OR NOT FILE(m.lcDBC) MESSAGEBOX([Debe seleccionar un archivo DBC], 16) RETURN ENDIF CLEAR STRTOFILE([*--- Regenera los índices compuestos de las tablas de la base de datos ] + ; JUSTFNAME(m.lcDBC) + CR_LF, m.lcPRG, 0) STRTOFILE([*--- ] + CHRTRAN(TTOC(DATETIME(), 3), [T], [ ]) + CR_LF + CR_LF, m.lcPRG, 1) OPEN DATABASE (m.lcDBC) && EXCLUSIVE VALIDATE SET DATABASE TO (JUSTSTEM(m.lcDBC)) STRTOFILE([OPEN DATABASE ("] + m.lcDBC + [") EXCLUSIVE VALIDATE] + CR_LF, m.lcPRG, 1) STRTOFILE([SET DATABASE TO ] + JUSTSTEM(m.lcDBC) + CR_LF + CR_LF, m.lcPRG, 1) m.lnDBF = ADBOBJECTS(laDBF, "TABLE") ASORT(m.laDBF) FOR m.lnI = 1 TO m.lnDBF *-- Recorro todas las tablas de la DBC m.lcTabla = ADDBS(JUSTPATH(DBC())) + m.laDBF(m.lnI) TRY IF m.llRegenera && Necesito abrir en modo EXCLUSIVE USE (m.lcTabla) EXCLUSIVE IN SELECT(m.laDBF(m.lnI)) ELSE USE (m.lcTabla) SHARED IN SELECT(m.laDBF(m.lnI)) ENDIF STRTOFILE([USE ("] + m.lcTabla + [") EXCLUSIVE ] + CR_LF, m.lcPRG, 1) m.lnTAG = ATAGINFO(laTag) m.lcCmd = "" FOR m.lnJ = 1 TO m.lnTAG *-- Recorro todas las etiquetas de índices IF m.laTag(m.lnJ, 2) = [PRIMARY] m.lcCmd = m.lcCmd + ; [ALTER TABLE ] + m.laDBF(m.lnI) + [ ADD PRIMARY KEY ] + m.laTag(m.lnJ, 3) + ; [ TAG ] + m.laTag(m.lnJ, 1) + ; [ COLLATE "] + m.laTag(m.lnJ, 6) + ["] + CR_LF ELSE m.lcCmd = m.lcCmd + ; [INDEX ON ] + m.laTag(m.lnJ, 3) + [ ] + ; [TAG ] + m.laTag(m.lnJ, 1) + [ ] + ; IIF(m.laTag(m.lnJ, 2) = "BINARY", m.laTag(m.lnJ, 2) + [ ], m.laTag(m.lnJ, 5) + [ ]) + ; IIF(EMPTY(m.laTag(m.lnJ, 4)), [], [FOR ] + m.laTag(m.lnJ, 4) + [ ]) + ; IIF(m.laTag(m.lnJ, 2) = "CANDIDATE", m.laTag(m.lnJ, 2) + [ ], []) + ; [COLLATE "] + m.laTag(m.lnJ, 6) + ["] + CR_LF ENDIF ENDFOR IF m.llRegenera DELETE TAG ALL PACK EXECSCRIPT(m.lcCmd) ENDIF STRTOFILE([DELETE TAG ALL] + CR_LF, m.lcPRG, 1) STRTOFILE([PACK] + CR_LF + CR_LF, m.lcPRG, 1) STRTOFILE(m.lcCmd + CR_LF, m.lcPRG, 1) CATCH TO m.loExc STRTOFILE([* ERROR:] + CR_LF, m.lcPRG, 1) STRTOFILE([* ] + m.loExc.MESSAGE + CR_LF, m.lcPRG, 1) FINALLY USE IN SELECT(m.laDBF(m.lnI)) STRTOFILE([USE IN SELECT("] + m.laDBF(m.lnI) + [")] + CR_LF + CR_LF, m.lcPRG, 1) ENDTRY ENDFOR MODIFY FILE (m.lcPRG)