Category Archives: SQL-tietokanta

Android SQL-tietokannan käyttäminen

Jatkona viimeviikon tiedon tallentamiselle toteuttakaamme SQLite-tietokanta Androidissa.

Yksinkertaisuuden vuoksi luomme vain yhden taulun sisältävän tietokannan. Tietokantaan talletetaan tuotteita, joilla on nimi, määrä sekä kuvaus. Tämän artikkelin liitteenä on esimerkki ohjelma, jossa tietokantaa voi kokeilla.

Product
product_name
product_count
product_description


Lataa esimerkin lähdekoodi.

Jatkamme SQLiteOpenHelper-luokkaa omalla toteutuksellamme ja luomme taulut onCreate-metodissa. Taulujen sarakkeiden nimet voi kätevästi tallettaa finaaleina muuttujina erillisiin sisäluokkiin, jotta ne on määritelty vain yhdessä paikassa ja selkeästi jäsenneltyinä.

Taulujen luonti tapahtuu samoilla SQL-komennoilla, kuin normaalin tietokannan luonnissa. Komentojen kirjoittaminen koodissa vain on hiukan eri näköistä, jos sen tekee StringBuilderilla. Create table-lauseen voi antaa myös suoraan stringinä.

private static final class ProductTable {
    public static final String PRODUCT_NAME = "product_name";
    public static final String PRODUCT_COUNT = "product_count";
    public static final String PRODUCT_DESCRIPTION = "product_description";
}
@Override
public void onCreate(SQLiteDatabase db) {
    StringBuilder sql = new StringBuilder();

    sql.append("CREATE TABLE ").append(PRODUCT_TABLE_NAME).append(" (");

    sql.append(ProductTable.PRODUCT_NAME).append(" TEXT,");
    sql.append(ProductTable.PRODUCT_COUNT).append(" INTEGER,");
    sql.append(ProductTable.PRODUCT_DESCRIPTION).append(" TEXT,");
    sql.append("PRIMARY KEY(").append(ProductTable.PRODUCT_NAME).append(")");
    sql.append(")");

    db.execSQL(sql.toString());
}

Tiedon tallentaminen tietokantaan

Tieto tallennetaan tietokantaan SQLiteDatabase-luokan instanssilla, joka saadaan SQLiteOpenHelper:ltä perityllä getWritableDatabase()-metodilla. Näin saatuun tietokantaolioon voi suorittaa kyselyitä tai lisäyksiä.

Lisättävät arvot on asetettava ContentValues-luokan ilmentymällä, joka pitää sisällään avain-arvo pareja, jossa avaimet ovat tietokannan sarakkeen nimiä ja arvo tietokantariville tulevan sarakkeen arvo. Jokaiselle tietokantariville täytyy luoda oma ContentValues-joukkonsa.

Hyvän ohjelmointitavan mukaista on, että tietokantametodit palauttavat boolean arvon riippuen onnistuiko metodi vai ei. Tietokantakyselyt luonnollisesti palauttavat kyselyn tuloksen.

boolean addProduct(Product product) {
    boolean result = true;
    SQLiteDatabase db = this.getWritableDatabase();

    ContentValues values;
    values = new ContentValues();
    values.put(ProductTable.PRODUCT_NAME, product.getName());
    values.put(ProductTable.PRODUCT_DESCRIPTION, product.getDescription());
    values.put(ProductTable.PRODUCT_COUNT, product.getQuantity());

    long id = db.insert(PRODUCT_TABLE_NAME, null, values);

    if(id == -1) {
        Log.e(TAG, "Could not add product");
        result = false;
    }
    return result;
}

Tiedon hakeminen tietokannasta

Tietokannan lukemiseen riittää vain lukemiseen tarkoitettu SQLiteDatabase-olio, jonka saa getReadableDatabase()-metodilla. Kyselyn voi toteuttaa yhteen tauluun query()-metodilla, joka tarvitsee useanlaisia parametrejä. Tietokantaan voi myös suorittaa kyselyitä rawQuery()-metodilla, mille voi argumenttinä antaa sql-kyselyn suoraan stringinä.

Metodeista saadaan paluuarvona Cursor-luokan ilmentymä. Kursori antaa pääsyn haettuun tietokantatauluun. Tässä esimerkissä käymme kursorin jokaisen rivin läpi ja otamme sarakkeiden tiedot getString()- ja getInt()-metodeilla, missä parametreinä on sarakkeen numero alkaen nollasta. Sarakkeet ovat samassa järjestyksessä, kuin kyselyssä annetussa argumentissä.

Kursori tulisi aina muistaa sulkea sen käyttämisen jälkeen.

List<Product> getProducts() {

    SQLiteDatabase db = this.getReadableDatabase();

    String[] colums = new String[] { ProductTable.PRODUCT_NAME, ProductTable.PRODUCT_COUNT, ProductTable.PRODUCT_DESCRIPTION };

    Cursor cursor = db.query(PRODUCT_TABLE_NAME, colums, null, null, ProductTable.PRODUCT_NAME, null, null);

    cursor.moveToFirst();

    List<Product> products = new ArrayList<Product>();
    while (cursor.isAfterLast() == false) {
        String name = cursor.getString(0);

        Log.v(TAG, "Found product: "+name);
        Product product = new Product(name);

        product.setDescription(cursor.getString(2));
        product.setQuantity(cursor.getInt(1));

        products.add(product);

        cursor.moveToNext();
    }
    cursor.close();
    return products;
}

Tiedon poistaminen

Tiedon poistaminen tietokannasta tapahtuu hyvin samalla tavalla, kuin lisääminen. Metodin onnistumisen seuraaminen onnistuu helpoiten, kun se palauttaa boolean arvon. SQLiteDatabase tarjoaa metodin delete(taulun_nimi, where_lause, where_parametrit), joka palauttaa poistettujen rivien lukumäärän.

boolean deleteProduct(Product product) {
    SQLiteDatabase db = this.getWritableDatabase();
    String[] params = new String[] { product.getName() };

    int numOfRows = db.delete(PRODUCT_TABLE_NAME, ProductTable.PRODUCT_NAME + " = ?", params);

    if (numOfRows >= 1) {
        return true;
    }
    return false;
}