# Cómo abrir o crear una base de datos SQLite

> Abrir/crear un archivo .db con try-with-resources, usar base de datos en memoria y crear tablas.

Source: https://crossfly.dev/es/docs/cookbook/data/abrir-banco — CrossFly documentation. Full docs as one file: https://crossfly.dev/llms-full.txt

# Cómo abrir o crear una base de datos SQLite

**Propósito.** Abrir (o crear, si no existe) una base de datos SQLite y crear sus tablas. En CrossFly la puerta de entrada es `SqliteDb`, un handle `AutoCloseable` — usa siempre `try (...)` para garantizar el cierre de la conexión nativa.

## APIs usadas
- `SqliteDb.open(String filename)` — abre/crea una base de datos **no cifrada** en read/write (`OPEN_DEFAULT = OPEN_READWRITE | OPEN_CREATE`). Retorna un `SqliteDb`.
- `SqliteDb.openMemory()` — abre una base de datos **en memoria** (`:memory:`), volátil: desaparece al cerrar. Ideal para pruebas y cachés temporales.
- `SqliteDb.exec(String sql)` — ejecuta una o más instrucciones **sin resultado** (DDL, PRAGMA, DML en lote). Úsalo para `CREATE TABLE`, `CREATE INDEX`, `PRAGMA ...`. Lanza `SqliteException` en caso de error.
- `SqliteDb.close()` — cierra la conexión nativa. **Idempotente** (llamarlo dos veces es seguro). El `try-with-resources` lo llama automáticamente.
- `SqliteDb.version()` — retorna la cadena de versión de la biblioteca SQLite (útil para diagnóstico).

> **Ruta del archivo.** Pasa una ruta de archivo escribible (por plataforma). No uses `Gdx.graphics` para nada aquí; SQLite es independiente de la UI. Para la ubicación de archivos por plataforma, consulta la guía de storage.

## Ejemplo completo (copiar, pegar y ejecutar)

```java
package com.exemplo;

import dev.crossfly.ui.*;                     // Window
import dev.crossfly.ui.layout.*;             // VerticalLayout
import dev.crossfly.sqlite.*;                // SqliteDb, SqliteException

/** Pantalla principal ejecutable. Apunta el launcher (classname) y corre: gradlew :lwjgl3:run */
public class MainWindow extends Window
{
   @Override
   public void onShow() throws Exception
   {
      super.onShow();
      setLayout(new VerticalLayout());

      // 1) Base de datos en archivo (creada si no existe)
      try (SqliteDb db = SqliteDb.open("app.db"))
      {
         db.exec(
            "CREATE TABLE IF NOT EXISTS person(" +
            "  id   INTEGER PRIMARY KEY," +
            "  name TEXT NOT NULL," +
            "  age  INTEGER)");
         // ... usa la base de datos aquí ...
      }
      // conexión ya cerrada al salir del try

      // 2) Base de datos en memoria (volátil) — buena para pruebas
      try (SqliteDb mem = SqliteDb.openMemory())
      {
         mem.exec("CREATE TABLE t(id INTEGER PRIMARY KEY, v TEXT)");
         // ... vive solo mientras 'mem' esté abierto ...
      }
   }
}
```

> El fragmento de abajo muestra **solo el núcleo**. Para ejecutarlo, colócalo en el esqueleto `MainWindow` de arriba.

## Fragmento mínimo
```java
// verificado en la fuente: SqliteDb.open / openMemory / exec
import dev.crossfly.sqlite.*;

// 1) Base de datos en archivo (creada si no existe)
try (SqliteDb db = SqliteDb.open("app.db"))
{
   db.exec(
      "CREATE TABLE IF NOT EXISTS person(" +
      "  id   INTEGER PRIMARY KEY," +
      "  name TEXT NOT NULL," +
      "  age  INTEGER)");
   // ... usa la base de datos aquí ...
}
// conexión ya cerrada al salir del try

// 2) Base de datos en memoria (volátil) — buena para pruebas
try (SqliteDb mem = SqliteDb.openMemory())
{
   mem.exec("CREATE TABLE t(id INTEGER PRIMARY KEY, v TEXT)");
   // ... vive solo mientras 'mem' esté abierto ...
}
```

## Profundiza
- [Guía de storage SQLite](/docs/data-and-services/storage-sqlite) · Guía de desarrollo
- Recetas hermanas: [CRUD parametrizado](/docs/cookbook/data/crud) · [Base de datos cifrada](/docs/cookbook/data/banco-criptografado) · [Uso fuera de la paint thread](/docs/cookbook/data/banco-fora-da-paint-thread)
