运行参数化查询

在使用用户输入构建查询时,BigQuery 支持利用查询参数来防范 SQL 注入。只有 GoogleSQL 语法提供此功能。查询参数可用于替换任意表达式。但参数不能用于替换标识符、列名、表名或查询的其他部分。

如需指定命名参数,请使用 @ 字符后跟标识符,例如 @param_name。或者,使用占位值 ? 指定一个位置参数。请注意,查询可以使用位置参数或命名参数,但不能同时使用这两种参数。

使用参数时,提供的值本身不会记录在 BigQuery 日志中,以保护潜在的敏感信息。

您可以通过以下方式在 BigQuery 中运行参数化查询:

  • bq 命令行工具的 bq query 命令
  • API
  • 客户端库

以下示例展示了如何将参数值传递给参数化查询:

控制台

Google Cloud 控制台不支持参数化查询。

bq

  1. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  2. 使用 --parameter 以 name:type:value 的形式提供参数值。如果名称为空,则系统会生成一个定位参数。可以忽略类型,此时系统会假设应使用 STRING 类型。

    如需指定使用 GoogleSQL 语法,必须将 --parameter 标志与 --use_legacy_sql=false 标志结合使用。

    (可选)使用 --location 标志指定您的位置。

    bq query \
       --use_legacy_sql=false \
       --parameter=corpus::romeoandjuliet \
       --parameter=min_word_count:INT64:250 \
       'SELECT
         word,
         word_count
       FROM
         `bigquery-public-data.samples.shakespeare`
       WHERE
         corpus = @corpus
       AND
         word_count >= @min_word_count
       ORDER BY
         word_count DESC;'
  3. API

    如需使用命名参数,请在 query 作业配置中将 parameterMode 设置为 NAMED。

    使用 query 作业配置中的参数列表填充 queryParameters。通过在查询中使用 @param_name 设置各参数的 name。

    如需启用 GoogleSQL 语法,请将 useLegacySql 设置为 false。

    {
      "query": "SELECT word, word_count FROM `bigquery-public-data.samples.shakespeare` WHERE corpus = @corpus AND word_count >= @min_word_count ORDER BY word_count DESC;",
      "queryParameters": [
        {
          "parameterType": {
            "type": "STRING"
          },
          "parameterValue": {
            "value": "romeoandjuliet"
          },
          "name": "corpus"
        },
        {
          "parameterType": {
            "type": "INT64"
          },
          "parameterValue": {
            "value": "250"
          },
          "name": "min_word_count"
        }
      ],
      "useLegacySql": false,
      "parameterMode": "NAMED"
    }
    

    在 Google APIs Explorer 中尝试。

    如需使用位置参数,请在 query 作业配置中将 parameterMode 设置为 POSITIONAL。

    C#

    试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 C# 设置说明进行操作。 如需了解详情,请参阅 BigQuery C# API 参考文档。

    如需向 BigQuery 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为客户端库设置身份验证。

    使用命名参数的方法如下:
    
    using Google.Cloud.BigQuery.V2;
    using System;
    
    public class BigQueryQueryWithNamedParameters
    {
        public void QueryWithNamedParameters(string projectId = "your-project-id")
        {
            var corpus = "romeoandjuliet";
            var minWordCount = 250;
    
            // Note: Standard SQL is required to use query parameters.
            var query = @"
                SELECT word, word_count
                FROM `bigquery-public-data.samples.shakespeare`
                WHERE corpus = @corpus
                AND word_count >= @min_word_count
                ORDER BY word_count DESC";
    
            // Initialize client that will be used to send requests.
            var client = BigQueryClient.Create(projectId);
    
            var parameters = new BigQueryParameter[]
            {
                new BigQueryParameter("corpus", BigQueryDbType.String, corpus),
                new BigQueryParameter("min_word_count", BigQueryDbType.Int64, minWordCount)
            };
    
            var job = client.CreateQueryJob(
                sql: query,
                parameters: parameters,
                options: new QueryOptions { UseQueryCache = false });
            // Wait for the job to complete.
            job = job.PollUntilCompleted().ThrowOnAnyError();
            // Display the results
            foreach (BigQueryRow row in client.GetQueryResults(job.Reference))
            {
                Console.WriteLine($"{row["word"]}: {row["word_count"]}");
            }
        }
    }

    试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 C# 设置说明进行操作。 如需了解详情,请参阅 BigQuery C# API 参考文档。

    如需向 BigQuery 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为客户端库设置身份验证。

    使用位置参数的方法如下:
    
    using Google.Cloud.BigQuery.V2;
    using System;
    
    public class BigQueryQueryWithPositionalParameters
    {
        public void QueryWithPositionalParameters(string projectId = "project-id")
        {
            var corpus = "romeoandjuliet";
            var minWordCount = 250;
    
            // Note: Standard SQL is required to use query parameters.
            var query = @"
                    SELECT word, word_count
                    FROM `bigquery-public-data.samples.shakespeare`
                    WHERE corpus = ?
                    AND word_count >= ?
                    ORDER BY word_count DESC;";
    
            // Initialize client that will be used to send requests.
            var client = BigQueryClient.Create(projectId);
    
            // Set the name to None to use positional parameters.
            // Note that you cannot mix named and positional parameters.
            var parameters = new BigQueryParameter[]
            {
                new BigQueryParameter(null, BigQueryDbType.String, corpus),
                new BigQueryParameter(null, BigQueryDbType.Int64, minWordCount)
            };
    
            var job = client.CreateQueryJob(
                sql: query,
                parameters: parameters,
                options: new QueryOptions
                {
                    UseQueryCache = false,
                    ParameterMode = BigQueryParameterMode.Positional
                });
            // Wait for the job to complete.
            job = job.PollUntilCompleted().ThrowOnAnyError();
            // Display the results
            foreach (BigQueryRow row in client.GetQueryResults(job.Reference))
            {
                Console.WriteLine($"{row["word"]}: {row["word_count"]}");
            }
        }
    }

    Go

    试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 Go 设置说明进行操作。 如需了解详情,请参阅 BigQuery Go API 参考文档。

    如需向 BigQuery 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为客户端库设置身份验证。

    使用命名参数的方法如下:
    import (
    	"context"
    	"fmt"
    	"io"
    
    	"cloud.google.com/go/bigquery"
    	"google.golang.org/api/iterator"
    )
    
    // queryWithNamedParams demonstrate issuing a query using named query parameters.
    func queryWithNamedParams(w io.Writer, projectID string) error {
    	// projectID := "my-project-id"
    	ctx := context.Background()
    	client, err := bigquery.NewClient(ctx, projectID)
    	if err != nil {
    		return fmt.Errorf("bigquery.NewClient: %v", err)
    	}
    	defer client.Close()
    
    	q := client.Query(
    		`SELECT word, word_count
            FROM ` + "`bigquery-public-data.samples.shakespeare`" + `
            WHERE corpus = @corpus
            AND word_count >= @min_word_count
            ORDER BY word_count DESC;`)
    	q.Parameters = []bigquery.QueryParameter{
    		{
    			Name:  "corpus",
    			Value: "romeoandjuliet",
    		},
    		{
    			Name:  "min_word_count",
    			Value: 250,
    		},
    	}
    	// Run the query and print results when the query job is completed.
    	job, err := q.Run(ctx)
    	if err != nil {
    		return err
    	}
    	status, err := job.Wait(ctx)
    	if err != nil {
    		return err
    	}
    	if err := status.Err(); err != nil {
    		return err
    	}
    	it, err := job.Read(ctx)
    	for {
    		var row []bigquery.Value
    		err := it.Next(&row)
    		if err == iterator.Done {
    			break
    		}
    		if err != nil {
    			return err
    		}
    		fmt.Fprintln(w, row)
    	}
    	return nil
    }
    

    使用位置参数的方法如下:
    import (
    	"context"
    	"fmt"
    	"io"
    
    	"cloud.google.com/go/bigquery"
    	"google.golang.org/api/iterator"
    )
    
    // queryWithPostionalParams demonstrate issuing a query using positional query parameters.
    func queryWithPositionalParams(w io.Writer, projectID string) error {
    	// projectID := "my-project-id"
    	ctx := context.Background()
    	client, err := bigquery.NewClient(ctx, projectID)
    	if err != nil {
    		return fmt.Errorf("bigquery.NewClient: %v", err)
    	}
    	defer client.Close()
    
    	q := client.Query(
    		`SELECT word, word_count
            FROM ` + "`bigquery-public-data.samples.shakespeare`" + `
            WHERE corpus = ?
            AND word_count >= ?
            ORDER BY word_count DESC;`)
    	q.Parameters = []bigquery.QueryParameter{
    		{
    			Value: "romeoandjuliet",
    		},
    		{
    			Value: 250,
    		},
    	}
    	// Run the query and print results when the query job is completed.
    	job, err := q.Run(ctx)
    	if err != nil {
    		return err
    	}
    	status, err := job.Wait(ctx)
    	if err != nil {
    		return err
    	}
    	if err := status.Err(); err != nil {
    		return err
    	}
    	it, err := job.Read(ctx)
    	for {
    		var row []bigquery.Value
    		err := it.Next(&row)
    		if err == iterator.Done {
    			break
    		}
    		if err != nil {
    			return err
    		}
    		fmt.Fprintln(w, row)
    	}
    	return nil
    }
    

    Java

    试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 Java 设置说明进行操作。 如需了解详情,请参阅 BigQuery Java API 参考文档。

    如需向 BigQuery 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为客户端库设置身份验证。

    使用命名参数的方法如下:
    import com.google.cloud.bigquery.BigQuery;
    import com.google.cloud.bigquery.BigQueryException;
    import com.google.cloud.bigquery.BigQueryOptions;
    import com.google.cloud.bigquery.QueryJobConfiguration;
    import com.google.cloud.bigquery.QueryParameterValue;
    import com.google.cloud.bigquery.TableResult;
    
    public class QueryWithNamedParameters {
    
      public static void queryWithNamedParameters() {
        try {
          // Initialize client that will be used to send requests. This client only needs to be created
          // once, and can be reused for multiple requests.
          BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();
    
          String corpus = "romeoandjuliet";
          long minWordCount = 250;
          String query =
              "SELECT word, word_count\n"
                  + "FROM `bigquery-public-data.samples.shakespeare`\n"
                  + "WHERE corpus = @corpus\n"
                  + "AND word_count >= @min_word_count\n"
                  + "ORDER BY word_count DESC";
    
          // Note: Standard SQL is required to use query parameters.
          QueryJobConfiguration queryConfig =
              QueryJobConfiguration.newBuilder(query)
                  .addNamedParameter("corpus", QueryParameterValue.string(corpus))
                  .addNamedParameter("min_word_count", QueryParameterValue.int64(minWordCount))
                  .build();
    
          TableResult results = bigquery.query(queryConfig);
    
          results
              .iterateAll()
              .forEach(row -> row.forEach(val -> System.out.printf("%s,", val.toString())));
    
          System.out.println("Query with named parameters performed successfully.");
        } catch (BigQueryException | InterruptedException e) {
          System.out.println("Query not performed \n" + e.toString());
        }
      }
    }

    使用位置参数的方法如下:
    import com.google.cloud.bigquery.BigQuery;
    import com.google.cloud.bigquery.BigQueryException;
    import com.google.cloud.bigquery.BigQueryOptions;
    import com.google.cloud.bigquery.QueryJobConfiguration;
    import com.google.cloud.bigquery.QueryParameterValue;
    import com.google.cloud.bigquery.TableResult;
    
    public class QueryWithPositionalParameters {
      public static void queryWithPositionalParameters() {
        try {
          // Initialize client that will be used to send requests. This client only needs to be created
          // once, and can be reused for multiple requests.
          BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();
    
          String corpus = "romeoandjuliet";
          long minWordCount = 250;
          String query =
              "SELECT word, word_count\n"
                  + "FROM `bigquery-public-data.samples.shakespeare`\n"
                  + "WHERE corpus = ?\n"
                  + "AND word_count >= ?\n"
                  + "ORDER BY word_count DESC";
    
          // Note: Standard SQL is required to use query parameters.
          QueryJobConfiguration queryConfig =
              QueryJobConfiguration.newBuilder(query)
                  .addPositionalParameter(QueryParameterValue.string(corpus))
                  .addPositionalParameter(QueryParameterValue.int64(minWordCount))
                  .build();
    
          TableResult results = bigquery.query(queryConfig);
    
          results
              .iterateAll()
              .forEach(row -> row.forEach(val -> System.out.printf("%s,", val.toString())));
    
          System.out.println("Query with positional parameters performed successfully.");
        } catch (BigQueryException | InterruptedException e) {
          System.out.println("Query not performed \n" + e.toString());
        }
      }
    }

    Node.js

    试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 Node.js 设置说明进行操作。 如需了解详情,请参阅 BigQuery Node.js API 参考文档。

    如需向 BigQuery 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为客户端库设置身份验证。

    使用命名参数的方法如下:
    // Run a query using named query parameters
    
    // Import the Google Cloud client library
    const {BigQuery} = require('@google-cloud/bigquery');
    const bigquery = new BigQuery();
    
    async function queryParamsNamed() {
      // The SQL query to run
      const sqlQuery = `SELECT word, word_count
            FROM \`bigquery-public-data.samples.shakespeare\`
            WHERE corpus = @corpus
            AND word_count >= @min_word_count
            ORDER BY word_count DESC`;
    
      const options = {
        query: sqlQuery,
        // Location must match that of the dataset(s) referenced in the query.
        location: 'US',
        params: {corpus: 'romeoandjuliet', min_word_count: 250},
      };
    
      // Run the query
      const [rows] = await bigquery.query(options);
    
      console.log('Rows:');
      rows.forEach(row => console.log(row));
    }

    使用位置参数的方法如下:
    // Run a query using positional query parameters
    
    // Import the Google Cloud client library
    const {BigQuery} = require('@google-cloud/bigquery');
    const bigquery = new BigQuery();
    
    async function queryParamsPositional() {
      // The SQL query to run
      const sqlQuery = `SELECT word, word_count
            FROM \`bigquery-public-data.samples.shakespeare\`
            WHERE corpus = ?
            AND word_count >= ?
            ORDER BY word_count DESC`;
    
      const options = {
        query: sqlQuery,
        // Location must match that of the dataset(s) referenced in the query.
        location: 'US',
        params: ['romeoandjuliet', 250],
      };
    
      // Run the query
      const [rows] = await bigquery.query(options);
    
      console.log('Rows:');
      rows.forEach(row => console.log(row));
    }

    Python

    试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 Python 设置说明进行操作。 如需了解详情,请参阅 BigQuery Python API 参考文档。

    如需向 BigQuery 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为客户端库设置身份验证。

    使用命名参数的方法如下:
    from google.cloud import bigquery
    
    # Construct a BigQuery client object.
    client = bigquery.Client()
    
    query = """
        SELECT word, word_count
        FROM `bigquery-public-data.samples.shakespeare`
        WHERE corpus = @corpus
        AND word_count >= @min_word_count
        ORDER BY word_count DESC;
    """
    job_config = bigquery.QueryJobConfig(
        query_parameters=[
            bigquery.ScalarQueryParameter("corpus", "STRING", "romeoandjuliet"),
            bigquery.ScalarQueryParameter("min_word_count", "INT64", 250),
        ]
    )
    results = client.query_and_wait(
        query, job_config=job_config
    )  # Make an API request.
    
    for row in results:
        print("{}: \t{}".format(row.word, row.word_count))

    使用位置参数的方法如下:
    from google.cloud import bigquery
    
    # Construct a BigQuery client object.
    client = bigquery.Client()
    
    query = """
        SELECT word, word_count
        FROM `bigquery-public-data.samples.shakespeare`
        WHERE corpus = ?
        AND word_count >= ?
        ORDER BY word_count DESC;
    """
    # Set the name to None to use positional parameters.
    # Note that you cannot mix named and positional parameters.
    job_config = bigquery.QueryJobConfig(
        query_parameters=[
            bigquery.ScalarQueryParameter(None, "STRING", "romeoandjuliet"),
            bigquery.ScalarQueryParameter(None, "INT64", 250),
        ]
    )
    results = client.query_and_wait(
        query, job_config=job_config
    )  # Make an API request.
    
    for row in results:
        print("{}: \t{}".format(row.word, row.word_count))

