SQLSQL 的带有子选择语句的 SQLite 列名称现在用 table 名称作为列名称的前缀

SQLite column names for SQL with subselect statements now prefix column name with table name

在 iOS 11 中,如果您将 sqlite3_column_name 和 SQL 与子选择语句一起使用,它现在 returns 带有 table 前缀的列名,而 iOS 10 没有。

例如考虑这个 SQL:

SELECT f.foo_value, b.bar_value
  FROM foo as f LEFT JOIN
    (SELECT * FROM bar) AS b ON f.foo_id = b.foo_id

如果您随后使用 sqlite3_column_name 检索列名称(请注意这是 Objective-C 片段,但这是 SQLite 问题,并非 Objective-C 独有或Swift):

const char *name1 = sqlite3_column_name(statement, 0);
const char *name2 = sqlite3_column_name(statement, 1);

NSLog(@"SQLite version: %s", sqlite3_version);
NSLog(@"name of column 0: %s", name1);
NSLog(@"name of column 1: %s", name2);

在 iOS 11.1 中,此报告:

SQLite version: 3.19.3
name of column 0: f.foo_value
name of column 1: b.bar_value

在 iOS 10.1 中,此报告:

SQLite version: 3.14.0
name of column 0: foo_value
name of column 1: bar_value

为什么?

顺便说一句,这个问题似乎只在 SQL 包含子选择语句时才会出现。

正如 SQLite documentation for sqlite3_column_name 所说:

The name of a result column is the value of the "AS" clause for that column, if there is an AS clause. If there is no AS clause then the name of the column is unspecified and may change from one release of SQLite to the next.

因此,如果您想将 sqlite3_column_name 的结果用于提供信息以外的任何用途,您确实应该在 SQL 中使用 AS 子句,例如

SELECT f.foo_value AS foo_value, b.bar_value AS bar_value
  FROM ...

As Gwendal Roué noted,这是 iOS11 附带的 SQLite 版本中引入的已知问题:

This change has been introduced in SQLite 3.19.0. It is present in SQLite 3.19.3 shipped with iOS 11. It has been reverted in SQLite 3.20.0.

For more information, see: