如何将 SQL COLLATE 运算符与 Android CursorLoader 一起使用
How to use SQL COLLATE operator with Android CursorLoader
我需要创建 CursorLoader,它将提取与名称和类型匹配的所有项目。更重要的是 name 必须忽略 Locale 特定的字母(重音)。例如,如果我提供查询:
item_name LIKE '%cafe%' COLLATE LOCALIZED
然后我需要提取名称包含 'cafe' 或 'café' 的所有项目。我不知道如何提供 COLLATE 运算符来像那样构建查询(没有普通的 SQL)。
return CursorLoader(
context,
someUri,
arrayOf(
PrompterTable.WORD_C,
PrompterTable.WORD_PLAIN_C,
PrompterTable.ENTRY_ID_C,
PrompterTable.CATEGORY_ID_C,
lengthClause,
PrompterTable.FAVOURITE_C
),
"item_name LIKE ? COLLATE LOCALIZED AND item_type IN (0, 1)",
arrayOf(myItemName),
"L" //alias given to lengthClause before
)
我确实将数据库区域设置为西班牙语,我还尝试了几种构建 WHERE 语句的方法:
"item_name LIKE ? COLLATE LOCALIZED AND item_type IN (0, 1)"
"(item_name LIKE ? COLLATE LOCALIZED) AND item_type IN (0, 1)"
"item_name LIKE ? AND item_type IN (0, 1) COLLATE LOCALIZED"
"item_name = ? AND item_type IN (0, 1) COLLATE LOCALIZED"
"item_name = ? COLLATE LOCALIZED AND item_type IN (0, 1)"
"(item_name = ? COLLATE LOCALIZED) AND item_type IN (0, 1)"
但它们中的每一个都无法按需要工作(仅找到 'cafe')。查询计算如下:
SELECT word, item_name, entryID, item_type, length(word) as L , favourite
FROM item_table
WHERE (item_name LIKE '%cafe%' COLLATE LOCALIZED AND item_type IN (0, 1))
GROUP BY word ORDER BY L LIMIT 25
我试图引用这个主题:Using COLLATE in Android SQLite - Locales is ignored in LIKE statement
但在我的情况下,即使使用“=”而不是 LIKE
也无法正常工作
我找到了答案,但这不是我所希望的。方便的 COLLATE LOCALIZED 在 Nougat 发布前后从 Android 中删除,并且没有以任何方式替换。
已知的解决方法是:
- 在编码中执行过滤(使用 Normalizer.normalize 或 Collator java 对象)
- 向过滤后的 table 添加额外的列,并使用规范化名称(无重音符号等)并将您的用户输入与此列进行比较
- 向 SQLite 数据库添加自定义 COLLATOR,这听起来很酷,但没有 Java API 这样做。您将不得不使用 Anroid NDK 并用 C++ 代码编写它。
如果你想得到详细的回答,我在租用中找到了这些:
https://discuss.zetetic.net/t/workaround-for-using-androids-localized-collator-after-3-5-0-update/1515/14
我需要创建 CursorLoader,它将提取与名称和类型匹配的所有项目。更重要的是 name 必须忽略 Locale 特定的字母(重音)。例如,如果我提供查询:
item_name LIKE '%cafe%' COLLATE LOCALIZED
然后我需要提取名称包含 'cafe' 或 'café' 的所有项目。我不知道如何提供 COLLATE 运算符来像那样构建查询(没有普通的 SQL)。
return CursorLoader(
context,
someUri,
arrayOf(
PrompterTable.WORD_C,
PrompterTable.WORD_PLAIN_C,
PrompterTable.ENTRY_ID_C,
PrompterTable.CATEGORY_ID_C,
lengthClause,
PrompterTable.FAVOURITE_C
),
"item_name LIKE ? COLLATE LOCALIZED AND item_type IN (0, 1)",
arrayOf(myItemName),
"L" //alias given to lengthClause before
)
我确实将数据库区域设置为西班牙语,我还尝试了几种构建 WHERE 语句的方法:
"item_name LIKE ? COLLATE LOCALIZED AND item_type IN (0, 1)"
"(item_name LIKE ? COLLATE LOCALIZED) AND item_type IN (0, 1)"
"item_name LIKE ? AND item_type IN (0, 1) COLLATE LOCALIZED"
"item_name = ? AND item_type IN (0, 1) COLLATE LOCALIZED"
"item_name = ? COLLATE LOCALIZED AND item_type IN (0, 1)"
"(item_name = ? COLLATE LOCALIZED) AND item_type IN (0, 1)"
但它们中的每一个都无法按需要工作(仅找到 'cafe')。查询计算如下:
SELECT word, item_name, entryID, item_type, length(word) as L , favourite
FROM item_table
WHERE (item_name LIKE '%cafe%' COLLATE LOCALIZED AND item_type IN (0, 1))
GROUP BY word ORDER BY L LIMIT 25
我试图引用这个主题:Using COLLATE in Android SQLite - Locales is ignored in LIKE statement
但在我的情况下,即使使用“=”而不是 LIKE
也无法正常工作我找到了答案,但这不是我所希望的。方便的 COLLATE LOCALIZED 在 Nougat 发布前后从 Android 中删除,并且没有以任何方式替换。
已知的解决方法是:
- 在编码中执行过滤(使用 Normalizer.normalize 或 Collator java 对象)
- 向过滤后的 table 添加额外的列,并使用规范化名称(无重音符号等)并将您的用户输入与此列进行比较
- 向 SQLite 数据库添加自定义 COLLATOR,这听起来很酷,但没有 Java API 这样做。您将不得不使用 Anroid NDK 并用 C++ 代码编写它。
如果你想得到详细的回答,我在租用中找到了这些: https://discuss.zetetic.net/t/workaround-for-using-androids-localized-collator-after-3-5-0-update/1515/14