-2

宿題として、ユーザーがカレンダーの予定作成アプリの「タイトル」フィールドに同じ文字列値を入力するのを止めようとしています。

これが私がこれまでに考えたことです:

private static String[] CHECK = {TITLE};
    private Cursor addAppointment(String title, String time, String details){
        calendarData = new CalendarData(this);
        SQLiteDatabase db1 = calendarData.getReadableDatabase();
        SQLiteDatabase db = calendarData.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(DATE, calendar.getDate());
        values.put(TITLE, title);
        values.put(TIME, time);     
        values.put(DETAILS, details);
        db.insertOrThrow(TABLE_NAME, null, values);
        Cursor titleCursor = db1.query(TABLE_NAME, CHECK, TITLE+" = "+appointmentTitle.getText().toString(), null, null, null, null);
        if(titleCursor.getString(0) != null){//MEANING THERE IS A DUPLICATE
            final AlertDialog alertDialog = new AlertDialog.Builder(this).create();
            alertDialog.setMessage("You've entered a duplicate title field, please rename.");
            alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
                  public void onClick(DialogInterface dialog, int which) {

                   alertDialog.dismiss();

                } });
            alertDialog.show();
        }
        return titleCursor;
    }

しかし、addAppointments メソッドにすべてを含めるという考えは好きではありません。クリーンでシンプルなままにしておくほうがよいでしょう。

代わりに次のことを試しました。

private static String[] CHECK = {TITLE};
    private void addAppointment(String title, String time, String details){
        calendarData = new CalendarData(this);
        SQLiteDatabase db1 = calendarData.getReadableDatabase();
        SQLiteDatabase db = calendarData.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(DATE, calendar.getDate());
        values.put(TITLE, title);
        values.put(TIME, time);     
        values.put(DETAILS, details);
        db.insertOrThrow(TABLE_NAME, null, values);
    }

    private Cursor checkTitle(){
        calendarData = new CalendarData(this);
        SQLiteDatabase db1 = calendarData.getReadableDatabase();

        Cursor titleCursor = db1.query(TABLE_NAME, CHECK, TITLE+" = "+appointmentTitle.getText().toString(), null, null, null, null);

        startManagingCursor(titleCursor);
        return titleCursor;
    }

    private void showTitleError(Cursor cursor){
        if(cursor.getString(0) != null){//MEANING THERE IS A DUPLICATE
            final AlertDialog alertDialog = new AlertDialog.Builder(this).create();
            alertDialog.setMessage("You've entered a duplicate title field, please rename.");
            alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
                  public void onClick(DialogInterface dialog, int which) {

                   alertDialog.dismiss();

                } });
            alertDialog.show();
        }
    }

しかし、両方のケースでこのエラーが発生します: 04-24 17:56:51.263: E/AndroidRuntime(17856): android.database.sqlite.SQLiteException: no such column: hello: 、コンパイル中: SELECT title FROM 予定 WHERE title =こんにちは

アドバイスがあれば共有してください、ありがとう。

4

2 に答える 2

3

インジェクションセーフが必要な場合は、そのように使用してください

Cursor titleCursor = db1.query(TABLE_NAME, CHECK, TITLE+" = ?",
        new String[]{ appointmentTitle.getText().toString() }, null, null, null);

これは、次の引数から引用符で囲まれたエスケープされたデータ?に置き換えられます。'

ヒント: 一意のタイトルを強制する場合は、データベースの列を作成しますUNIQUE。そうすれば、既に存在するタイトルを持つデータをSQLiteExceptionいつでも取得できます。insert期待する代わりに、列UNIQUE ON CONFLICT IGNOREを作成することもできます。これは、単にデータを挿入せず、エラーをスローしないことを意味します。

于 2012-04-24T18:07:33.360 に答える
1

appointmentTitle.getText().toString()一重引用符で囲む必要があります。

db1.query(TABLE_NAME, CHECK, TITLE+" = '"+appointmentTitle.getText().toString() + "'", null, null, null, null);

そうすれば、組み立てられたクエリは次のようになります。

SELECT title FROM appointments WHERE title = 'hello'

ただし、他の投稿者が丁寧に指摘しているように、ここでクエリがユーザー入力を受け取ると、SQL インジェクションの問題が発生する可能性があります。パラメーター化されたアプローチに適応することは、より良い方法です。

于 2012-04-24T18:01:14.643 に答える