ধারা এবং স্থানধারীদের মধ্যে


104

আমি Android এর মধ্যে নিম্নলিখিত এসকিউএল কোয়েরিটি করার চেষ্টা করছি:

    String names = "'name1', 'name2";   // in the code this is dynamically generated

    String query = "SELECT * FROM table WHERE name IN (?)";
    Cursor cursor = mDb.rawQuery(query, new String[]{names});

তবে, অ্যান্ড্রয়েড প্রশ্ন চিহ্নটি সঠিক মানগুলির সাথে প্রতিস্থাপন করে না। আমি নিম্নলিখিতগুলি করতে পারি, তবে এটি এসকিউএল ইঞ্জেকশন থেকে রক্ষা করে না:

    String query = "SELECT * FROM table WHERE name IN (" + names + ")";
    Cursor cursor = mDb.rawQuery(query, null);

আমি কীভাবে এই সমস্যাটি পেতে পারি এবং আইএন ক্লজটি ব্যবহার করতে সক্ষম হতে পারি?

উত্তর:


188

ফর্মটির একটি স্ট্রিং "?, ?, ..., ?"একটি গতিশীলভাবে তৈরি স্ট্রিং হতে পারে এবং নিরাপদে মূল এসকিউএল কোয়েরিতে রাখা যেতে পারে (কারণ এটি একটি সীমাবদ্ধ ফর্ম যা বাহ্যিক ডেটা ধারণ করে না) এবং তারপরে স্থানধারকরা স্বাভাবিক হিসাবে ব্যবহার করা যেতে পারে।

একটি ফাংশন বিবেচনা করুন String makePlaceholders(int len)যা lenকমা দিয়ে পৃথক করা প্রশ্ন-চিহ্নগুলি দেয়, তারপরে:

String[] names = { "name1", "name2" }; // do whatever is needed first
String query = "SELECT * FROM table"
    + " WHERE name IN (" + makePlaceholders(names.length) + ")";
Cursor cursor = mDb.rawQuery(query, names);

ঠিক জায়গাগুলির মতো অনেকগুলি মান পাস করার বিষয়টি নিশ্চিত করুন। এসকিউএলাইটে হোস্ট প্যারামিটারগুলির ডিফল্ট সর্বাধিক সীমা 999 - কমপক্ষে একটি সাধারণ বিল্ডে, অ্যান্ড্রয়েড সম্পর্কে নিশ্চিত নয় :)

শুভ কোডিং।


এখানে একটি বাস্তবায়ন:

String makePlaceholders(int len) {
    if (len < 1) {
        // It will lead to an invalid query anyway ..
        throw new RuntimeException("No placeholders");
    } else {
        StringBuilder sb = new StringBuilder(len * 2 - 1);
        sb.append("?");
        for (int i = 1; i < len; i++) {
            sb.append(",?");
        }
        return sb.toString();
    }
}

8
হ্যাঁ, এসকিউএলাইটে প্যারামিটারাইজড IN () ক্যোয়ারী এবং অন্য কোনও এসকিউএল ডাটাবেস ব্যবহারের একমাত্র উপায় (এটি)।
ল্যারি লাস্টিগ

এই পদ্ধতিটি ব্যবহার করে, আমি আমার ব্যবহৃত কন্টেন্টপ্রাইডার সংযোজন করেছি এবং ক্যোয়ারী () পদ্ধতিতে উপস্থিতির জন্য পরীক্ষার জন্য যুক্তি যুক্ত করেছি: "IN?" এবং যদি পাওয়া যায় তবে "" "এর উপস্থিতি গণনা করে? মূল নির্বাচনের সাথে, যুক্তিগুলির দৈর্ঘ্যের সাথে তুলনা করে একটি "?,?, ... একত্রিত হয়?" পার্থক্যের জন্য এবং মূল "IN" কে প্রতিস্থাপন করে? উত্পন্ন প্রশ্ন চিহ্ন সংগ্রহ সহ। এটি যুক্তিটিকে প্রায় বিশ্বব্যাপী উপলব্ধ করে তোলে এবং আমার ব্যবহারগুলির জন্য এটি ভালভাবে কাজ করছে বলে মনে হয়। খালি আইএন তালিকাগুলি ফিল্টার করার জন্য আমাকে কিছু বিশেষ বিধান যুক্ত করতে হয়েছিল, এই ক্ষেত্রে, "আইএন"? আপাতত "1" দিয়ে প্রতিস্থাপিত হয়েছে।
SandWyrm

