绑定变量

应用程序可以接受来自用户的数据,并在 SQL 语句中使用该数据。例如,应用程序可能会要求用户输入联系信息,例如地址和电话号码。

要在 SQL 语句中指定此用户输入,您可以以编程方式构造一个字符串来表示该 SQL 语句,方法是将用户输入与其他语句部分拼接起来。或者,您可以使用 绑定变量。要绑定变量,请在 SQL 语句文本中放置一个或多个占位符,然后为每个占位符指定变量(要使用的值)。

绑定变量概述

使用绑定变量,您可以将 SQL 语句中的字面量替换为占位符。例如,以下 SQL 语句对插入的值使用字面量:

INSERT INTO t (c1, c2) VALUES (1, 'Test string');
Copy

以下 SQL 语句对插入的值使用占位符:

INSERT INTO t (c1, c2) VALUES (?, ?);
Copy

您的应用程序代码将数据与 SQL 语句中的每个占位符绑定在一起。使用占位符绑定数据的技术取决于编程语言。占位符的语法也因编程语言而异。可能是 ?:varname,也可能是 %varname

Use bind variables in Javascript stored procedures

You can use Javascript to create stored procedures that run SQL.

要在 JavaScript 代码中指定绑定变量,请使用 ? 占位符。例如,以下 INSERT 语句可为插入到表行中的值指定绑定变量:

INSERT INTO t (col1, col2) VALUES (?, ?)
Copy

在 Javascript 代码中,您可以对大多数 SQL 语句中的值使用绑定变量。有关限制的信息,请参阅 绑定变量的限制

有关在 JavaScript 中使用绑定变量的更多信息,请参阅 绑定变量

Use bind variables with Snowflake Scripting

You can use Snowflake Scripting to create procedural code that runs SQL, such as code blocks and stored procedures. To specify bind variables in Snowflake Scripting code, prefix the variable name with a colon. For example, the following INSERT statement specifies a bind variable named variable1:

INSERT INTO t (c1) VALUES (:variable1)
Copy

When you run SQL in an EXECUTE IMMEDIATE command or an OPEN command for a cursor, you can bind variables with the USING clause.

此示例使用 USING 子句绑定 EXECUTE IMMEDIATE 命令中的变量:

EXECUTE IMMEDIATE :query USING (minimum_price, maximum_price);
Copy

有关包含此代码的完整示例,请参阅 执行包含绑定变量的语句

声明游标时,可以在 SELECT 语句中指定绑定参数(? 字符)。然后,可以在 USING 子句中打开游标时将这些参数绑定到变量。

以下示例声明游标并指定绑定参数,然后使用 USING 子句打开游标:

LET c1 CURSOR FOR SELECT id FROM invoices WHERE price > ? AND price < ?;
OPEN c1 USING (minimum_price, maximum_price);
Copy

Snowflake Scripting 还支持按位置对绑定变量进行编号,并在 SQL 语句中重复使用绑定变量。对于编号的绑定变量,会为每个变量声明分配一个索引,您可以使用 :n 引用第 n 个声明的变量。例如,以下 Snowflake Scripting 块为 i 变量指定绑定变量 :1 并为 v 变量指定 :2,在 SQL 语句中重复使用 :1 绑定变量:

EXECUTE IMMEDIATE $$
DECLARE
  i INTEGER DEFAULT 1;
  v VARCHAR DEFAULT 'SnowFlake';
  r RESULTSET;
BEGIN
  CREATE OR REPLACE TABLE snowflake_scripting_bind_demo (id INTEGER, value VARCHAR);
  EXECUTE IMMEDIATE 'INSERT INTO snowflake_scripting_bind_demo (id, value)
    SELECT :1, (:2 || :1)' USING (i, v);
  r := (SELECT * FROM snowflake_scripting_bind_demo);
  RETURN TABLE(r);
END;
$$
;
Copy
+----+------------+
| ID | VALUE      |
|----+------------|
|  1 | SnowFlake1 |
+----+------------+