在参数化查询中使用数组

如需在查询参数中使用数组类型,请将类型设置为 ARRAY<T>,其中 T 是数组中元素的类型。请将值构造为用方括号括起来并且以英文逗号分隔的元素列表,例如 [1, 2, 3]。

请参阅数据类型参考以详细了解数组类型。

控制台

Google Cloud 控制台不支持参数化查询。

bq

  1. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  2. 下面的查询会选择在美国出生且名字以 W 开头的男婴中最常用的名字:

    bq query \
       --use_legacy_sql=false \
       --parameter='gender::M' \
       --parameter='states:ARRAY<STRING>:["WA", "WI", "WV", "WY"]' \
       'SELECT
         name,
         SUM(number) AS count
       FROM
         `bigquery-public-data.usa_names.usa_1910_2013`
       WHERE
         gender = @gender
         AND state IN UNNEST(@states)
       GROUP BY
         name
       ORDER BY
         count DESC
       LIMIT
         10;'

    请务必注意,需要将数组类型声明括在英文单引号中,以保证命令输出不会被 > 字符意外地重定向到某个文件。

  3. API

    如需使用数组值参数,请在 query 作业配置中将 parameterType 设置为 ARRAY。

    如果数组值是标量,请将 parameterType 设置为值的类型,例如 STRING。如果数组值是结构,请将其设置为 STRUCT,并将所需字段定义添加到 structTypes。

    例如,下面的查询会选择在美国出生且名字以 W 开头的男婴中最常用的名字。

    {
     "query": "SELECT name, sum(number) as count\nFROM `bigquery-public-data.usa_names.usa_1910_2013`\nWHERE gender = @gender\nAND state IN UNNEST(@states)\nGROUP BY name\nORDER BY count DESC\nLIMIT 10;",
     "queryParameters": [
      {
       "parameterType": {
        "type": "STRING"
       },
       "parameterValue": {
        "value": "M"
       },
       "name": "gender"
      },
      {
       "parameterType": {
        "type": "ARRAY",
        "arrayType": {
         "type": "STRING"
        }
       },
       "parameterValue": {
        "arrayValues": [
         {
          "value": "WA"
         },
         {
          "value": "WI"
         },
         {
          "value": "WV"
         },
         {
          "value": "WY"
         }
        ]
       },
       "name": "states"
      }
     ],
     "useLegacySql": false,
     "parameterMode": "NAMED"
    }
    

    在 Google APIs Explorer 中尝试。

    C#

    试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 C# 设置说明进行操作。 如需了解详情,请参阅 BigQuery C# API 参考文档。

    如需向 BigQuery 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为客户端库设置身份验证。

    
    using Google.Cloud.BigQuery.V2;
    using System;
    
    public class BigQueryQueryWithArrayParameters
    {
        public void QueryWithArrayParameters(string projectId = "your-project-id")
        {
            var gender = "M";
            string[] states = { "WA", "WI", "WV", "WY" };
    
            // Note: Standard SQL is required to use query parameters.
            var query = @"
                SELECT name, sum(number) as count
                FROM `bigquery-public-data.usa_names.usa_1910_2013`
                WHERE gender = @gender
                AND state IN UNNEST(@states)
                GROUP BY name
                ORDER BY count DESC
                LIMIT 10;";
    
            // Initialize client that will be used to send requests.
            var client = BigQueryClient.Create(projectId);
    
            var parameters = new BigQueryParameter[]
            {
                new BigQueryParameter("gender", BigQueryDbType.String, gender),
                new BigQueryParameter("states", BigQueryDbType.Array, states)
            };
    
            var job = client.CreateQueryJob(
                sql: query,
                parameters: parameters,
                options: new QueryOptions { UseQueryCache = false });
            // Wait for the job to complete.
            job = job.PollUntilCompleted().ThrowOnAnyError();
            // Display the results
            foreach (BigQueryRow row in client.GetQueryResults(job.Reference))
            {
                Console.WriteLine($"{row["name"]}: {row["count"]}");
            }
        }
    }

    Go

    试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 Go 设置说明进行操作。 如需了解详情,请参阅 BigQuery Go API 参考文档。

    如需向 BigQuery 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为客户端库设置身份验证。

    import (
    	"context"
    	"fmt"
    	"io"
    
    	"cloud.google.com/go/bigquery"
    	"google.golang.org/api/iterator"
    )
    
    // queryWithArrayParams demonstrates issuing a query and specifying query parameters that include an
    // array of strings.
    func queryWithArrayParams(w io.Writer, projectID string) error {
    	// projectID := "my-project-id"
    	ctx := context.Background()
    	client, err := bigquery.NewClient(ctx, projectID)
    	if err != nil {
    		return fmt.Errorf("bigquery.NewClient: %v", err)
    	}
    	defer client.Close()
    
    	q := client.Query(
    		`SELECT
    			name,
    			sum(number) as count 
            FROM ` + "`bigquery-public-data.usa_names.usa_1910_2013`" + `
    		WHERE
    			gender = @gender
            	AND state IN UNNEST(@states)
    		GROUP BY
    			name
    		ORDER BY
    			count DESC
    		LIMIT 10;`)
    	q.Parameters = []bigquery.QueryParameter{
    		{
    			Name:  "gender",
    			Value: "M",
    		},
    		{
    			Name:  "states",
    			Value: []string{"WA", "WI", "WV", "WY"},
    		},
    	}
    	// Run the query and print results when the query job is completed.
    	job, err := q.Run(ctx)
    	if err != nil {
    		return err
    	}
    	status, err := job.Wait(ctx)
    	if err != nil {
    		return err
    	}
    	if err := status.Err(); err != nil {
    		return err
    	}
    	it, err := job.Read(ctx)
    	for {
    		var row []bigquery.Value
    		err := it.Next(&row)
    		if err == iterator.Done {
    			break
    		}
    		if err != nil {
    			return err
    		}
    		fmt.Fprintln(w, row)
    	}
    	return nil
    }
    

    Java

    试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 Java 设置说明进行操作。 如需了解详情,请参阅 BigQuery Java API 参考文档。

    如需向 BigQuery 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为客户端库设置身份验证。

    import com.google.cloud.bigquery.BigQuery;
    import com.google.cloud.bigquery.BigQueryException;
    import com.google.cloud.bigquery.BigQueryOptions;
    import com.google.cloud.bigquery.QueryJobConfiguration;
    import com.google.cloud.bigquery.QueryParameterValue;
    import com.google.cloud.bigquery.TableResult;
    
    // Sample to running a query with array query parameters.
    public class QueryWithArrayParameters {
    
      public static void runQueryWithArrayParameters() {
        String gender = "M";
        String[] states = {"WA", "WI", "WV", "WY"};
        String query =
            "SELECT name, sum(number) as count\n"
                + "FROM `bigquery-public-data.usa_names.usa_1910_2013`\n"
                + "WHERE gender = @gender\n"
                + "AND state IN UNNEST(@states)\n"
                + "GROUP BY name\n"
                + "ORDER BY count DESC\n"
                + "LIMIT 10;";
        queryWithArrayParameters(query, gender, states);
      }
    
      public static void queryWithArrayParameters(String query, String gender, String[] states) {
        try {
          // Initialize client that will be used to send requests. This client only needs to be created
          // once, and can be reused for multiple requests.
          BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();
    
          // Note: Standard SQL is required to use query parameters.
          QueryJobConfiguration queryConfig =
              QueryJobConfiguration.newBuilder(query)
                  .addNamedParameter("gender", QueryParameterValue.string(gender))
                  .addNamedParameter("states", QueryParameterValue.array(states, String.class))
                  .build();
    
          TableResult results = bigquery.query(queryConfig);
    
          // Print the results.
          results
              .iterateAll()
              .forEach(row -> row.forEach(val -> System.out.printf("%s,", val.toString())));
          System.out.println("Query with arrays parameters performed successfully");
        } catch (BigQueryException | InterruptedException e) {
          System.out.println("Query not performed \n" + e.toString());
        }
      }
    }

    Node.js

    试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 Node.js 设置说明进行操作。 如需了解详情,请参阅 BigQuery Node.js API 参考文档。

    如需向 BigQuery 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为客户端库设置身份验证。

    // Run a query using array query parameters
    
    // Import the Google Cloud client library
    const {BigQuery} = require('@google-cloud/bigquery');
    const bigquery = new BigQuery();
    
    async function queryParamsArrays() {
      // The SQL query to run
      const sqlQuery = `SELECT name, sum(number) as count
      FROM \`bigquery-public-data.usa_names.usa_1910_2013\`
      WHERE gender = @gender
      AND state IN UNNEST(@states)
      GROUP BY name
      ORDER BY count DESC
      LIMIT 10;`;
    
      const options = {
        query: sqlQuery,
        // Location must match that of the dataset(s) referenced in the query.
        location: 'US',
        params: {gender: 'M', states: ['WA', 'WI', 'WV', 'WY']},
      };
    
      // Run the query
      const [rows] = await bigquery.query(options);
    
      console.log('Rows:');
      rows.forEach(row => console.log(row));
    }

    Python

    试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 Python 设置说明进行操作。 如需了解详情,请参阅 BigQuery Python API 参考文档。

    如需向 BigQuery 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为客户端库设置身份验证。

    from google.cloud import bigquery
    
    # Construct a BigQuery client object.
    client = bigquery.Client()
    
    query = """
        SELECT name, sum(number) as count
        FROM `bigquery-public-data.usa_names.usa_1910_2013`
        WHERE gender = @gender
        AND state IN UNNEST(@states)
        GROUP BY name
        ORDER BY count DESC
        LIMIT 10;
    """
    job_config = bigquery.QueryJobConfig(
        query_parameters=[
            bigquery.ScalarQueryParameter("gender", "STRING", "M"),
            bigquery.ArrayQueryParameter("states", "STRING", ["WA", "WI", "WV", "WY"]),
        ]
    )
    rows = client.query_and_wait(query, job_config=job_config)  # Make an API request.
    
    for row in rows:
        print("{}: \t{}".format(row.name, row.count))