3
এটি সম্পর্কে মূর্খ বিষয়টি অবশ্যই হ'ল আপনি যদি এন স্ট্রিংগুলিকে এন প্রশ্ন চিহ্ন দিয়ে তৈরি করতে চলেছেন তবে আপনি কেবল ডেটা সরাসরি এনকোড করতে পারেন। ধরে নিলাম এটি স্যানিটাইজড।
ক্রিস্টোফার

16
এই makePlaceholdersপুরোটি দিয়ে প্রতিস্থাপন করা যেতে পারে TextUtils.join(",", Collections.nCopies(len, "?"))। কম ভার্বোস।
কনরাড মোরাউস্কি

1
Caused by: android.database.sqlite.SQLiteException: near ",": syntax error (code 1): , while compiling: SELECT url FROM tasks WHERE url=?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?
ইমান মারাশী

9

সংক্ষিপ্ত উদাহরণ, ব্যবহারকারীর উত্তরের উপর ভিত্তি করে 166390:

public Cursor selectRowsByCodes(String[] codes) {
    try {
        SQLiteDatabase db = getReadableDatabase();
        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();

        String[] sqlSelect = {COLUMN_NAME_ID, COLUMN_NAME_CODE, COLUMN_NAME_NAME, COLUMN_NAME_PURPOSE, COLUMN_NAME_STATUS};
        String sqlTables = "Enumbers";

        qb.setTables(sqlTables);

        Cursor c = qb.query(db, sqlSelect, COLUMN_NAME_CODE+" IN (" +
                        TextUtils.join(",", Collections.nCopies(codes.length, "?")) +
                        ")", codes,
                null, null, null); 
        c.moveToFirst();
        return c;
    } catch (Exception e) {
        Log.e(this.getClass().getCanonicalName(), e.getMessage() + e.getStackTrace().toString());
    }
    return null;
}

5

দুঃখজনকভাবে এটি করার কোনও উপায় নেই (স্পষ্টতই 'name1', 'name2'একটি মান নয় এবং তাই প্রস্তুত বিবৃতিতে ব্যবহার করা যাবে না)।

সুতরাং আপনাকে আপনার দর্শনীয় স্থানগুলি WHERE name IN (?, ?, ?)হ্রাস করতে হবে (উদাহরণস্বরূপ খুব সুনির্দিষ্ট, পুনরায় ব্যবহারযোগ্য প্রশ্নগুলির মতো নয় ) বা সঞ্চিত পদ্ধতি ব্যবহার না করে এবং এসকিউএল ইঞ্জেকশনগুলিকে অন্য কোনও কৌশল দিয়ে প্রতিরোধ করার চেষ্টা করবেন ...


4
আপনি আসলে, একটি সামান্য কাজ দিয়ে, ক্যোয়ারীটি প্যারামিটারাইজড তৈরি করতে পারেন। পিএসটির উত্তর নীচে দেখুন। ফলাফলের ক্যোয়ারীটি প্যারামিটারাইজড এবং ইঞ্জেকশন-নিরাপদ।
ল্যারি লাস্টিগ

@ ল্যারিলাস্টিগ কোন উত্তরটি আপনি "পিএসটি'র উত্তর দিয়ে উল্লেখ করছেন? এটি মুছে ফেলা হয়েছে? এটি এখানে pst এর একমাত্র উপস্থিতি বলে মনে হচ্ছে ...
স্টিফান হস্টেইন

1
@ স্টেফানহাউস্টাইন "পিএসএসের উত্তর " (ব্যবহারকারী সরানো হয়েছে)
ব্যবহারকারীর 15157124

5

হিসাবে গৃহীত উত্তরের পরামর্শ হিসাবে কিন্তু কমা-বিচ্ছিন্ন '?' উত্পন্ন করতে কাস্টম ফাংশন ব্যবহার না করে। নীচে কোড চেক করুন।

String[] names = { "name1", "name2" }; // do whatever is needed first
String query = "SELECT * FROM table"
    + " WHERE name IN (" + TextUtils.join(",", Collections.nCopies(names.length, "?"))  + ")";
Cursor cursor = mDb.rawQuery(query, names);

1

