Androidアプリケーションのデータベース開発でselectionArgsとwhereArgsを使うのはなぜですか?

4567 ワード

Androidの開発では、非常に軽量なアプリケーションを除いて、基本的にデータベースにデータを格納する必要があります.
Androidに付属しているデータベースシステムはSQLiteです.しかし、SQL文は、他の構造化データベースシステム(MySQL、MSSQLなど)で使用されているものとあまり変わりません.
SQL文を実行する必要がある場合は、SQLiteDatabaseクラスの参照を持ち、対応するメソッドを呼び出す必要があります.
rawQueryメソッドとexecSQLメソッドは、純粋なSQL文を実行するために使用され、前者は戻りデータを指すCursorを返すことができ、後者は主に戻りデータのないSQL文を実行するために使用され、戻り値voidのメソッドです.この2つの方法に加えて、Androidはinsert、query、delete、updateなどの方法をパッケージ化し、開発者がSQL文を手動で接続する必要がないようにしています.
これらのメソッドの一般的な宣言は次のとおりです.
Cursor rawQuery(String sql, String[] selectionArgs)

void execSQL(String sql)

long insert(String table, String nullColumnHack, ContentValues values)

Cursor query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)

int delete(String table, String whereClause, String[] whereArgs)

int update(String table, ContentValues values, String whereClause, String[] whereArgs)


ほとんどのメソッドに文字列配列タイプのパラメータXXXXArgsが必要であることがわかります.
もちろん、このパラメータはnullであってもよいが、selectionまたはwhereClauseに完全なSQL条件文が含まれている限り.しかし、Androidが私たちにArgsを単独でカプセル化してくれた以上、それはきっと私たちに利益があるのではないでしょうか.
そこで考えてみると、id(Integer)、name(Text)、isGraduated(Integer)というデータテーブルsampleがあります.
このときdeleteのエントリの1つを、idが233、nameがtestNameのエントリと仮定すると、純粋なSQL文は次のようになります.
DELETE FROM sample WHERE id=233 AND name='testName'

deleteメソッドを呼び出しargsパラメータを使用しない場合は、次のようになります.
SQLiteDatabase db;
String table = "sample";
int id = 233;
String name = "testName";
int row = db.delete(table, "id=" + id + " AND name='" + name + "'", null);

ああ、このnameの等号には引用符が付いていて、まぶしいですね.
ではargsパラメータを使用すると、コードはどのように長くなりますか?
SQLiteDatabase db;
String table = "sample";
String[] args = new String[]{"233", "testName"};
int row = db.delete(table, "id=? AND name=?", args);

まぶしい引用符が消去され、このコードの論理も正常に動作します.
では、なぜargsを使った後、単一引用符を追加する必要がないのでしょうか.
この疑問を解決するために、私はまずSQLiteDataBaseクラスのargsパラメータを用いたメソッドソースコードを一歩一歩深く深く掘り下げ、javaソースレベルでwhereClaauseとwhereArgsを統合する方法を見つけて、実際に呼び出された純粋なSQL文がどのようなものかを知りたいと思っています.しかし、しばらく探してみると、この2つのパラメータはjavaレベルで統合されていないので、この方向は得られません.
では、グーグルで関連資料を検索してみると、意外にもブログWhat’s good about selectionArgs in SQLite queriesが見つかりました.SQLiteデータベースは他のSQLデータベースとは異なり、強いタイプのデータベースではありません.where文で文字列で比較すると、ヘッダーフィールドがどんなデータ型であっても、等号の右側には、単一引用符で囲まれた文字列があり、正しく一致します.SQLiteデータベースでは、文字列タイプは元のデータ型(例、文字列「1」はInteger型の1に戻すことができ、同じ文字列「-1」もInteger型の-1に戻すことができる)に無損に移行できるため、比較時にSQLiteデータベースは文字列をヘッダ項目が属するデータ型に変換して比較し、正しい比較結果を得ることができる.
この解釈によると、argsを使用したときのSQL文は実は次のようになっています.
DELETE FROM sample WHERE id='233' AND name='testName'

数字233も一重引用符で文字列に包まれている.
上記の学習によると、argsのメリットには2つの点が明らかになった.
  • 文字列は、ヘッダーのデータ型を気にすることなく、吐き気を催して手動でつなぎ合わせる.
  • プレースホルダを使用した文は、より短く読みやすい.

  • この2つの利点は、私が使用しているデータベース文をargsパラメータ方式に置き換えることを説得するのに十分だと思います.
    argsパラメータの利点を説明した後、注意点についてお話しします.
  • プレースホルダ疑問符は、等号の右側、すなわち「?=?」にのみ使用できます.このプレースホルダは不正です.
  • argsのバインドは、実際には、その中のargを単一引用符で囲んで、元の文の対応するプレースホルダ
  • を置き換えることである.
    2点目について、もう少し詳しくお話しします.最初はargsパラメータの使い方を理解していなかったとき、SQLのIN文を使う必要があったとき、私もバカでした.
    //   
    String whereClause = "id IN ?";
    String[] whereArgs = new String[]{"(1,2,3)"};
    

    または、
    //   
    String whereClause = "id IN (?)";
    String[] whereArgs = new String[]{"1,2,3"};
    

    では、このようにして、あれはどのように文法の間違い/一致していないクエリーの結果を提示しますか?データベースにあるのに?
    それは実は2点目を理解してから分かるのですが、実はこのときのSQL文は次のように対応しています.
    //      SQL  
    ... id IN '(1,2,3)'...
    
    //      SQL  
    ... id IN ('1,2,3')...
    

    それは明らかに用法の対応するSQL文に文法の間違いがある.使用法2に対応するSQL文は、idが文字列'1,2,3'であることを検索しますが、idの値が数字の場合、一致するエントリは返されません.
    しかし、私たちの本意のSQL文は次のとおりです.
    //   SQL  
    ... id IN (1,2,3)...
    

    その1/2/3がパラメータである場合、argsで置き換えるには、次のようにします.
    //  args      SQL  
    ... id IN ('1','2','3')...
    

    これにより、正確なクエリー結果が得られます.
    では、2つ目の注意点に基づいて、このSQL文をargsでバインドすると、これが正しい使い方になります.
    //     
    String whereClause = "id IN (?,?,?)";
    String[] whereArgs = new String[]{"1","2","3"};
    

    このように使うと、クエリの結果が正常であることがわかります.
    以上、私が最近データベースに関するロジックを書いたときに学んだことですが、本稿をご覧になった皆さん、開発時に行けるカーブを減らし、開発効率を向上させていただきたいと思います.ありがとうございます.
    疑問や見解があれば、討論に返事することを歓迎します.
    参考文献:
  • What’s good about selectionArgs in SQLite queries
  • Datatypes In SQLite Version 3