在参数化查询中使用时间戳

要在查询参数中使用时间戳,底层 REST API 采用 YYYY-MM-DD HH:MM:SS.DDDDDD time_zone 格式的 TIMESTAMP 类型的值。如果您使用的是客户端库,请以该语言创建内置日期对象,库会将其转换为正确的格式。如需了解详情,请参阅以下特定语言的示例。

如需详细了解 TIMESTAMP 类型,请参阅数据类型参考文档。

控制台

Google Cloud 控制台不支持参数化查询。

bq

  1. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  2. 下面的查询会将时间戳参数值增加一小时:

    bq query \
       --use_legacy_sql=false \
       --parameter='ts_value:TIMESTAMP:2016-12-07 08:00:00' \
       'SELECT
         TIMESTAMP_ADD(@ts_value, INTERVAL 1 HOUR);'
  3. API

    如需使用时间戳参数,请在查询作业配置中将 parameterType 设置为 TIMESTAMP。

    下面的查询会将时间戳参数值增加一小时。

    {
      "query": "SELECT TIMESTAMP_ADD(@ts_value, INTERVAL 1 HOUR);",
      "queryParameters": [
        {
          "name": "ts_value",
          "parameterType": {
            "type": "TIMESTAMP"
          },
          "parameterValue": {
            "value": "2016-12-07 08:00:00"
          }
        }
      ],
      "useLegacySql": false,
      "parameterMode": "NAMED"
    }
    

    在 Google APIs Explorer 中尝试。

    C#

    试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 C# 设置说明进行操作。 如需了解详情,请参阅 BigQuery C# API 参考文档。

    如需向 BigQuery 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为客户端库设置身份验证。

    
    using Google.Cloud.BigQuery.V2;
    using System;
    
    public class BigQueryQueryWithTimestampParameters
    {
        public void QueryWithTimestampParameters(string projectId = "project-id")
        {
            var timestamp = new DateTime(2016, 12, 7, 8, 0, 0, DateTimeKind.Utc);
    
            // Note: Standard SQL is required to use query parameters.
            var query = "SELECT TIMESTAMP_ADD(@ts_value, INTERVAL 1 HOUR);";
    
            // Initialize client that will be used to send requests.
            var client = BigQueryClient.Create(projectId);
    
            var parameters = new BigQueryParameter[]
            {
                new BigQueryParameter("ts_value", BigQueryDbType.Timestamp, timestamp),
            };
    
            var job = client.CreateQueryJob(
                sql: query,
                parameters: parameters,
                options: new QueryOptions { UseQueryCache = false });
            // Wait for the job to complete.
            job = job.PollUntilCompleted().ThrowOnAnyError();
            // Display the results
            foreach (BigQueryRow row in client.GetQueryResults(job.Reference))
            {
                Console.WriteLine(row[0]);
            }
        }
    }

    Go

    试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 Go 设置说明进行操作。 如需了解详情,请参阅 BigQuery Go API 参考文档。

    如需向 BigQuery 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为客户端库设置身份验证。

    import (
    	"context"
    	"fmt"
    	"io"
    	"time"
    
    	"cloud.google.com/go/bigquery"
    	"google.golang.org/api/iterator"
    )
    
    // queryWithTimestampParam demonstrates issuing a query and supplying a timestamp query parameter.
    func queryWithTimestampParam(w io.Writer, projectID string) error {
    	// projectID := "my-project-id"
    	ctx := context.Background()
    	client, err := bigquery.NewClient(ctx, projectID)
    	if err != nil {
    		return fmt.Errorf("bigquery.NewClient: %v", err)
    	}
    	defer client.Close()
    
    	q := client.Query(
    		`SELECT TIMESTAMP_ADD(@ts_value, INTERVAL 1 HOUR);`)
    	q.Parameters = []bigquery.QueryParameter{
    		{
    			Name:  "ts_value",
    			Value: time.Date(2016, 12, 7, 8, 0, 0, 0, time.UTC),
    		},
    	}
    	// Run the query and print results when the query job is completed.
    	job, err := q.Run(ctx)
    	if err != nil {
    		return err
    	}
    	status, err := job.Wait(ctx)
    	if err != nil {
    		return err
    	}
    	if err := status.Err(); err != nil {
    		return err
    	}
    	it, err := job.Read(ctx)
    	for {
    		var row []bigquery.Value
    		err := it.Next(&row)
    		if err == iterator.Done {
    			break
    		}
    		if err != nil {
    			return err
    		}
    		fmt.Fprintln(w, row)
    	}
    	return nil
    }
    

    Java

    试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 Java 设置说明进行操作。 如需了解详情,请参阅 BigQuery Java API 参考文档。

    如需向 BigQuery 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为客户端库设置身份验证。

    import com.google.cloud.bigquery.BigQuery;
    import com.google.cloud.bigquery.BigQueryException;
    import com.google.cloud.bigquery.BigQueryOptions;
    import com.google.cloud.bigquery.QueryJobConfiguration;
    import com.google.cloud.bigquery.QueryParameterValue;
    import com.google.cloud.bigquery.TableResult;
    import org.threeten.bp.LocalDateTime;
    import org.threeten.bp.ZoneOffset;
    import org.threeten.bp.ZonedDateTime;
    
    // Sample to running a query with timestamp query parameters.
    public class QueryWithTimestampParameters {
    
      public static void runQueryWithTimestampParameters() {
        queryWithTimestampParameters();
      }
    
      public static void queryWithTimestampParameters() {
        try {
          // Initialize client that will be used to send requests. This client only needs to be created
          // once, and can be reused for multiple requests.
          BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();
    
          ZonedDateTime timestamp = LocalDateTime.of(2016, 12, 7, 8, 0, 0).atZone(ZoneOffset.UTC);
          String query = "SELECT TIMESTAMP_ADD(@ts_value, INTERVAL 1 HOUR);";
          // Note: Standard SQL is required to use query parameters.
          QueryJobConfiguration queryConfig =
              QueryJobConfiguration.newBuilder(query)
                  .addNamedParameter(
                      "ts_value",
                      QueryParameterValue.timestamp(
                          // Timestamp takes microseconds since 1970-01-01T00:00:00 UTC
                          timestamp.toInstant().toEpochMilli() * 1000))
                  .build();
    
          TableResult results = bigquery.query(queryConfig);
    
          results
              .iterateAll()
              .forEach(row -> row.forEach(val -> System.out.printf("%s", val.toString())));
    
          System.out.println("Query with timestamp parameter performed successfully.");
        } catch (BigQueryException | InterruptedException e) {
          System.out.println("Query not performed \n" + e.toString());
        }
      }
    }

    Node.js

    试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 Node.js 设置说明进行操作。 如需了解详情,请参阅 BigQuery Node.js API 参考文档。

    如需向 BigQuery 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为客户端库设置身份验证。

    // Run a query using timestamp parameters
    
    // Import the Google Cloud client library
    const {BigQuery} = require('@google-cloud/bigquery');
    const bigquery = new BigQuery();
    
    async function queryParamsTimestamps() {
      // The SQL query to run
      const sqlQuery = `SELECT TIMESTAMP_ADD(@ts_value, INTERVAL 1 HOUR);`;
    
      const options = {
        query: sqlQuery,
        // Location must match that of the dataset(s) referenced in the query.
        location: 'US',
        params: {ts_value: new Date()},
      };
    
      // Run the query
      const [rows] = await bigquery.query(options);
    
      console.log('Rows:');
      rows.forEach(row => console.log(row.f0_));
    }

    Python

    试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 Python 设置说明进行操作。 如需了解详情,请参阅 BigQuery Python API 参考文档。

    如需向 BigQuery 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为客户端库设置身份验证。

    import datetime
    
    from google.cloud import bigquery
    
    # Construct a BigQuery client object.
    client = bigquery.Client()
    
    query = "SELECT TIMESTAMP_ADD(@ts_value, INTERVAL 1 HOUR);"
    job_config = bigquery.QueryJobConfig(
        query_parameters=[
            bigquery.ScalarQueryParameter(
                "ts_value",
                "TIMESTAMP",
                datetime.datetime(2016, 12, 7, 8, 0, tzinfo=datetime.timezone.utc),
            )
        ]
    )
    results = client.query_and_wait(
        query, job_config=job_config
    )  # Make an API request.
    
    for row in results:
        print(row)