আপনি TextUtils.join(",", parameters)স্ক্লাইট বাইন্ডিং পরামিতিগুলির সুবিধা নিতে ব্যবহার করতে পারেন, যেখানে স্থানধারীদের parametersসাথে একটি তালিকা রয়েছে "?"এবং ফলাফলের স্ট্রিং এমন কিছু"?,?,..,?"

এখানে একটি ছোট উদাহরণ:

Set<Integer> positionsSet = membersListCursorAdapter.getCurrentCheckedPosition();
List<String> ids = new ArrayList<>();
List<String> parameters = new ArrayList<>();
for (Integer position : positionsSet) {
    ids.add(String.valueOf(membersListCursorAdapter.getItemId(position)));
    parameters.add("?");
}
getActivity().getContentResolver().delete(
    SharedUserTable.CONTENT_URI,
    SharedUserTable._ID + " in (" + TextUtils.join(",", parameters) + ")",
    ids.toArray(new String[ids.size()])
);

"পরামিতিগুলির" একটিতে যদি নালার প্রয়োজন হয় তবে কী হবে?
অ্যান্ড্রয়েড বিকাশকারী

0

প্রকৃতপক্ষে আপনি অ্যান্ড্রয়েডের স্থানীয়ভাবে কাঁচা প্রশ্নের পরিবর্তে কোয়েরি করার পদ্ধতি ব্যবহার করতে পারেন:

public int updateContactsByServerIds(ArrayList<Integer> serverIds, final long groupId) {
    final int serverIdsCount = serverIds.size()-1; // 0 for one and only id, -1 if empty list
    final StringBuilder ids = new StringBuilder("");
    if (serverIdsCount>0) // ambiguous "if" but -1 leads to endless cycle
        for (int i = 0; i < serverIdsCount; i++)
            ids.append(String.valueOf(serverIds.get(i))).append(",");
    // add last (or one and only) id without comma
    ids.append(String.valueOf(serverIds.get(serverIdsCount))); //-1 throws exception
    // remove last comma
    Log.i(this,"whereIdsList: "+ids);
    final String whereClause = Tables.Contacts.USER_ID + " IN ("+ids+")";

    final ContentValues args = new ContentValues();
    args.put(Tables.Contacts.GROUP_ID, groupId);

    int numberOfRowsAffected = 0;
    SQLiteDatabase db = dbAdapter.getWritableDatabase());
        try {
            numberOfRowsAffected = db.update(Tables.Contacts.TABLE_NAME, args, whereClause, null);
        } catch (Exception e) {
            e.printStackTrace();
        }
        dbAdapter.closeWritableDB();


    Log.d(TAG, "updateContactsByServerIds() numberOfRowsAffected: " + numberOfRowsAffected);

    return numberOfRowsAffected;
}

0

এটি বৈধ নয়

String subQuery = "SELECT _id FROM tnl_partofspeech where part_of_speech = 'noun'";
Cursor cursor = SQLDataBase.rawQuery(
                "SELECT * FROM table_main where part_of_speech_id IN (" +
                        "?" +
                        ")",
                new String[]{subQuery}););

এটি বৈধ

String subQuery = "SELECT _id FROM tbl_partofspeech where part_of_speech = 'noun'";
Cursor cursor = SQLDataBase.rawQuery(
                "SELECT * FROM table_main where part_of_speech_id IN (" +
                        subQuery +
                        ")",
                null);

ContentResolver ব্যবহার করা হচ্ছে

String subQuery = "SELECT _id FROM tbl_partofspeech where part_of_speech = 'noun' ";

final String[] selectionArgs = new String[]{"1","2"};
final String selection = "_id IN ( ?,? )) AND part_of_speech_id IN (( " + subQuery + ") ";
SQLiteDatabase SQLDataBase = DataBaseManage.getReadableDatabase(this);

SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
queryBuilder.setTables("tableName");

Cursor cursor =  queryBuilder.query(SQLDataBase, null, selection, selectionArgs, null,
        null, null);


0

আমি এর জন্য Streamএপিআই ব্যবহার করি :

final String[] args = Stream.of("some","data","for","args").toArray(String[]::new);
final String placeholders = Stream.generate(() -> "?").limit(args.length).collect(Collectors.joining(","));
final String selection = String.format("SELECT * FROM table WHERE name IN(%s)", placeholders);

db.rawQuery(selection, args);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.