; # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ; # # ; # # -- PROGRAMA .....: MDB2SQLite_jamaro.au3 ; # # -- AUTOR ........: jamaro ; # # -- OTROS ........: - Funciones de lectura de base de datos .mdb basadas en Access.au3 por George (GEOSoft) Gedye ; # # - http://www.sqlite.org/ ; # # - http://www.w3schools.com/ado/default.asp ; # # - http://www.w3schools.com/ado/ado_datatypes.asp ; # # - ActiveX Data Objects (ADO) MSDN - http://msdn.microsoft.com/en-us/library/windows/desktop/ms676795%28v=vs.85%29.aspx ; # # -- CORREO .......: ; # # -- FECHA INCICIAL: Enero 2012 ; # # -- VERSIÓN ......: 20120211 ; # # -- COMENTARIO ...: Conversor de Base de Datos de Access (.mdb) a SQLite ; # # 1. Extrae el nombre de tablas de una base de datos de Access (.mdb) ; # # 2. Extrae el nombre de los campos de cada tabla extraída ; # # 3. Extrae el nombre de los campos clave (PRIMARY KEY) de cada tabla extraída ; # # 4. Extrae el nombre de los campos clave foráneos (FOREIGN KEY) de cada tabla extraída ; # # 5. Asigna a cada tipo de datos de la bd original, el tipo compatible en SQLite ; # # 6. Crea la bd SQLite con las tablas extraídas del modo ; # # 7. Extrae los datos de los campos de la bd (.mdb) y los copia en las tablas de la bd SQLite ; # # ; # # PENDIENTE: ; # # - Preguntar si se desea sobreescribir si ya existe la base de datos SQLite .db ; # # - Sobreescribir las tablas si ya existen en la base de datos SQLIte .db ; # # - ... ; # # ; # # - Hacer un GUI con: ; # # - selección de archivo origen y destino ; # # - selección de tipo de tabla que se desea copia Tablas y/o Vistas (Consultas) ; # # - listview con nombres de tablas para seleccionar las que se quiera convertir ; # # - seleccionar si se desea copiar sólo la estructura de tablas o también los datos de los registros ; # # - filtrar los registros que se desean copiar ; # # - Permitir uso desde línea de comando ; # # - ... ; # # ; # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #region Includes, Opciones ; ------ Includes ------ #include #include #include ;- De AccessConstans.au3 por George (GEOSoft) Gedye( Sólo las variables necesarias) Global Const $adoProvider = _adoProvider() ; ------ Opciones ------ Opt("MustDeclareVars", 1) ; Se desactiva porque da error al no haberse declarado algunas variables en Access.au3 Global $depuracion = 1 #endregion Includes, Opciones #region Variables ; Tipos de datos según http://www.w3schools.com/ado/ado_datatypes.asp Global $tipoDatos[11][2] = [["2", "INTEGER"],["3", "INTEGER"],["4", "REAL"],["5", "REAL"],["6", "TEXT"],["7", "INTEGER"],["11", "INTEGER"],["131", "INTEGER"],["202", "TEXT"],["203", "TEXT"],["205", "BLOB"]] ;_ArrayDisplay($tipoDatos, "[" & @ScriptLineNumber & "]") Global $BaseAccess, $NombreBDsinExtension, $NombreBD Global $mListaTablasConTipos Global $mListadoFKTablasConCadena Global $mListadoPrimaryKeys #endregion Variables #region Principal ; ----- Selección de archivo .mdb (la base de datos SQLite tendrá el mismo nombre con la extensión .db) $BaseAccess = FileOpenDialog("Abrir BD Access", @ScriptDir & "\", "Base Datos Access (*.mdb)", 1) $NombreBDsinExtension = StringLeft($BaseAccess, StringLen($BaseAccess) - 4) $NombreBD = $NombreBDsinExtension & '.db' ; Nombre de BD SQLite ; ----- Iniciación de SQLite InicioSQLite() Global $TiempoInicio = TimerInit() ; Inicio de contador. Al final muestra en MsgBox con el tiempo empleado en hacer la conversión ; ------------------------------------------------------- ; ---------------- Extracción de TABLAS ----------------- ; Se obtiene una matriz de dos columnas: NOMBRE_TABLA, TIPO_TABLA ; ------------------------------------------------------- $mListaTablasConTipos = _accessListTables_j($BaseAccess, 0) ; Segundo parámetro $TipoTabla= 0 TABLE, 1 VIEW ;_ArrayDisplay($mListaTablasConTipos, "[" & @ScriptLineNumber & "]") ; ------------------------------------------------------ ; ------------- Extracción de FOREIGN KEYS ------------- ; Se obtiene una matriz de dos columnas: NOMBRE_TABLA, Cadena_Foreign_Key (Ej: FOREING KEY ('Nombre_Tabla') REFERENCES [Nombre_Tabla](Campo_Foreign_Key) ON UPDATE NO ACTION/CASCADE ON DELETE NO ACTION/CASCADE ; ------------------------------------------------------ $mListadoFKTablasConCadena = _accessListForeignKeys($BaseAccess) ;_ArrayDisplay($mListadoFKTablasConCadena, "[" & @ScriptLineNumber & "]") ; ------------------------------------------------------ ; ------------- Extracción de PRIMARY KEYS ------------- ; Se obtiene una matriz de dos columnas: NOMBRE_TABLA, NOMBRE_CAMPO_PRIMARY_KEY ; ------------------------------------------------------ $mListadoPrimaryKeys = _accessListPrimaryKeys($BaseAccess) ;_ArrayDisplay($mListadoPrimaryKeys, "[" & @ScriptLineNumber & "]") ; ------------------------------------------------------ ; --------- Extracción de CAMPOS y TIPO_DE_DATO -------- ; ------------------------------------------------------ ; Se recorre el listado de tablas para extraer los nombres de los CAMPOS y sus TIPO_DE_DATOS ; Se añade el texto PRIMARY KEY en los campos que corresponde ; Se reemplaza el valor de TIPO_DE_DATOS por el valor en texto para SQLite (TEXT, REAL, INTEGER, BLOB,...) ; Se añade el texto FOREIGN KEY ... REFERENCES ... ON UPDATE ... ON DELETE ... ; Se crea la tabla en el archivo SQLite ; ------------------------------------------------------ For $i = 0 To UBound($mListaTablasConTipos) - 1 Global $ListaCampos = __accessCampos($BaseAccess, $mListaTablasConTipos[$i][0], 1) ; Se utiliza 1 para que devuelva tipo de datos de los campos _cw($ListaCampos) ; ----- Inserta PRIMARY KEY en el campo ----- ; Busca en la matriz de FOREIGN KEYS el nombre de la TABLA Local $IndiceTablaBuscadaPK = _ArraySearch($mListadoPrimaryKeys, $mListaTablasConTipos[$i][0], 0, 0, 0, 0, 0, 0) _cw("Indice de " & $mListaTablasConTipos[$i][0] & " = " & $IndiceTablaBuscadaPK) If $IndiceTablaBuscadaPK <> -1 Then ; Si no se encuentra el nombre de la tabla en la matriz de PrimaryKeys, no tiene PK y salta Local $CampoPK = $mListadoPrimaryKeys[$IndiceTablaBuscadaPK][1] ;_cw("Tabla " & $mListaTablasConTipos[$i][0] & " PK " &$CampoPK) $ListaCampos = StringRegExpReplace($ListaCampos, "(" & $CampoPK & "\|\w+)", "$1" & " PRIMARY KEY", 1) ; Inserta PRIMARY KEY después del tipo de dato del campo. (Ej. [Ciudad] TEXT,... pasa a ser [Ciudad] TEXT PRIMARY KEY,... EndIf Global $mListaCampos = StringSplit($ListaCampos, "|") Global $sListaCamposComas = StringReplace($ListaCampos, "|", ",") Local $ListaCampostxt = "" For $x = 1 To UBound($mListaCampos) - 1 Step 2 $ListaCampostxt = $ListaCampostxt & "[" & $mListaCampos[$x] & "] " & $mListaCampos[$x + 1] & "," Next $ListaCampostxt = StringTrimRight($ListaCampostxt, 1) ; Quita el último carácter "," Local $IndiceTablaBuscadaFK = _ArrayFindAll($mListadoFKTablasConCadena, $mListaTablasConTipos[$i][0], 0, 0, 0, 0, 0) ; Columna=0 ;_ArrayDisplay($IndiceTablaBuscadaFK, "[" & @ScriptLineNumber & "] Tabla " & $mListaTablasConTipos[$i][0]) Local $CadenaFK = "" For $FN_TablaFK = 0 To UBound($IndiceTablaBuscadaFK) - 1 ;_cw("Índice: " & $IndiceTablaBuscadaFK[$FN_TablaFK] & " La tabla " & $mListaTablasConTipos[$i][0] & " tiene " & $mListadoFKTablasConCadena[$IndiceTablaBuscadaFK[$FN_TablaFK]][1]) $CadenaFK = $CadenaFK & $mListadoFKTablasConCadena[$IndiceTablaBuscadaFK[$FN_TablaFK]][1] & "," Next If $CadenaFK <> "" Then $CadenaFK = ", " & StringTrimRight($CadenaFK, 1) Local $sCommand = "CREATE TABLE [" & $mListaTablasConTipos[$i][0] & "] (" & $ListaCampostxt & $CadenaFK & ");" ;_cw($sCommand) ; Se sustituye el valor del tipo de datos por su correspondiente tipo en SQLite For $f = UBound($tipoDatos, 1) - 1 To 0 Step -1 ; Cuenta atrás para que tome primero 203 y luego 3 (sino se convierte mal) $sCommand = StringRegExpReplace($sCommand, " " & $tipoDatos[$f][0], " " & $tipoDatos[$f][1]) ;_cw("Sustituye: " & $tipoDatos[$f][0] & " por " & $tipoDatos[$f][1]) Next _cw($sCommand) ; Crea Tablas If _SQLite_Exec(-1, $sCommand) <> $SQLITE_OK Then _m("Error con SQLite");Return SetError(1, 0, -1) ;_ArrayDisplay($mListaCampos,"[" & @ScriptLineNumber & "] Tabla " & $i & " - " &$mListaTablasConTipos[$i][0]) Next ; ------------------------------------------------------ ; ----------- Lectura de Datos de una Tabla ------------ ; Se introduce los valores en la base de datos SQLite con: INSERT INTO [Nombre_Tabla] ... ; Para evitar cadenas muy largas, se inserta los datos en grupos de $tamanogrupo registros ; ------------------------------------------------------ For $a = 0 To UBound($mListaTablasConTipos) - 1 ; Recorre todas las tablas _cw("Leyendo datos de tabla: " & "[" & $mListaTablasConTipos[$a][0] & "]") Global $matriz1 = _accessQueryLike_j($BaseAccess, "[" & $mListaTablasConTipos[$a][0] & "]") ;_accessQueryLike_j($adSource,$adTable) ;_ArrayDisplay($matriz1, "[" & @ScriptLineNumber & "] " & $mListaTablasConTipos[$a][0]) If @error = 0 Then ; Cuando la tabla tenga registros (si no tiene registros @error=1 definido en _accessQueryLike_j() Local $tamanogrupo = 100 ; Tamaño de grupos para crear el comando INSERT de SQLite Local $totalregistros = UBound($matriz1) - 1; Filas (el primer registro es la fila 0) Local $CamposEnRegistro = UBound($matriz1, 2) - 1; Columnas ; Cuando $tamanogrupo es menor que el total de registros se divide el total de registros en grupos para no soprepasar límites de SQLite en INSERT TO ... UNION SELECT If $tamanogrupo <= $totalregistros Then Local $grupos = Int($totalregistros / $tamanogrupo) _cw("[" & $mListaTablasConTipos[$a][0] & "] tiene " & $totalregistros & " registros. Se va a repetir " & $grupos & " veces y el resto") For $ForGrupos = 1 To $grupos ; Desde el primer registro hasta el último de los grupos enteros Local $valuesTODO = "" If $ForGrupos = 1 Then Local $ini = ($ForGrupos * $tamanogrupo) - $tamanogrupo, $fin = $ForGrupos * $tamanogrupo Else Local $ini = ($ForGrupos * $tamanogrupo) - $tamanogrupo + 1, $fin = $ForGrupos * $tamanogrupo EndIf InsertaDatosSQLite($ini, $fin, $mListaTablasConTipos[$a][0], $valuesTODO, $CamposEnRegistro) Next ; $ForGrupos If $grupos * $tamanogrupo < $totalregistros Then ; Para el caso en $totalregistros/$tamanogrupo sea un número exacto sin decimales Local $ini = ($grupos * $tamanogrupo) + 1, $fin = $totalregistros ; Los registros restantes después de hacer grupos de $tamanogrupo Local $valuesTODO = "" InsertaDatosSQLite($ini, $fin, $mListaTablasConTipos[$a][0], $valuesTODO, $CamposEnRegistro) EndIf Else Local $valuesTODO = "" Local $ini = 0, $fin = $totalregistros InsertaDatosSQLite($ini, $fin, $mListaTablasConTipos[$a][0], $valuesTODO, $CamposEnRegistro) EndIf ; $tamanogrupo Else _cw("La tabla [" & $mListaTablasConTipos[$a][0] & "] no tiene datos.") EndIf ; @error=0 Next ; $a ;;;_SQLite_Exec(-1,"PRAGMA FOREIGN_KEYS=1") ; Para activar el uso de FOREIGN KEYS ---> Esto se debe hacer en el programa que utilice la base de datos para poder utilizar las Foreign Keys CierraBD($NombreBD) MsgBox(0, "Aviso", "La operación de conversión ha durado : " & StringFormat("%.2f", TimerDiff($TiempoInicio) / 1000) & " segundos") #endregion Principal Func InsertaDatosSQLite($ini, $fin, $mTabla, $sValores, $nCampos, $LineaDesde = @ScriptLineNumber) _cw($LineaDesde & " [" & $mListaTablasConTipos[$a][0] & "] De " & $ini & " a " & $fin) ; <--- Para pruebas For $FNRegistros = $ini To $fin ; Recorre registros de la tabla ;_cw($FNRegistros & " ") Local $values = "" For $FNCampos = 0 To $nCampos $values = $values & StringReplace($matriz1[$FNRegistros][$FNCampos], "'", "''") & "','" ; Se reemplaza ' por '' para que se pueda insertar ' en un campo de SQLite. Ej. L''Horta Next If $FNRegistros = $fin Then $valuesTODO = $valuesTODO & StringTrimRight($values, 2) ; Elimina el último ,' Else $valuesTODO = $valuesTODO & StringTrimRight($values, 2) & " UNION ALL SELECT '" ; Elimina el último ,' y añade UNION ALL SELECT EndIf ;_cw($valuesTODO) ; <--- Para pruebas Next ; $FNRegistros ;_cw($valuesTODO) ; <--- Para pruebas Local $sCommand = "INSERT INTO [" & $mListaTablasConTipos[$a][0] & "] SELECT '" & $valuesTODO & ";" ;_cw(StringLeft($sCommand,150) & "... ... ...") ; Introduce datos en las tablas If _SQLite_Exec(-1, $sCommand) <> $SQLITE_OK Then ;_ArrayDisplay($Campos, "ERROR SQLITE [" & @ScriptLineNumber & "] " & $matriz1[$FNRegistros]) _m("Error con SQLite");Return SetError(1, 0, -1) EndIf EndFunc ;==>InsertaDatosSQLite #region Funciones lectura datos de archivos .mdb ; ------------ De Access.au3 por George (GEOSoft) Gedye: http://autoit.mvps.org/udf_code.aspx?udf=access ------------ Func _adoProvider() Local $oProvider = "Microsoft.Jet.OLEDB.4.0; " Local $objCheck = ObjCreate("Access.application") If IsObj($objCheck) Then Local $oVersion = $objCheck.Version If StringLeft($oVersion, 2) == "12" Then $oProvider = "Microsoft.ACE.OLEDB.12.0; " EndIf Return $oProvider EndFunc ;==>_adoProvider Func _dbOpen($adSource) Global $oADO $oADO = ObjCreate("ADODB.Connection") $oADO.Provider = $adoProvider $oADO.Open($adSource) Return $oADO EndFunc ;==>_dbOpen Func _dbOpenRecordset() Global $oRec $oRec = ObjCreate("ADODB.Recordset") Return $oRec EndFunc ;==>_dbOpenRecordset ; ------------ Basadas en Access.au3 por George (GEOSoft) Gedye: http://autoit.mvps.org/udf_code.aspx?udf=access ------------ ;=============================================================================== ; Function Name: _accessListTables_j() (Modificación de _accessListTables()) ; Description: List the tables in an MSAccess (*.mdb) file ; Syntax: _accessListTables_j ($adSource) ; Parameter(s): $adSource - The full path/filename of the database to be listed ; $TipoTabla - 0 TABLE, 1 VIEW ; Requirements: ; Return Value(s): Success - Matriz con dos columnas: NOMBRE_TABLA y TIPO_TABLA ; Failure Sets @Error ; 1 = unable to create connection ; 3 = no matching tables located (returns a blankString) ; Author(s): George (GEOSoft) Gedye ; Notes: ; Modifications: 20120129 jamaro: Añadido parámetro $TipoTabla ; jamaro: Modificados los datos de salida ;=============================================================================== Func _accessListTables_j($adSource, $TipoTabla = 0) ; $TipoTabla=0 TABLE, 1 VIEW Local $oADO, $oRec Local $TipoTablaTxt If $TipoTabla = 0 Then $TipoTablaTxt = "TABLE" If $TipoTabla = 1 Then $TipoTablaTxt = "VIEW" Local $mList[2][1] ; 2 col 1 fil Local $ContadorDeTablas = 1 $oADO = 'ADODB.Connection' If IsObj($oADO) Then $oADO = ObjGet('', $oADO) Else $oADO = _dbOpen($adSource) EndIf If IsObj($oADO) = 0 Then Return SetError(1) $oRec = $oADO.OpenSchema(20) ; $adSchemaTables=20 While Not $oRec.EOF Select Case $TipoTabla = 0 Or $TipoTabla = 1 If $oRec("TABLE_TYPE").value <> $TipoTablaTxt Then ; Salta todo excepto $TipoTablaTxt $oRec.movenext ContinueLoop EndIf Case $TipoTabla = 2 ; No hace nada, admite TABLAS y VISTAS EndSelect If StringLeft($oRec("TABLE_NAME").value, 4) <> "Msys" Then ; Salta las tablas Msys ReDim $mList[$ContadorDeTablas][2] $mList[$ContadorDeTablas - 1][0] = $oRec("TABLE_NAME").value $mList[$ContadorDeTablas - 1][1] = $oRec("TABLE_TYPE").value $ContadorDeTablas = $ContadorDeTablas + 1 EndIf $oRec.movenext WEnd If $mList <> '' Then $oADO.close Return $mList Else SetError(3, 0, 0) $oADO.close Return $mList EndIf EndFunc ;==>_accessListTables_j ;=============================================================================== ; Function Name: __accessCampos() ----> Modificación de _accessListFields() de George (GEOSoft) ; Description: List the names of fields in an MS Access database table ; Syntax: __accessCampos($adSource, $adTable) ; Parameter(s): $adSource - The full path/filename of the database to be opened ; $adTable - the name of the table to check ; $contipo - 1 = Devuelve el tipo de datos del campo ; Requirements: ; Return Value(s): Success - A "|" delimited list of the field names. ; Failure Sets @Error ; 1 = unable to create connection ; 2 = unable to create recordset ; Author(s): George (GEOSoft) Gedye ; Notes: ; Modifications: 20120129 jamaro: Se añade el parámetro $contipo para que devuelva el tipo si es $contipo=1 ; jamaro: Añadido [] para nombres de tablas con espacios ; jamaro: Modificados los datos de salida ;=============================================================================== Func __accessCampos($adSource, $adTable, $contipo = 0) ; * Modifications Local $Fc Local $Rtn = '' $oADO = 'ADODB.Connection' If IsObj($oADO) Then $oADO = ObjGet('', $oADO) Else $oADO = _dbOpen($adSource) EndIf If IsObj($oADO) = 0 Then Return SetError(1) $oRec = _dbOpenRecordset();ObjCreate("ADODB.Recordset") If IsObj($oRec) = 0 Then Return SetError(2) $oRec.Open("[" & $adTable & "]", $oADO, 3, 3) ; 3=$adOpenStatic,3=$adLockOptimistic - Se añade [] para nombres de tablas con espacios $Fc = $oRec.fields.count If $Fc > 0 Then For $i = 0 To $Fc - 1 If $contipo = 1 Then $Rtn &= $oRec.fields($i).name & '|' & $oRec.fields($i).type & "|" ;_cw($oRec.fields($I).type) ; Muestra el tipo de datos del campo Else $Rtn &= $oRec.fields($i).name & '|' EndIf Next EndIf $oRec.Close $oADO.Close If $Rtn Then Return StringTrimRight($Rtn, 1) EndIf EndFunc ;==>__accessCampos ;=============================================================================== ; Function Name: _accessQueryLike_j() -> A partir de _accessQueryLike() por George (GEOSoft) Gedye ; Description: Searches a database for all records where the specified field contains a specified string ; Syntax: _accessQueryLike_j($adSource,$adTable, [$adFull]) ; Parameter(s): $adSource - The full path/filename of the database to be opened ; $adTable - the name of the table to search ; $adFull - If = 1 Returns an array containing a Chr(28) delimited list of the records field values. (Default) ; If <> 1 Returns an array of the specified field values for each record. ; Requirements: ; Return Value(s): Success - An Array containing records field values.(Default --- see $adFull above) ; Failure Sets @Error ; 1 = unable to create connection ; 2 = unable to create recordset ; Author(s): George (GEOSoft) Gedye ; Notes: ; Modifications: ;=============================================================================== Func _accessQueryLike_j($adSource, $adTable, $adFull = 1);, $adCol,$Find, $adFull = 1) Local $i, $Rtn $oADO = 'ADODB.Connection' If IsObj($oADO) Then $oADO = ObjGet('', $oADO) Else $oADO = _dbOpen($adSource) EndIf If IsObj($oADO) = 0 Then Return SetError(1) $oRec = _dbOpenRecordset();ObjCreate("ADODB.Recordset") If IsObj($oRec) = 0 Then Return SetError(2) $oRec.Open("SELECT * FROM " & $adTable, $oADO, 3, 3) ; 3=$adOpenStatic,3=$adLockOptimistic ;_m(">>>>>>>>>>>>>>>>>>>QUERY DE TABLA [" & $adTable & "]" & @CRLF & $oRec.GetString()) If $oRec.RecordCount < 1 Then Return SetError(1) Else SetError(0) Local $array = $oRec.GetRows($oRec.RecordCount, 1) ; Pasa a una matriz todos los registros seleccionados con $oRec.Open() ;_ArrayDisplay($array,@ScriptLineNumber) $oRec.Close() $oADO.Close() Return $array ; Devuelve matriz con los valores de los campos EndIf EndFunc ;==>_accessQueryLike_j ;=============================================================================== ; Function Name: _accessListPrimaryKeys() ; Description: Busca en una base de datos todas las Claves Primarias ; Syntax: _accessListPrimaryKeys($adSource) ; Parameter(s): $adSource - The full path/filename of the database to be opened ; Requirements: ; Return Value(s): Success - Matriz de dos columnas con NOMBRE_TABLA y CLAVE_PRIMARIA ; Failure Sets @Error ; 1 = unable to create connection ; 3 = no hay PrimaryKeys (devuelve una cadena vacía) ; Author(s): jamaro ; Notes: ; Modifications: ;=============================================================================== Func _accessListPrimaryKeys($adSource) Local $oRec1, $oEsquema_PK, $oEsquemaTablas Local $mList[2][1] ; 2 col 1 fil Local $ContadorDeTablas = 1 $oADO = 'ADODB.Connection' If IsObj($oADO) Then $oADO = ObjGet('', $oADO) Else $oADO = _dbOpen($adSource) EndIf If IsObj($oADO) = 0 Then Return SetError(1) $oEsquemaTablas = $oADO.OpenSchema(20) ; $adSchemaTables=20 While Not $oEsquemaTablas.EOF If $oEsquemaTablas("TABLE_TYPE").value <> "TABLE" Then ; Salta todo excepto TABLAS $oEsquemaTablas.movenext ContinueLoop EndIf $oRec1 = _dbOpenRecordset() ;ObjCreate("ADODB.Recordset") Local $adTable = $oEsquemaTablas("TABLE_NAME").value _cw($adTable) $oRec1.Open("[" & $adTable & "]", $oADO, 3, 3) ; 3=$adOpenStatic,3=$adLockOptimistic - Se añade [] para nombres de tablas con espacios $oEsquema_PK = $oADO.OpenSchema(28) ; $adSchemaPrimaryKeys=28 For $xx = 1 To 7 ;_cw("[" & $xx & "] " & $oEsquema_PK.fields($xx).name & @TAB & $oEsquema_PK.fields($xx).value) Next While Not $oEsquema_PK.EOF If $oEsquema_PK("TABLE_NAME").value = $adTable Then ; Sólo cuando coincide con el nombre de la tabla ReDim $mList[$ContadorDeTablas][2] $mList[$ContadorDeTablas - 1][0] = $oEsquemaTablas("TABLE_NAME").value $mList[$ContadorDeTablas - 1][1] = $oEsquema_PK("COLUMN_NAME").value $ContadorDeTablas = $ContadorDeTablas + 1 EndIf $oEsquema_PK.movenext WEnd $oEsquemaTablas.movenext WEnd If $mList <> '' Then $oADO.close Return $mList Else SetError(3, 0, 0) $oADO.close Return $mList EndIf EndFunc ;==>_accessListPrimaryKeys Func _accessListForeignKeys($adSource) Local $oRec Local $mList[2][1] ; 2 col 1 fil Local $ContadorDeTablas = 1 $oADO = 'ADODB.Connection' If IsObj($oADO) Then $oADO = ObjGet('', $oADO) Else $oADO = _dbOpen($adSource) EndIf If IsObj($oADO) = 0 Then Return SetError(1) ; unable to create connection $oRec = $oADO.OpenSchema(27) ; <<<<<<<<<<<<<<<<<<<<< http://www.w3schools.com/ado/met_conn_openschema.asp If IsObj($oRec) = 0 Then Return SetError(2) ; unable to open schema While Not $oRec.EOF ;MuestraDatos(17) ReDim $mList[$ContadorDeTablas][2] $mList[$ContadorDeTablas - 1][0] = $oRec.fields(8).value $mList[$ContadorDeTablas - 1][1] = "FOREIGN KEY ('" & $oRec.fields(9).value & "') REFERENCES [" & $oRec.fields(2).value & "](" & $oRec.fields(3).value & ")" & " ON UPDATE " & $oRec.fields(13).value & " ON DELETE " & $oRec.fields(14).value _cw("Foreign Keys en Tabla [" & $mList[$ContadorDeTablas - 1][0] & "] " & $mList[$ContadorDeTablas - 1][1]) $ContadorDeTablas = $ContadorDeTablas + 1 $oRec.movenext WEnd If $mList <> '' Then $oADO.close Return $mList Else SetError(3, 0, 0) $oADO.close Return $mList EndIf EndFunc ;==>_accessListForeignKeys #endregion Funciones lectura datos de archivos .mdb #region Funciones Inicio/Cierre SQLite Func InicioSQLite() _SQLite_Startup() ConsoleWrite("_SQLite_LibVersion=" & _SQLite_LibVersion() & @CR) _cw("Creando BD: " & $NombreBD) _SQLite_Open($NombreBD) ; No es necesario crear el archivo previamente ;~ _m("Código Error: " & _SQLite_ErrCode() & @CRLF & "Mensaje Error: " & _SQLite_ErrMsg()) If @error Then MsgBox(16, "SQLite Error (Linea " & @ScriptLineNumber & ")", "No se pudo crear la BD") Exit -1 EndIf EndFunc ;==>InicioSQLite Func CierraBD($NombreBD) _SQLite_Close($NombreBD) _SQLite_Shutdown() EndFunc ;==>CierraBD #endregion Funciones Inicio/Cierre SQLite #region Funciones auxiliares personalizadas ; Funciones _m y _cw para mostrar MsgBox y ConsoleWrite (en función del valor de $depuracíon) Func _m($msj = "", $a = @ScriptLineNumber) If $depuracion = 1 Then MsgBox(0, "Linea " & $a, $msj) EndFunc ;==>_m Func _cw($msj = "", $a = @ScriptLineNumber) If $depuracion = 1 Then ConsoleWrite("[L:" & $a & "] " & $msj & @CRLF) EndFunc ;==>_cw #endregion Funciones auxiliares personalizadas