Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何处理iOS SQLite中的重音字符?_Ios_Sqlite_Cultureinfo_Diacritics - Fatal编程技术网

如何处理iOS SQLite中的重音字符?

如何处理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_

我需要执行对大小写和重音不敏感的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_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无法对国际字符进行排序而导致的问题

  • 您也可以创建自己的“uncented”C函数(在类的
    @实现
    之外定义此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));
    
  • 您将需要或重写(即替换)的默认实现。原因是sqlite中的
    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
    来解决。见修改后的答案。