在参数化查询中使用结构体

如需在查询参数中使用结构体,请将类型设置为 STRUCT<T>,其中 T 用于定义结构体中的字段和类型。字段定义以英文逗号分隔,采用 field_name TF 格式,其中 TF 是字段的类型。例如,STRUCT<x INT64, y STRING> 定义了一个结构体,其中包含一个名称为 x、类型为 INT64 的字段,还包含名称为 y、类型为 STRING 的第二个字段。

如需详细了解 STRUCT 类型,请参阅数据类型参考文档 。

控制台

Google Cloud 控制台不支持参数化查询。

bq

  1. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  2. 以下简单的查询通过返回参数值演示了结构化类型的用法:

    bq query \
       --use_legacy_sql=false \
       --parameter='struct_value:STRUCT<x INT64, y STRING>:{"x": 1, "y": "foo"}' \
       'SELECT
         @struct_value AS s;'
  3. API

    如需使用结构体参数,请在查询作业配置中将 parameterType 设置为 STRUCT。

    在作业的 queryParameters 中,为结构体的各字段向 structTypes 中添加一个对象。如果结构体值是标量,请将 type 设置为值的类型,例如 STRING。如果结构体值是数组,请将此设置为 ARRAY,并将嵌套的 arrayType 字段设置为相应类型。如果结构体值是结构,则将 type 设置为 STRUCT,并添加必要的 structTypes。

    下面这条简单的查询通过返回参数值来演示结构化类型的用法。

    {
      "query": "SELECT @struct_value AS s;",
      "queryParameters": [
        {
          "name": "struct_value",
          "parameterType": {
            "type": "STRUCT",
            "structTypes": [
              {
                "name": "x",
                "type": {
                  "type": "INT64"
                }
              },
              {
                "name": "y",
                "type": {
                  "type": "STRING"
                }
              }
            ]
          },
          "parameterValue": {
            "structValues": {
              "x": {
                "value": "1"
              },
              "y": {
                "value": "foo"
              }
            }
          }
        }
      ],
      "useLegacySql": false,
      "parameterMode": "NAMED"
    }
    

    在 Google APIs Explorer 中尝试。

    C#

    .NET 版 BigQuery 客户端库目前不支持结构体参数。

    Go

    试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 Go 设置说明进行操作。 如需了解详情,请参阅 BigQuery Go API 参考文档。

    如需向 BigQuery 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为客户端库设置身份验证。

    import (
    	"context"
    	"fmt"
    	"io"
    
    	"cloud.google.com/go/bigquery"
    	"google.golang.org/api/iterator"
    )
    
    // queryWithStructParam demonstrates running a query and providing query parameters that include struct
    // types.
    func queryWithStructParam(w io.Writer, projectID string) error {
    	// projectID := "my-project-id"
    	ctx := context.Background()
    	client, err := bigquery.NewClient(ctx, projectID)
    	if err != nil {
    		return fmt.Errorf("bigquery.NewClient: %v", err)
    	}
    	defer client.Close()
    
    	type MyStruct struct {
    		X int64
    		Y string
    	}
    	q := client.Query(
    		`SELECT @struct_value as s;`)
    	q.Parameters = []bigquery.QueryParameter{
    		{
    			Name:  "struct_value",
    			Value: MyStruct{X: 1, Y: "foo"},
    		},
    	}
    	// Run the query and print results when the query job is completed.
    	job, err := q.Run(ctx)
    	if err != nil {
    		return err
    	}
    	status, err := job.Wait(ctx)
    	if err != nil {
    		return err
    	}
    	if err := status.Err(); err != nil {
    		return err
    	}
    	it, err := job.Read(ctx)
    	for {
    		var row []bigquery.Value
    		err := it.Next(&row)
    		if err == iterator.Done {
    			break
    		}
    		if err != nil {
    			return err
    		}
    		fmt.Fprintln(w, row)
    	}
    	return nil
    }
    

    Java

    试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 Java 设置说明进行操作。 如需了解详情,请参阅 BigQuery Java API 参考文档。

    如需向 BigQuery 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为客户端库设置身份验证。

    import com.google.cloud.bigquery.BigQuery;
    import com.google.cloud.bigquery.BigQueryException;
    import com.google.cloud.bigquery.BigQueryOptions;
    import com.google.cloud.bigquery.QueryJobConfiguration;
    import com.google.cloud.bigquery.QueryParameterValue;
    import com.google.cloud.bigquery.TableResult;
    import java.util.HashMap;
    import java.util.Map;
    
    public class QueryWithStructsParameters {
    
      public static void queryWithStructsParameters() {
        try {
          // Initialize client that will be used to send requests. This client only needs to be created
          // once, and can be reused for multiple requests.
          BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();
    
          // Create struct
          Map<String, QueryParameterValue> struct = new HashMap<>();
          struct.put("booleanField", QueryParameterValue.bool(true));
          struct.put("integerField", QueryParameterValue.string("test-stringField"));
          struct.put("stringField", QueryParameterValue.int64(10));
          QueryParameterValue recordValue = QueryParameterValue.struct(struct);
    
          String query = "SELECT STRUCT(@recordField) AS record";
          QueryJobConfiguration queryConfig =
              QueryJobConfiguration.newBuilder(query)
                  .setUseLegacySql(false)
                  .addNamedParameter("recordField", recordValue)
                  .build();
    
          TableResult results = bigquery.query(queryConfig);
    
          results
              .iterateAll()
              .forEach(row -> row.forEach(val -> System.out.printf("%s", val.toString())));
    
          System.out.println("Query with struct parameter performed successfully.");
        } catch (BigQueryException | InterruptedException e) {
          System.out.println("Query not performed \n" + e.toString());
        }
      }
    }

    Node.js

    试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 Node.js 设置说明进行操作。 如需了解详情,请参阅 BigQuery Node.js API 参考文档。

    如需向 BigQuery 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为客户端库设置身份验证。

    // Run a query using struct query parameters
    
    // Import the Google Cloud client library
    const {BigQuery} = require('@google-cloud/bigquery');
    const bigquery = new BigQuery();
    
    async function queryParamsStructs() {
      // The SQL query to run
      const sqlQuery = `SELECT @struct_value AS struct_obj;`;
    
      const options = {
        query: sqlQuery,
        // Location must match that of the dataset(s) referenced in the query.
        location: 'US',
        params: {struct_value: {x: 1, y: 'foo'}},
      };
    
      // Run the query
      const [rows] = await bigquery.query(options);
    
      console.log('Rows:');
      rows.forEach(row => console.log(row.struct_obj.y));
    }

    Python

    试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 Python 设置说明进行操作。 如需了解详情,请参阅 BigQuery Python API 参考文档。

    如需向 BigQuery 进行身份验证,请设置应用默认凭证。如需了解详情,请参阅为客户端库设置身份验证。

    from google.cloud import bigquery
    
    # Construct a BigQuery client object.
    client = bigquery.Client()
    
    query = "SELECT @struct_value AS s;"
    job_config = bigquery.QueryJobConfig(
        query_parameters=[
            bigquery.StructQueryParameter(
                "struct_value",
                bigquery.ScalarQueryParameter("x", "INT64", 1),
                bigquery.ScalarQueryParameter("y", "STRING", "foo"),
            )
        ]
    )
    results = client.query_and_wait(
        query, job_config=job_config
    )  # Make an API request and waits for results.
    
    for row in results:
        print(row.s)