Android'de SQlite'de hazırlanmış ifadeleri nasıl kullanırım?


100

Android'de SQlite'de hazırlanmış ifadeleri nasıl kullanırım?


9
Kabul edilen cevabı değiştirmeyi düşünün.
Suragch

9
kabul edildi - cevabı değiştirmeyi düşünün ... sürü zihniyeti, daha iyi bir çözüm mevcut olduğunda, kabul edilen cevabı kaldırdı.
goodguys_activate

4
Pablo, lütfen kabul edilen cevabı değiştir ... verilen örnek işe yaramıyor bile. Ve olumsuz oylarımız onu çözmek için yeterli değil.
SparK

Yanıtlar:


21

Android'de her zaman hazırlanmış ifadeler kullanıyorum, oldukça basit:

SQLiteDatabase db = dbHelper.getWritableDatabase();
SQLiteStatement stmt = db.compileStatement("INSERT INTO Country (code) VALUES (?)");
stmt.bindString(1, "US");
stmt.executeInsert();

81
Bu cevabın nasıl bu kadar çok oy alabileceğini bilmiyorum. SQLIteStatement # execute Sql sorguları için değil, sadece ifadeler için kullanılmalıdır. Lütfen developer.android.com/reference/android/database/sqlite/…
adresini

9
Öyleyse, verileri sorgulamak için hazırlanmış bir ifadeyi nasıl kullanacaksınız?
Juan Mendes

12
SQLiteStatement.bindXXX()En çok olduğu gibi 0 tabanlı değil, 1 tabanlı bir dizine sahip olduğuna dikkat edin.
Simulant

6
@jasonhudgins Neden SELECT'inizi INSERT ile değiştirmiyorsunuz? Sadece gelen bu yeni başlayan karıştı ettik iplik,
Keyser

35
Tamamen yanlış olan bir yanıtı destekleyen ve kabul eden sürü zihniyetine mükemmel bir örnek

165

Android'de hazırlanan SQLite deyimleri için SQLiteStatement vardır . Hazırlanan ifadeler performansı hızlandırmanıza yardımcı olur (özellikle birden çok kez yürütülmesi gereken ifadeler için) ve ayrıca enjeksiyon saldırılarına karşı önlemeye yardımcı olur. Hazırlanmış ifadeler hakkında genel bir tartışma için bu makaleye bakın .

SQLiteStatementbirden çok değer döndürmeyen SQL ifadeleriyle kullanılması amaçlanmıştır. (Bu, çoğu sorgu için onları kullanmayacağınız anlamına gelir.) Aşağıda bazı örnekler verilmiştir:

Tablo oluştur

String sql = "CREATE TABLE table_name (column_1 INTEGER PRIMARY KEY, column_2 TEXT)";
SQLiteStatement stmt = db.compileStatement(sql);
stmt.execute();

execute()CREATE ve bırak ile kullanmak için uygun olan, ancak DELETE SELECT, INSERT ile kullanılması amaçlanan ve UPDATE bu değerleri, çünkü böylece yöntemi bir değer döndürmez. (Ama bu soruya bakın .)

Değerleri ekle

String sql = "INSERT INTO table_name (column_1, column_2) VALUES (57, 'hello')";
SQLiteStatement statement = db.compileStatement(sql);
long rowId = statement.executeInsert();

executeInsert()Yöntemin yerine kullanıldığını unutmayın execute(). Elbette, her satıra her zaman aynı şeyleri girmek istemezsiniz. Bunun için bağlamaları kullanabilirsiniz .

String sql = "INSERT INTO table_name (column_1, column_2) VALUES (?, ?)";
SQLiteStatement statement = db.compileStatement(sql);

int intValue = 57;
String stringValue = "hello";

statement.bindLong(1, intValue); // 1-based: matches first '?' in sql string
statement.bindString(2, stringValue);  // matches second '?' in sql string

long rowId = statement.executeInsert();

Genellikle bir şeyi (INSERT gibi) birçok kez hızlıca tekrarlamak istediğinizde hazırlanmış ifadeleri kullanırsınız. Hazırlanan ifade, SQL ifadesinin her seferinde ayrıştırılması ve derlenmesi gerekmemesini sağlar. İşlemleri kullanarak işleri daha da hızlandırabilirsiniz . Bu, tüm değişikliklerin aynı anda uygulanmasına izin verir. İşte bir örnek:

String stringValue = "hello";
try {

    db.beginTransaction();
    String sql = "INSERT INTO table_name (column_1, column_2) VALUES (?, ?)";
    SQLiteStatement statement = db.compileStatement(sql);

    for (int i = 0; i < 1000; i++) {
        statement.clearBindings();
        statement.bindLong(1, i);
        statement.bindString(2, stringValue + i);
        statement.executeInsert();
    }

    db.setTransactionSuccessful(); // This commits the transaction if there were no exceptions

} catch (Exception e) {
    Log.w("Exception:", e);
} finally {
    db.endTransaction();
}

İşlemler ve veri tabanı girişlerini hızlandırmak hakkında daha iyi bilgiler için bu bağlantılara göz atın.

Satırları güncelle

Bu temel bir örnektir. Yukarıdaki bölümdeki kavramları da uygulayabilirsiniz.

String sql = "UPDATE table_name SET column_2=? WHERE column_1=?";
SQLiteStatement statement = db.compileStatement(sql);

int id = 7;
String stringValue = "hi there";

statement.bindString(1, stringValue);
statement.bindLong(2, id);

int numberOfRowsAffected = statement.executeUpdateDelete();

Satırları sil

executeUpdateDelete()Yöntem ayrıca, DELETE tablolar için de kullanılabilir ve API 11'de tanıtılan See Bu soru-cevap .

İşte bir örnek.

