2010-12-28 14 views
7

Uso un ContentProvider per parlare con il database della mia applicazione e sto riscontrando un piccolo problema.Modo elegante di eseguire query non elaborate complesse utilizzando ContentProvider

Ho una query leggermente complicata. Sembra qualcosa di simile:

String sql = 
    "select " + 
    " tblHistory._id _id, " + 
    " tblHistory.item item, " + 
    " tblHistory.updated_on updated_on, " + 
    " (select _id from tblList " + 
     "where tblList.item = tblHistory.item) list_id, " + 
    " 1 priority, " + 
    "from " + 
    " tblHistory " + 
    "where " + 
    " tblHistory.status <> 'STATE_DELETING' and " + selection + " " + 
    "union " + 
    "select " + 
    " tblSearch._id _id, " + 
    " tblSearch.item item, " + 
    " -1 updated_on, " + 
    " (select _id from tblList " + 
     "where tblList.item = tblSearch.product_name) list_id, " + 
    " 2 priority, " + 
    "from " + 
    " tblSearch " + 
    "where " + 
    " not exists (select * from tblHistory " + 
     "where tblHistory.item = tblSearch.product_name) " + 
    "order by " + 
    " priority, _id asc"; 

    c = mDb.rawQuery(sql, null); 

selezione è:

String where = "tblHistory.user_id=" 
       + Integer.toString(intUserId) 
       + " and tblHistory.item like '%" 
       + strSearch + "%'"; 

Il mio problema è il mio sub-query. Ho un vincolo che devo aggiungere, ma non è un buon modo per ottenere questo vincolo dal pipe al metodo. Ho bisogno di usare l'user_id corretto nelle sottoquery.

A questo punto, penso di avere 2 opzioni:

1) analizzare la user_id sottostringa dalla selezione.

2) Utilizzare selectionArgs come un hack per passare "user_id = " + Integer.toString(intUserId) al metodo.

Altre idee?

Devo notare che mentre preferirei non fare nulla hack-ish, ho reso il mio privato ContentProvider così come è destinato a essere utilizzato solo dalla mia applicazione; quindi se devo assolutamente, posso.

+1

Fatevi un favore e l'uso ' "" + intUserId' invece di' Integer.toString (intUserId) '. : p –

+0

Vedere http://stackoverflow.com/a/6548733/633187. Questo risponde alla tua domanda? – jcwenger

+1

Andrew, per espandere il commento di Alex (questo è un po 'fuori tema e non affronta il tuo problema reale): Il modo più efficiente di convertire ints in stringhe in Java è l'utilizzo di Integer.toString, ma se hai intenzione di concatenare il risultato con una stringa, è sufficiente scrivere: String where = "tblHistory.user_id =" + intUserId + "e tblHistory.item come"% "+ strSearch +"% ""; –

risposta

2

quando si tratta di query complesse come questa, una classe builder può tornare utile. Evita di doverli convertire in String, spero che questo ti aiuti.

public class SqlQueryBuilder { 

private static final String SELECT = "SELECT"; 

private static final String COMA = " , "; 

private static final String WHERE = " where "; 

private static final String EQUALS = " = "; 

private static final String NOT_EQUALS = " != "; 

private static final String FROM = " FROM "; 

private final StringBuilder mStrBuilder = new StringBuilder(); 

public void init() { 
    mStrBuilder.setLength(0); 
} 

public SqlQueryBuilder select(Object ...columns) { 
    mStrBuilder.append(SELECT); 
    for(Object column:columns) { 
     mStrBuilder.append(column); 
     mStrBuilder.append(COMA); 
    } 
    return this; 
} 

public SqlQueryBuilder where(Object conditionVar) { 
    mStrBuilder.append(WHERE); 
    mStrBuilder.append(conditionVar); 
    return this; 
} 


public SqlQueryBuilder equalsVal(Object equalsVal) { 
    mStrBuilder.append(EQUALS); 
    mStrBuilder.append(equalsVal); 
    return this; 
} 

public SqlQueryBuilder notEqualsVal(Object notEqualsVal) { 
    mStrBuilder.append(NOT_EQUALS); 
    mStrBuilder.append(notEqualsVal); 
    return this; 
} 

public SqlQueryBuilder from(Object from) { 
    mStrBuilder.append(FROM); 
    mStrBuilder.append(from); 
    return this; 
} 

public String build() { 
    final String sqlQuery = mStrBuilder.toString(); 
    init(); 
    return sqlQuery; 
} 

}

utilizzo è come qui di seguito

{ 

    SqlQueryBuilder sqlQueryBuilder = new SqlQueryBuilder(); 

    String innerQuery = sqlQueryBuilder.select("_id").from("tblList") 
      .where("tblList.item").equalsVal("tblHistory.item").build(); 

    String query = sqlQueryBuilder.select("tblHistory._id _id", 
      "tblHistory.item", "tblHistory.updated_on updated_on", 
      innerQuery + " list_id", "1 priority").build(); 

} 
Problemi correlati