在 Snowflake Scripting 代码中,您可以对大多数 SQL 语句中的值使用绑定变量。有关限制的信息,请参阅 绑定变量的限制

有关在 Snowflake Scripting 中使用绑定变量的更多信息,请参阅 在 SQL 语句中使用变量(绑定)在 SQL 语句中使用实参(绑定)

Use bind variables with the SQL API

您可以使用 Snowflake SQL API 访问和更新 Snowflake 数据库中的数据。您可以创建使用 SQL API 的应用程序,以提交 SQL 语句并管理部署。

When you submit a request that runs a SQL statement, you can use bind variables for values in the statement. For more information, see 在语句中使用绑定变量.

Use bind variables with drivers

使用 Snowflake 驱动程序,您可以编写在 Snowflake 上执行操作的应用程序。驱动程序支持 Go、Java 和 Python 等编程语言。有关在应用程序中为特定驱动程序使用绑定变量的信息,请按照驱动程序的链接进行操作:

备注

PHP 驱动程序不支持绑定变量。

Use bind variables with arrays of values

您可以将值数组绑定到 SQL 语句中的变量。使用此技术,您可以通过在单个批处理中插入多行来提高性能,从而避免网络往返和编译。数组绑定的使用也称为“批量插入”。

备注

Snowflake 支持建议使用的其他数据加载方法,而不是使用数组绑定。有关更多信息,请参阅 将数据载入 Snowflake数据加载和卸载命令

以下是 Python 代码中的数组绑定示例:

conn = snowflake.connector.connect( ... )
rows_to_insert = [('milk', 2), ('apple', 3), ('egg', 2)]
conn.cursor().executemany(
            "insert into grocery (item, quantity) values (?, ?)",
            rows_to_insert)
Copy

此示例指定以下绑定列表:[('milk', 2), ('apple', 3), ('egg', 2)]。应用程序指定绑定列表的方式取决于编程语言。

此代码在表中插入三行:

+-------+----+
| C1    | C2 |
|-------+----|
| milk  |  2 |
| apple |  3 |
| egg   |  2 |
+-------+----+

有关在应用程序中为特定驱动程序使用数组绑定的信息,请按照驱动程序的链接进行操作:

备注

The PHP driver doesn't support array binds.

使用数组绑定的限制

以下限制适用于数组绑定:

  • 仅 INSERT INTO ...VALUES 语句可以包含数组绑定变量。

  • VALUES 子句必须是绑定变量的单行列表。例如,不允许出现以下 VALUES 子句:

    VALUES (?,?), (?,?)
    
    Copy

Insert multiple rows without using array binds

INSERT 语句可能会使用绑定变量插入多行,而不使用数组绑定。以下示例将值插入到两行中,但它不使用数组绑定。

INSERT INTO t VALUES (?,?), (?,?);
Copy

例如,应用程序可以按顺序为占位符指定一个绑定列表,该列表相当于以下值:[1,'String1',2,'String2']。因为 VALUES 子句指定多行时,语句仅插入确切的值数(在示例中为 4 个),而不是动态数量的行。

Use bind variables with semi-structured data

要将绑定变量与半结构化数据结合使用,请将变量绑定为字符串类型,并使用 PARSE_JSONARRAY_CONSTRUCT 等函数。

以下示例创建包含一个 VARIANT 列的表,然后调用 PARSE_JSON 函数将半结构化数据插入到带有绑定变量的表中:

CREATE TABLE t (a VARIANT);
-- Code that supplies a bind value for ? of '{'a': 'abc', 'x': 'xyz'}'
INSERT INTO t SELECT PARSE_JSON(a) FROM VALUES (?);
Copy

以下示例查询该表:

SELECT * FROM t;
Copy

该查询会返回以下输出:

+---------------+
| A             |
|---------------|
| {             |
|   "a": "abc", |
|   "x": "xyz"  |
| }             |
+---------------+

以下语句调用 ARRAY_CONSTRUCT 函数将半结构化数据数组插入到带有绑定变量的 VARIANT 列中:

INSERT INTO t SELECT ARRAY_CONSTRUCT(column1) FROM VALUES (?);
Copy