try {

    db.beginTransaction();
    String sql = "DELETE FROM " + table_name +
            " WHERE " + column_1 + " = ?";
    SQLiteStatement statement = db.compileStatement(sql);

    for (Long id : words) {
        statement.clearBindings();
        statement.bindLong(1, id);
        statement.executeUpdateDelete();
    }

    db.setTransactionSuccessful();

} catch (SQLException e) {
    Log.w("Exception:", e);
} finally {
    db.endTransaction();
}

Sorgu

Normalde bir sorgu çalıştırdığınızda, çok sayıda satır içeren bir imleci geri almak istersiniz. Yine de bunun SQLiteStatementiçin değil . Veritabanındaki satır sayısı gibi yalnızca basit bir sonuca ihtiyacınız olmadığı sürece onunla bir sorgu çalıştırmazsınız.simpleQueryForLong()

String sql = "SELECT COUNT(*) FROM table_name";
SQLiteStatement statement = db.compileStatement(sql);
long result = statement.simpleQueryForLong();

Genellikle bir imleç almak için SQLiteDatabasequery() yöntemini çalıştırırsınız .

SQLiteDatabase db = dbHelper.getReadableDatabase();
String table = "table_name";
String[] columnsToReturn = { "column_1", "column_2" };
String selection = "column_1 =?";
String[] selectionArgs = { someValue }; // matched to "?" in selection
Cursor dbCursor = db.query(table, columnsToReturn, selection, selectionArgs, null, null, null);

Sorgular hakkında daha ayrıntılı bilgi için bu yanıta bakın .


5
Bir hatırlatma: .bindString / .bindLong / ... yöntemlerinin tümü 1 tabanlıdır.
Denys Vitali

.Query, .insert ve .delete gibi Android kolaylık yöntemlerine bakıyordum ve başlık altında SQLiteStatement kullandıklarını fark ettim. Kendi ifadelerinizi oluşturmak yerine sadece kolaylık yöntemlerini kullanmak daha kolay olmaz mıydı?
Nicolás Carrasco

@ NicolásCarrasco, bunun üzerinde çalışmayalı uzun zaman oldu, bu yüzden şimdi biraz paslandım. Sorgular ve tekli eklemeler, güncellemeler ve silmeler için kesinlikle uygunluk yöntemlerini kullanırdım. Ancak, toplu ekleme, güncelleme veya silme işlemi yapıyorsanız, bir işlemle birlikte hazırlanmış ifadeleri dikkate alırım. Başlık altında kullanılan SQLiteStatement ve kolaylık yöntemlerinin yeterince iyi olup olmadığına gelince, bununla konuşamıyorum. Sanırım şunu söyleyebilirim, eğer kolaylık yöntemleri sizin için yeterince hızlı çalışıyorsa, o zaman kullanın.
Suragch

ClearBindings () neden kullanıyorsunuz? Tüm değerlerinizi koşulsuz bağlarsınız. Önce onları boş ve gerçek değere ayarlamak bana mantıklı gelmiyor.
inanılmaz

@TheincredibleJan, emin değilim. Gerekli olmayabilir ve bir fark yaratıp yaratmadığını görmek için bağları temizlemeden deneyebilirsiniz. Bununla birlikte, bu, çağırmanın clearBindings()yalnızca onları ayarlamadığını söyledi null( kaynak koduna bakın ). Ben buna durumu temizliyor olarak bakıyorum, böylece önceki döngüden hiçbir şey onu etkilemiyor. Belki de bu gerekli değildir. Yorum yapmayı bilen biri için mutlu olurum.
Suragch

22

Dönüşte bir imleç istiyorsanız, bunun gibi bir şey düşünebilirsiniz:

SQLiteDatabase db = dbHelper.getWritableDatabase();

public Cursor fetchByCountryCode(String strCountryCode)
{
    /**
     * SELECT * FROM Country
     *      WHERE code = US
     */
    return cursor = db.query(true, 
        "Country",                        /**< Table name. */
        null,                             /**< All the fields that you want the 
                                                cursor to contain; null means all.*/
        "code=?",                         /**< WHERE statement without the WHERE clause. */
        new String[] { strCountryCode },    /**< Selection arguments. */
        null, null, null, null);
}

/** Fill a cursor with the results. */
Cursor c = fetchByCountryCode("US");

/** Retrieve data from the fields. */
String strCountryCode = c.getString(cursor.getColumnIndex("code"));

/** Assuming that you have a field/column with the name "country_name" */
String strCountryName = c.getString(cursor.getColumnIndex("country_name"));

Daha eksiksiz bir tane istiyorsanız, bu pasaj Genscripts'e bakın . Bunun parametreleştirilmiş bir SQL sorgusu olduğuna dikkat edin, bu nedenle özünde hazırlanmış bir ifadedir.


Yukarıdaki kodda küçük hata: "new String {strCountryCode}" yerine "new String [] {strCountryCode}" olmalıdır.
Pierre-Luc Simard

Verileri alabilmeniz için önce imleci hareket ettirmeniz gerekir
Chin

9

jasonhudgins örneği işe yaramayacak. İle bir sorgu çalıştırıp bir stmt.execute()değer (veya a Cursor) geri alamazsınız .

Yalnızca hiç satır döndürmeyen (bir ekleme veya tablo deyimi oluşturma gibi) veya tek bir satır ve sütun (ve simpleQueryForLong()veya kullanın simpleQueryForString()) ifadelerini önceden derleyebilirsiniz .


1

İmleç almak için compiledStatement kullanamazsınız. Bununla birlikte, tam hazırlanmış bir SQL ifadesi kullanmak istiyorsanız, jbaez yönteminin bir uyarlamasını öneririm ... db.rawQuery()yerine db.query().

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.