⌘+k ctrl+k
1.4 (LTS)
搜索快捷键 cmd + k | ctrl + k
Swift 客户端

DuckDB 提供了一个 Swift 客户端。详情请参阅发布公告

实例化 DuckDB

DuckDB 同时支持内存数据库和持久化数据库。要使用内存数据库,请运行

let database = try Database(store: .inMemory)

要使用持久化数据库,请运行

let database = try Database(store: .file(at: "test.db"))

可以通过数据库连接执行查询。

let connection = try database.connect()

DuckDB 支持每个数据库建立多个连接。

应用示例

本页面的其余部分基于我们发布公告中的示例,该示例使用了直接加载到 DuckDB 中的 NASA 系外行星数据库 (NASA's Exoplanet Archive) 的原始数据。

创建应用特定类型

我们首先创建一个应用特定的类型,用于存放我们的数据库和连接,并最终通过它定义我们的应用专用查询。

import DuckDB

final class ExoplanetStore {

  let database: Database
  let connection: Connection

  init(database: Database, connection: Connection) {
    self.database = database
    self.connection = connection
  }
}

加载 CSV 文件

我们从 NASA 系外行星数据库加载数据

wget https://exoplanetarchive.ipac.caltech.edu/TAP/sync?query=select+pl_name+,+disc_year+from+pscomppars&format=csv -O downloaded_exoplanets.csv

一旦我们在本地下载了 CSV 文件,就可以使用以下 SQL 命令将其作为新表加载到 DuckDB 中

CREATE TABLE exoplanets AS
    SELECT * FROM read_csv('downloaded_exoplanets.csv');

让我们将其封装为 ExoplanetStore 类型上的一个新的异步工厂方法

import DuckDB
import Foundation

final class ExoplanetStore {

  // Factory method to create and prepare a new ExoplanetStore
  static func create() async throws -> ExoplanetStore {

  // Create our database and connection as described above
    let database = try Database(store: .inMemory)
    let connection = try database.connect()

  // Download the CSV from the exoplanet archive
  let (csvFileURL, _) = try await URLSession.shared.download(
    from: URL(string: "https://exoplanetarchive.ipac.caltech.edu/TAP/sync?query=select+pl_name+,+disc_year+from+pscomppars&format=csv")!)

  // Issue our first query to DuckDB
  try connection.execute("""
      CREATE TABLE exoplanets AS
          SELECT * FROM read_csv('\(csvFileURL.path)');
  """)

  // Create our pre-populated ExoplanetStore instance
    return ExoplanetStore(
    database: database,
      connection: connection
  )
  }

  // Let's make the initializer we defined previously
  // private. This prevents anyone accidentally instantiating
  // the store without having pre-loaded our Exoplanet CSV
  // into the database
  private init(database: Database, connection: Connection) {
  ...
  }
}

查询数据库

以下示例通过异步函数在 Swift 中查询 DuckDB。这意味着在执行查询时,调用者不会被阻塞。我们将使用 DuckDB 的 ResultSet cast(to:) 系列方法将结果列转换为 Swift 原生类型,最后将其封装在来自 TabularData 框架的 DataFrame 中。

...

import TabularData

extension ExoplanetStore {

  // Retrieves the number of exoplanets discovered by year
  func groupedByDiscoveryYear() async throws -> DataFrame {

  // Issue the query we described above
    let result = try connection.query("""
      SELECT disc_year, count(disc_year) AS Count
        FROM exoplanets
        GROUP BY disc_year
        ORDER BY disc_year
      """)

    // Cast our DuckDB columns to their native Swift
    // equivalent types
    let discoveryYearColumn = result[0].cast(to: Int.self)
    let countColumn = result[1].cast(to: Int.self)

    // Use our DuckDB columns to instantiate TabularData
    // columns and populate a TabularData DataFrame
    return DataFrame(columns: [
      TabularData.Column(discoveryYearColumn).eraseToAnyColumn(),
      TabularData.Column(countColumn).eraseToAnyColumn(),
    ])
  }
}

完整项目

如需获取完整示例项目,请克隆 DuckDB Swift 仓库 并打开位于 Examples/SwiftUI/ExoplanetExplorer.xcodeproj 的可运行应用程序项目。

© 2025 DuckDB 基金会,阿姆斯特丹,荷兰
行为准则 商标使用指南