ios设备和sqlite3命令行的sqlite区别

Posted

技术标签:

【中文标题】ios设备和sqlite3命令行的sqlite区别【英文标题】:Sqlite differences between ios device and sqlite3 command line 【发布时间】:2014-01-13 18:13:46 【问题描述】:

我很好奇我在使用 ios 模拟器/设备和 Mac OSX 附带的 sqlite3 命令行应用程序时遇到的差异。

在另一台机器(我的 Windows 机器)上,我用一个文本文件创建了一个 sqlite 数据库。这是 SQLite 文件的创建语句。

CREATE TABLE IF NOT EXISTS GeocodeData (ZipCode TEXT, City TEXT COLLATE NOCASE, State TEXT COLLATE NOCASE, Latitude REAL, Longitude REAL, PRIMARY KEY(ZipCode, City, State) ON CONFLICT INGORE);

我正在使用COLLATE NOCASE,因为我发现on this SO question 进行不区分大小写的搜索。

当我将数据库移动到我的 Mac 时,在终端中运行 sqlite3 应用程序,我可以运行以下查询: SELECT * FROM GeocodeData WHERE City = 'elyria' AND State = 'oh'.

44035|Elyria|OH|41.3724|-82.1051
44036|Elyria|OH|41.4015|-82.0771

运行此语句会从我的数据库中返回 2 个结果。太棒了。

转到我正在创建的 iPad 应用程序,我正在使用 FMDatabase 包装对 Sqlite 数据库的访问。

这是访问它的代码。

+(CLLocationCoordinate2D)getCoordinateForFilter:(GeocodingFilter *)filter

    __block CLLocationCoordinate2D coordinate;
    FMDatabaseQueue *queue = [self databaseQueue];
    [queue inDatabase:^(FMDatabase *db)
    
        //Determine if we're using zipcode or city/state.
        NSMutableString *query = [[NSMutableString alloc] initWithString:SELECT_STATEMENT];
        NSMutableDictionary *params = [NSMutableDictionary dictionary];
        if(![NSString isNilOrWhitespace:filter.zipCode])//Zipcode logic
        
            [query appendFormat:WHERE_CLAUSE, @"ZipCode = :zipCode "];
            params[@"zipCode"] = filter.zipCode;
        
        else
        
            NSString *clause = nil;
            if(![NSString isNilOrWhitespace:filter.city])
            
                clause = [NSString stringWithFormat:WHERE_CLAUSE, @"City = :city"];
                params[@"city"] = filter.city;
            
            if (![NSString isNilOrWhitespace:filter.state])
            
                if(clause)
                    clause = [NSString stringWithFormat:@"%@ AND", clause];
                clause = [NSString stringWithFormat:@"%@ State = :state", clause];
                params[@"state"] = filter.state;
            
            [query appendString:clause];
        
        FMResultSet *set = [db executeQuery:query withParameterDictionary:params];
        NSMutableArray *results = [NSMutableArray array];
        while ([set next])
        
            double latitude = [set doubleForColumn:@"Latitude"];
            double longitude = [set doubleForColumn:@"Longitude"];
            [results addObject:[[CLLocation alloc] initWithLatitude:latitude longitude:longitude]];
        

        [set close];
        [db close];

        __block double avgLat = 0.;
        __block double avgLong = 0.;
        [results enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) 
            CLLocation *loc = obj;
            avgLat += loc.coordinate.latitude;
            avgLong += loc.coordinate.longitude;
        ];

        coordinate = CLLocationCoordinate2DMake(avgLat/(double)results.count, avgLong/(double)results.count);
    ];

    return coordinate;

这运行与我在 sqlite3 命令行中使用的完全相同的查询,但每次都返回 0 个结果。

现在,我可以通过更改这 4 行代码来解决此问题。

clause = [NSString stringWithFormat:WHERE_CLAUSE, @"City LIKE :city"];
params[@"city"] = [NSString stringWithFormat:@"%%%@%%", filter.city];

clause = [NSString stringWithFormat:@"%@ State LIKE :state", clause];
params[@"state"] = [NSString stringWithFormat:@"%%%@%%", filter.state];

但我明确创建了表以在 create 语句中使用 COLLATE NOCASE。为什么这不起作用?

编辑:显然我需要重新提出这个问题。问题是不是LIKE 查询!

我想知道为什么这个查询:SELECT * FROM GeocodeData WHERE City = 'elyria' AND State = 'oh' 在命令行上返回 2 个结果,而在带有 FMDatabase 的 iOS 环境中运行 THIS EXACT SAME QUERY 返回 0 个结果。

【问题讨论】:

您阅读过 sqlite.org 上的文档吗? 我不确定阅读文档会给我带来什么。我已经展示了一个案例,其中 sqlite3 命令行(版本 3.7.13)返回一组结果,然后在 iOS 7 上的设备上运行(运行完全相同的版本,从这个答案得到,***.com/questions/14288128/… ),给我一个空的结果。我唯一可以假设的是两者在实现上存在差异,我想这就是我要问的。为什么这些完全相同的版本与完全相同的查询之间存在差异? 所以你记住了this? 我不确定你是否明白我在问什么。我明白为什么LIKE 是我的解决方案。这是一个关于数据库所在环境的问题。为什么我在 iOS 上的查询给出的结果与在命令行上的不同?它在完全相同的数据库上执行完全相同的查询,运行完全相同版本的 sqlite。 使用相同的编译指示? 【参考方案1】:

我承认 SQLite 文档在某些地方组织得很差,但对于一个开源项目来说,它的准确度和精确度已经达到了人们所希望的水平。

查阅文档表明您不应该遇到您所描述的问题,最终得出的结论是某些事情与您所描述的不完全一样。

【讨论】:

优雅!哈。感谢您的帮助。

以上是关于ios设备和sqlite3命令行的sqlite区别的主要内容,如果未能解决你的问题,请参考以下文章

IOS 开发学习33 使用sqlite3

如何使用ROWID编辑Python SQLite3中特定行的内容

Android安卓 “adb控件android+sqlite3”

转iOS开发24:使用SQLite3存储和读取数据

如何使用 ROWID 在 Python SQLite3 中编辑特定行的内容

sqlite3常用命令以及django如何操作sqlite3数据库