Documentation

使用参数化查询与SQL

InfluxDB Cloud Serverless中的参数化查询允许您动态安全地更改查询中的值。 如果您的应用代码允许用户输入以自定义查询中的值或表达式,请使用参数化查询,以确保不受信任的输入严格作为数据处理,而不是作为代码执行。

参数化查询:

  • 帮助防止注入攻击,这可能发生在输入被作为代码执行时
  • 帮助使查询更具可重用性

防止注入攻击

有关安全性和查询参数化的更多信息,请参阅 OWASP SQL Injection Prevention Cheat Sheet

在 InfluxDB 3 中,参数化查询是一个包含一个或多个命名参数占位符的 InfluxQL 或 SQL 查询——这些占位符是代表输入数据的变量。

仅在 WHERE 表达式中支持的参数

InfluxDB 3 支持 WHERE 子句 谓词表达式 中的参数。参数值必须是允许的参数数据类型之一。

如果您在其他表达式或子句中使用参数,例如函数参数、 SELECTGROUP BY,则您的查询可能无法按预期工作。

WHERE 表达式中使用参数

您可以在 WHERE 子句 谓词表达式 中使用参数——例如,以下查询包含一个 $temp 参数:

SELECT * FROM measurement WHERE temp > $temp

在执行查询时,您指定参数名称-值对。
您赋值给参数的值必须是参数数据类型之一。

{"temp": 22.0}

InfluxDB 查询器解析带有参数占位符的查询文本,然后生成查询计划,将占位符替换为您提供的值。 这种将查询结构与输入数据分离的方式确保输入被视为允许的 数据类型 之一,而不是可执行代码。

参数数据类型

参数值可以是以下数据类型之一:

  • 空值
  • 布尔值
  • 无符号整数 (u_int64)
  • 整数 (int64)
  • 双精度 (float64)
  • 字符串

数据类型示例

{
  "string": "Living Room",
  "double": 3.14,
  "unsigned_integer": 1234,
  "integer": -1234,
  "boolean": false,
  "null": Null,
}

时间表达式

要参数化时间边界,请用参数替换时间戳字面量,例如:

SELECT *
FROM home
WHERE time >= $min_time

对于参数值,指定时间戳字面量作为字符串–例如:

// Assign a timestamp string literal to the min_time parameter.
parameters := influxdb3.QueryParameters{
    "min_time": "2022-01-01 00:00:00.00",
}

InfluxDB 执行查询如下:

SELECT *
FROM home
WHERE time >= '2022-01-01 00:00:00.00'

与参数不兼容

如果您对以下内容使用参数,您的查询可能无法按照您的预期工作:

  • 在除 WHERE 以外的子句中,例如 SELECTGROUP BY
  • 作为函数参数,例如 avg($temp)
  • 作为标识符,例如列名或表名
  • 代替持续时间文字,例如 INTERVAL $minutes

参数化SQL查询

示例数据

以下示例使用 开始使用主页传感器数据。 在运行示例查询并返回结果之前, 将示例数据写入 您的 InfluxDB Cloud Serverless 存储桶。

要使用参数化查询,请执行以下操作:

  1. 在您的查询文本中,使用 $parameter 语法引用参数名称–例如,以下查询包含 $room$min_temp 参数占位符:

    SELECT *
    FROM home
    WHERE time > now() - INTERVAL '7 days'
    AND temp >= $min_temp
    AND room = $room
    
  2. 为每个参数名称提供一个值。 如果您未为参数分配值,InfluxDB 将返回错误。 提供参数值的语法取决于您使用的客户端——例如:

    // Define a QueryParameters struct--a map of parameters to input values.
    parameters := influxdb3.QueryParameters{
        "room": "Kitchen",
        "min_temp": 20.0,
    }
    

在 InfluxDB 接收到你的请求并解析查询后,它将执行查询作为

SELECT *
FROM home
WHERE time > now() - INTERVAL '7 days'
AND temp >= 20.0
AND room = 'Kitchen'

执行参数化 SQL 查询

示例数据

