【问题标题】:SQLite Query containing Path failing on iPhone包含路径的 SQLite 查询在 iPhone 上失败
【发布时间】:2016-04-26 19:29:06
【问题描述】:

我已尝试使用准备好的语句和常规语句来使用长 iPhone 模拟器路径从我的表中检索记录。

我根本无法让使用 WHERE 语句中的字段 Path 的 SELECT 语句工作。如果我删除 WHERE 语句,它会返回记录。

例如

Last Added[/Users/admin/Library/Developer/CoreSimulator/Devices/1546523B-D9E4-45F6-9ACA-ADA5CF73DFE4/data/Containers/Data/Application/9187662E-16F3-4573-B486-256BDA00CBD1/Documents/wf_mages-3.lha]

SQL[SELECT ID FROM Tune  WHERE Path="/Users/admin/Library/Developer/CoreSimulator/Devices/1546523B-D9E4-45F6-9ACA-ADA5CF73DFE4/data/Containers/Data/Application/9187662E-16F3-4573-B486-256BDA00CBD1/Documents/wf_mages-3.lha"]

我在查询中尝试了双引号和单引号。我什至在 SQLiteBrowser 中尝试过相同的查询,效果很好。

SELECT ID FROM Tune WHERE Path LIKE '%mages%' 工作正常。

是正斜杠的问题还是路径值的大小有问题?是否需要以某种方式转义正斜杠?

我能找到的唯一一篇关于正斜杠的帖子建议使用准备好的语句,但这就是我最初的开始,它们不起作用。查找在我的表中的任何其他字段上都可以正常工作 - 只是路径不行。

int GetTuneIDWithPath( char *pszPath )
{
  // TEST
  char   txTmp   [ 1024 ];

  sprintf( g_txSQL, "SELECT %s", fldTune_ID );

  sprintf( txTmp, " FROM %s ", tbTune );
  strcat( g_txSQL, txTmp );

  //sprintf( txTmp, " WHERE %s=\"%s\"", fldTune_Path, pszPath );
  //strcat( g_txSQL, txTmp );

//  sprintf( txTmp, " WHERE %s='%s'", fldTune_Path, pszPath );
  //strcat( g_txSQL, txTmp );

  //sprintf( txTmp, " WHERE %s LIKE '%%mages%%'", fldTune_Path );
  //strcat( g_txSQL, txTmp );

  LogDebugf( "SQL[%s]", g_txSQL );

  char  *zErrMsg = 0;
  char **pszResult;
  int    nRows;
  int    nCols;
  int    rc;

  rc = sqlite3_get_table_wrapper( g_MainDB,
                                 g_txSQL,
                                 &pszResult,
                                 &nRows,
                                 &nCols,
                                 &zErrMsg );

  if( nRows != 1 )
  {
    LogDebugf( "FAILED nRows: %d", nRows );
    return FALSE;
  }

  // First row is field names, so start at 1
  int nCol = 0;
  int nID = Safe_atoi(    pszResult[ nCols + nCol ] );  nCol ++;

  LogDebugf( "PDS> nID: %d Find[%s]", nID, pszPath );  
  return nID;
}

在此之前,我确实尝试过使用准备好的语句,就像我对其他查询所做的那样:

  char   txTmp   [ 1024 ];

  sprintf( g_txSQL, "SELECT %s", fldTune_ID );    
  sprintf( txTmp, " FROM %s WHERE %s=?", tbTune, fldTune_Path );
  strcat( g_txSQL, txTmp );

  sqlite3_stmt *stmt = NULL;  
  sqlite3_prepare( g_MainDB, g_txSQL, -1, &stmt, NULL );
  sqlite3_reset( stmt );
  sqlite3_bind_text( stmt,  1, pszPath, strlen( pszPath ), SQLITE_STATIC );

  rc = sqlite3_step( stmt );

  if( rc != SQLITE_ROW ) 
  {
    LogDebugf( "PDS> Lookup failed [%s] rc: %d", pszPath, rc );
    return FALSE;
  }

  int nID = sqlite3_column_int( stmt, 0 );

  LogDebugf( "PDS> nID: %d Find[%s]", nID, pszPath );

【问题讨论】:

  • @CL - 添加了一些代码。

标签: iphone sqlite ios-simulator


【解决方案1】:

你需要忽略文件的实际位置,只记录和搜索应用文档目录内的文件,所以你需要存储/搜索'wf_mages-3.lha'而不是'/Users/admin/Library/Developer/CoreSimulator/Devices/1546523B-D9E4-45F6-9ACA-ADA5CF73DFE4/data/Containers/Data/Application/9187662E-16F3-4573-B486-256BDA00CBD1/Documents/wf_mages-3.lha'。

只有在实际读取/写入文件时,您才需要预先添加文档路径,您可以通过 NSSearchPathForDirectoriesInDomains() 获得。

原因是在应用更新期间位置会发生变化,文档目录内容会迁移但数据库行不会迁移,您将失去两者之间的连接。

在语句中使用'/'应该没有问题,因为就SQL而言它并不特殊,因此应该可以在documents文件夹中创建层次结构而没有问题。

要评论您的代码,我以前从未见过这种方法,我会提倡更传统的sqlite3_prepare()、sqlite3_step() 和sqlite3_finalize() 函数。此外,最关键的是,您需要使用sqlite3_errmsg() 报告任何错误,否则您将毫无进展。

【讨论】:

  • 谢谢 - 使用文档目录的要点。我意识到我不需要存储整个内容,但为了测试此功能,它仍然无法解释为什么我可以存储大长路径但不能对大长路径名称执行 SELECT。我还应该指出,我正在写入表格,然后立即选择 - 这两个操作之间没有重新启动应用程序或模拟器。这只是向我的应用程序添加了一个查询 - 它总共有大约 50 个查询,比这更复杂,它们都可以工作。这里错过了一些愚蠢的事情。
  • @SparkyNZ 我会从更传统的功能开始,然后从那里开始。
猜你喜欢
  • 1970-01-01
  • 2013-10-04
  • 2018-08-31
  • 2014-10-02
  • 2018-12-17
  • 2018-08-14
  • 1970-01-01
  • 1970-01-01
  • 2021-09-23
相关资源
最近更新 更多