这两个示例都可以插入单行,也可以使用数组绑定在一个批处理中插入多行。您可以使用此技术插入 VARIANT 列中有效的任何类型的半结构化数据。

Retrieve bind variable values

备注

要检索绑定变量值,必须在您的账户中启用 2025_06 行为变更捆绑包。此捆绑包默认禁用。

要检索已执行查询中绑定变量的值,您可以使用 INFORMATION_SCHEMA 架构中的 BIND_VALUES 表函数。通过此函数,您可以从任何支持绑定变量的代码(包括 Javascript 和 Snowflake Scripting 代码)中检索绑定变量值。

您还可以从 QUERY_HISTORY Account Usage 视图QUERY_HISTORY Organization Usage 视图 的输出中的 bind_values 列,或 </sql-reference/functions/query_history>` 中的 :doc:`QUERY_HISTORY 函数来访问这些绑定变量值。

要使用上述任何方法检索绑定变量值,您必须将账户级参数 ALLOW_BIND_VALUES_ACCESS 设置为 TRUE

您可能需要在以下情况下检索绑定变量值:

  • 查询故障排除 – 当您了解查询中使用的确切绑定值时,更容易优化查询并调试以下类型的问题:

    • 查询运行失败。

    • 查询性能不佳。

    • 查询未使用缓存或预期的执行计划。

  • 重新创建查询以进行测试 - 开发人员和 DBAs 可以使用绑定变量值重新创建用户生成的查询,以复现问题并进行压力测试。

  • 审计与合规 - 出于安全和合规目的,组织必须审计用户正在访问的数据。他们可以使用绑定变量值来确定用户检索的确切数据。

检索绑定变量值的示例

以下查询返回先前查询的绑定变量值:

SELECT * FROM TABLE(
  INFORMATION_SCHEMA.BIND_VALUES('<query_id_value>'));
Copy
SELECT bind_values
  FROM SNOWFLAKE.ACCOUNT_USAGE.QUERY_HISTORY
  WHERE query_id = '<query_id_value>';
Copy

query_id_value 替换为查询 ID。您可以使用 LAST_QUERY_ID 函数返回先前查询的 ID。

备注

QUERY_HISTORY 视图的延迟可能长达 45 分钟。

The following examples use the BIND_VALUES function:

检索命名绑定变量的 Snowflake Scripting 示例

运行以下 Snowflake Scripting 匿名块,其中包含一个使用绑定变量的语句:

DECLARE
  name STRING;
  temperature FLOAT;
  res RESULTSET;
BEGIN
  name := 'Snowman';
  temperature := -20.14;
  res := (
    SELECT
      CONCAT('Hello ', :NAME, '!') as greeting,
      CONCAT('It is ', :TEMPERATURE, 'deg C today.') as weather
  );
  RETURN LAST_QUERY_ID();
END;
Copy

注意:如果您在 Python Connector 代码中使用 Snowflake CLISnowSQLClassic Console 或者 execute_streamexecute_string 方法,请改用本示例(请参阅 在 Snowflake CLI、SnowSQL、Classic Console 和 Python Connector 中使用 Snowflake Scripting):

EXECUTE IMMEDIATE
$$
DECLARE
  name STRING;
  temperature FLOAT;
  res RESULTSET;
BEGIN
  name := 'Snowman';
  temperature := -20.14;
  res := (
    SELECT
      CONCAT('Hello ', :NAME, '!') as greeting,
      CONCAT('It is ', :TEMPERATURE, 'deg C today.') as weather
  );
  RETURN LAST_QUERY_ID();
END;
$$
;
Copy

该块返回使用绑定变量的语句的查询 ID。

备注

您的语句将返回与此处显示的查询 ID 不同的 ID。

+--------------------------------------+
| anonymous block                      |
|--------------------------------------|
| 01bbe3d6-0109-0863-0000-a99502ffa062 |
+--------------------------------------+

要检索匿名块中使用的绑定变量,请运行以下查询。运行匿名块后,将输出中的 01bbe3d6-0109-0863-0000-a99502ffa062 替换为查询 ID。