以下示例使用 开始使用主页传感器数据。 在运行示例查询并返回结果之前, 将示例数据写入 您的 InfluxDB Cloud Serverless 存储桶。

使用 InfluxDB Flight RPC 客户端

使用 InfluxDB 3 原生 Flight RPC 协议和支持的客户端,您可以发送带参数的查询和一组参数名称-值对。支持带参数查询的 InfluxDB Flight 客户端在 Flight 票据 params 字段中传递参数名称-值对。

以下示例展示了如何使用客户端库来执行参数化的SQL查询:

import (
    "context"
    "fmt"
    "io"
    "os"
    "text/tabwriter"
    "time"
    "github.com/InfluxCommunity/influxdb3-go/v2/influxdb3"
)

func Query(query string, parameters influxdb3.QueryParameters) error {
    url := os.Getenv("INFLUX_HOST")
    token := os.Getenv("INFLUX_TOKEN")
    database := os.Getenv("INFLUX_BUCKET")

    // Instantiate the influxdb3 client.
    client, err := influxdb3.New(influxdb3.ClientConfig{
        Host:     url,
        Token:    token,
        Database: database,
    })

    if err != nil {
        panic(err)
    }

    // Ensure the client is closed after the Query function finishes.
    defer func(client *influxdb3.Client) {
        err := client.Close()
        if err != nil {
            panic(err)
        }
    }(client)

    // Call the client's QueryWithParameters function.
    // Provide the query and parameters. The default QueryType is SQL.
    iterator, err := client.QueryWithParameters(context.Background(), query,
       parameters)

    // Create a buffer for storing rows as you process them.
    w := tabwriter.NewWriter(io.Discard, 4, 4, 1, ' ', 0)
    w.Init(os.Stdout, 0, 8, 0, '\t', 0)

    fmt.Fprintf(w, "time\troom\tco\thum\ttemp\n")

    // Format and write each row to the buffer.
    // Process each row as key-value pairs.
    for iterator.Next() {
        row := iterator.Value()
        // Use Go time package to format unix timestamp
        // as a time with timezone layout (RFC3339 format)
        time := (row["time"].(time.Time)).
                Format(time.RFC3339)

        fmt.Fprintf(w, "%s\t%s\t%d\t%.1f\t%.1f\n",
            time, row["room"], row["co"], row["hum"], row["temp"])
    }
    w.Flush()

    return nil
}

func main() {
    // Use the $placeholder syntax in a query to reference parameter placeholders
    // for input data.
    // The following SQL query contains the placeholders $room and $min_temp.
    query := `
        SELECT *
        FROM home
        WHERE time > now() - INTERVAL '7 days'
        AND temp >= $min_temp
        AND room = $room`

    // Define a QueryParameters struct--a map of placeholder names to input values.
    parameters := influxdb3.QueryParameters{
        "room": "Kitchen",
        "min_temp": 20.0,
    }
}

对参数化查询的客户端支持

  • 并不是所有的 InfluxDB 3 Flight clients 都支持参数化查询。
  • InfluxDB 目前不支持参数化查询或 DataFusion 为 Flight SQL 或 Flight SQL 客户端准备的语句。
  • InfluxDB 3 SQL 和 InfluxQL 的参数化查询在 InfluxDB v1 和 v2 客户端中不受支持。

不支持

目前,在 InfluxDB Cloud Serverless 中,参数化查询不提供以下内容:

  • 支持DataFusion预编译语句
  • 查询缓存、优化或性能收益


Flux的未来

Flux 正在进入维护模式。您可以像现在一样继续使用它,而无需对您的代码进行任何更改。

阅读更多

InfluxDB 3 开源版本现已公开Alpha测试

InfluxDB 3 Open Source is now available for alpha testing, licensed under MIT or Apache 2 licensing.

我们将发布两个产品作为测试版的一部分。

InfluxDB 3 核心,是我们新的开源产品。 它是一个用于时间序列和事件数据的实时数据引擎。 InfluxDB 3 企业版是建立在核心基础之上的商业版本,增加了历史查询能力、读取副本、高可用性、可扩展性和细粒度安全性。

有关如何开始的更多信息,请查看:

InfluxDB 云端无服务器