如何处理iOS SQLite中的重音字符?
我需要执行对大小写和重音不敏感的SELECT查询。出于演示目的,我创建了如下表:如何处理iOS SQLite中的重音字符?,ios,sqlite,cultureinfo,diacritics,Ios,Sqlite,Cultureinfo,Diacritics,我需要执行对大小写和重音不敏感的SELECT查询。出于演示目的,我创建了如下表: create table table ( column text collate nocase ); insert into table values ('A'); insert into table values ('a'); insert into table values ('Á'); insert into table values ('á'); create index table_cloumn_
create table table
(
column text collate nocase
);
insert into table values ('A');
insert into table values ('a');
insert into table values ('Á');
insert into table values ('á');
create index table_cloumn_Index
on table (column collate nocase);
> A
> a
> Á
> á
然后,我在执行以下查询时得到这些结果:
SELECT * FROM table WHERE column LIKE 'a';
> A
> a
SELECT * FROM table WHERE column LIKE 'á';
> á
SELECT * FROM table WHERE column LIKE 'Á';
> Á
我如何解决这个问题,使以下任何查询的结果都是这样的:
create table table
(
column text collate nocase
);
insert into table values ('A');
insert into table values ('a');
insert into table values ('Á');
insert into table values ('á');
create index table_cloumn_Index
on table (column collate nocase);
> A
> a
> Á
> á
顺便说一下,sqlite是在iOS上运行的
提前感谢,两种基本方法:
NSData *data = [string dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
您还可以将重音字符替换为:
NSMutableString *mutableString = [string mutableCopy];
CFStringTransform((__bridge CFMutableStringRef)mutableString, NULL, kCFStringTransformStripCombiningMarks, NO);
顺便说一句,如果您需要对结果进行排序,您还可以在此二级搜索字段而不是主字段上进行排序,这将避免由于SQLite无法对国际字符进行排序而导致的问题@实现
之外定义此C函数):
然后,您可以定义一个SQLite函数,该函数将调用此C函数(在打开数据库后调用此方法,该方法在关闭该数据库之前有效):
完成此操作后,您现在可以在SQL中使用此新的uncented
函数,例如:
if (sqlite3_prepare_v2(database, "select a from table where unaccented(column) like 'a'", -1, &statement, NULL) != SQLITE_OK)
NSLog(@"%s: insert 1: %s", __FUNCTION__, sqlite3_errmsg(database));
LIKE
运算符不支持非ASCII大小写不敏感:
SQLite只能通过以下方式理解ASCII字符的大写/小写
违约对于unicode,LIKE运算符默认区分大小写
超出ASCII范围的字符。例如
像“a”一样的“a”是真的,但像“Æ”一样的“æ”是假的
这是有道理的,否则sqlite将需要支持不同的区域性,因为情况因人而异。一个例子是。将所有这些区域性信息嵌入sqlite将是非常麻烦的(也就是说,这将增加sqlite目标代码)。下面是我对类似问题的解决方案
static void myLow(sqlite3_context *context, int argc, sqlite3_value **argv)
{
NSString* str = [[NSString alloc] initWithUTF8String:
(const char *)sqlite3_value_text(argv[0])];
const char* s = [[str lowercaseString] UTF8String];
sqlite3_result_text(context, s, strlen(s), NULL);
[str release];
}
// call it once after opening db
sqlite3_create_function(_db, "myLow", 1, SQLITE_UTF8,NULL, &myLow, NULL, NULL);
然后代替查询
SELECT * FROM table WHERE column LIKE 'a'
你应该使用
SELECT * FROM table WHERE myLow(column) LIKE 'a'
您是否已经在iOS上创建了任何用户函数?你有关于这个的示例代码吗?这似乎是更正确的方法。是的,我也在使用这种方法,但现在我需要处理一个我无法改变其结构的数据库。但如果可以的话,而且你的db不是太大,这是一个简单的方法。@LeandroAlves我知道你早就解决了这个问题,但我(a)包括了另一个不一致字符串的变体;和(b)向您展示如何动态地在SQLite中创建非关联字符串。@Rob选项2的代码执行并正确处理数据,但需要占用99%的CPU和>1000 MB的内存。操作完成后,应用程序立即崩溃,执行错误访问(代码=2,地址=0x0)。有什么办法可以用这段代码来控制内存使用吗?@ChrisSchiffhauer这需要一些讨论,所以我为这个后续问题创建了一个聊天室:@ChrisSchiffhauer通过在许多记录上进行此更新而产生的内存问题可以通过引入
@autoreleasepool
来解决。见修改后的答案。