SELECT * FROM TABLE(
  INFORMATION_SCHEMA.BIND_VALUES('01bbe3d6-0109-0863-0000-a99502ffa062'));
Copy
+--------------------------------------+----------+-------------+------+---------+
| QUERY_ID                             | POSITION | NAME        | TYPE | VALUE   |
|--------------------------------------+----------+-------------+------+---------|
| 01bbe3d6-0109-0863-0000-a99502ffa062 |     NULL | TEMPERATURE | REAL | -20.14  |
| 01bbe3d6-0109-0863-0000-a99502ffa062 |     NULL | NAME        | TEXT | Snowman |
+--------------------------------------+----------+-------------+------+---------+

检索位置绑定变量的 Python 连接器示例

以下 Python Connector 代码使用 BIND_VALUES 函数在输出中显示位置绑定变量的值:

cursor = conn.cursor()
print(cursor.execute(
          """
          SELECT
              CONCAT('Hello ', ?, '!') as greeting,
              CONCAT('It is ', ?, 'deg C today.') as weather
          """,
          params=["Snowman", -20.14],
      ).fetch_pandas_all())

query_id = cursor.sfqid
print(f"Bind values for query {query_id} are:")
print(cursor.execute("SELECT * FROM TABLE(INFORMATION_SCHEMA.BIND_VALUES(?))", params=[query_id]).fetch_pandas_all())
Copy
        GREETING                   WEATHER
0  Hello Snowman!  It is -20.14deg C today.

Bind values for query 01bbe918-0200-0001-0000-000000101145 are:

                               QUERY_ID POSITION  NAME  TYPE    VALUE
0  01bbe918-0200-0001-0000-000000101145        1  None  TEXT  Snowman
1  01bbe918-0200-0001-0000-000000101145        2  None  REAL   -20.14

绑定变量的限制

以下限制适用于绑定变量:

  • SELECT 语句的限制:

    • 绑定变量不能替换属于数据类型定义(例如 NUMBER(?))或 排序规则规范 <label-collation_specification>`(例如 ``COLLATE ?`)的数字。

    • 在查询暂存区上的文件的 SELECT 语句中,绑定变量不能用于源代码。

  • DDL 命令的限制:

    • 绑定变量不能在以下 DDL 命令中使用:

      • CREATE/ALTER INTEGRATION

      • CREATE/ALTER REPLICATION GROUP

      • CREATE/ALTER PIPE

      • CREATE TABLE ...USING TEMPLATE

    • 绑定变量不能在以下子句中使用:

      • ALTER COLUMN

      • COMMENT ON CONSTRAINT

    • 在 CREATE/ALTER 命令中,绑定变量不能用于以下参数的值:

      • CREDENTIALS

      • DIRECTORY

      • ENCRYPTION

      • IMPORTS

      • PACKAGES

      • REFRESH

      • TAG

      • 特定于外部表的参数

    • 绑定变量不能用于属于 FILE FORMAT 值的属性。

  • 在 COPY INTO 命令中,绑定变量不能用于以下参数的值:

    • CREDENTIALS

    • ENCRYPTION

    • FILE_FORMAT

  • 在 SHOW 命令中,绑定变量不能用于 STARTS WITH 参数。

  • 绑定变量不能在 EXECUTE IMMEDIATE FROM 命令中使用。

  • 在以下内容中使用绑定变量时,绑定变量值无法自动从一种数据类型转换为另一种数据类型:

    • 明确指定数据类型的 Snowflake Scripting 代码

    • DDL 语句

    • 暂存区名称

绑定变量的安全注意事项

绑定变量不会在所有情况下都对敏感数据进行掩码处理。例如,绑定变量的值可能会出现在错误消息和其他构件中。

绑定变量可以在构造带有用户输入的 SQL 语句时帮助防止 SQL 注入攻击。但是,绑定变量可能会带来潜在的安全风险。如果 SQL 语句的输入来自外部来源,请确保它们有效。有关更多信息,请参阅 SQL 注入

语言: 中文