Modifica esquemas de tabla

En este documento, se describe cómo modificar las definiciones de esquema para tablas de BigQuery existentes. BigQuery es compatible con las modificaciones de esquema siguientes de forma nativa:

  • Agregar columnas a una definición de esquema
  • Disminuir la rigurosidad del modo de una columna de REQUIRED a NULLABLE

Es válido crear una tabla sin definir un esquema inicial y agregar una definición de esquema a la tabla más adelante.

Todas las demás modificaciones del esquema no son compatibles y requieren soluciones alternativas manuales, que incluyen las opciones siguientes:

  • Cambiar el nombre de una columna
  • Cambiar el tipo de datos de una columna
  • Cambiar el modo de una columna (además de disminuir la rigurosidad de las columnas REQUIRED a NULLABLE)
  • Borrar una columna

Para obtener más información sobre cambios de esquema no compatibles que requieren soluciones alternativas, consulta Cambia esquemas de tablas de forma manual.

Agrega columnas a la definición de esquema de una tabla

Puedes agregar columnas a la definición de esquema de una tabla existente de las formas siguientes:

  • De forma manual (crea una columna vacía).
  • Cuando usas un trabajo o consulta de carga para reemplazar una tabla
  • Cuando adjuntas datos a una tabla con un trabajo de carga o consulta

Toda columna que agregas se debe adherir a las funciones de BigQuery para los nombres de consultas. Para obtener más información sobre cómo crear componentes de esquema, consulta Especifica un esquema.

Agrega una columna vacía de forma manual

Puedes agregar una columna vacía a una tabla existente con uno de estos métodos:

  • Mediante Cloud Console o la IU web clásica de BigQuery
  • Mediante el comando bq update de la herramienta de línea de comandos de bq
  • Con una llamada al método tables.patch de la API
  • Usar bibliotecas cliente

Si agregas columnas nuevas a un esquema de tabla existente, las columnas deben ser NULLABLE o REPEATED. No puedes agregar una columna REQUIRED a un esquema de tabla existente. Si intentas agregar una columna REQUIRED a un esquema de tabla existente en la API o la herramienta de línea de comandos de bq, se mostrará el siguiente error: BigQuery error in update operation: Provided Schema does not match Table project_id:dataset.table. Cannot add required columns to an existing schema. Las columnas REQUIRED solo pueden agregarse cuando creas una tabla mientras cargas datos, o cuando creas una tabla vacía con una definición de esquema.

Después de agregar una columna nueva a la definición de esquema de la tabla, puedes cargar datos en la columna nueva si usas los siguientes elementos:

Para agregar columnas vacías a la definición de esquema de una tabla, sigue estos pasos:

Console

  1. En el panel Recursos, selecciona tu tabla.

  2. Debajo del Editor de consultas, desplázate hasta la parte inferior de la sección Esquema y haz clic en Editar esquema.

Edita un esquema de tabla

  1. Desplázate hasta la parte inferior del panel que se abre y haz clic en Agregar campo.

    • Para Nombre, escribe el nombre de la columna.
    • Para Tipo, elige el tipo de datos.
    • Para Modo, elige NULLABLE o REPEATED.
  2. Cuando termines de agregar columnas, haz clic en Guardar.

IU clásica

  1. Selecciona tu tabla en el panel de navegación.

  2. En la página Detalles de la tabla, haz clic en Agregar campos nuevos.

  3. En la sección New Fields (Campos nuevos), sigue estos pasos:

    • Para Nombre, escribe el nombre de la columna.
    • Para Tipo, elige el tipo de datos.
    • Para Modo, elige NULLABLE o REPEATED.

      Actualiza el esquema de tabla

  4. Cuando termines de agregar las columnas, haz clic en Add To Table.

bq

Ejecuta el comando bq update y proporciona un archivo de esquema JSON. Si la tabla que actualizas está en un proyecto que no es tu proyecto predeterminado, agrega el ID del proyecto al nombre del conjunto de datos en el siguiente formato: project_id:dataset.

bq update project_id:dataset.table schema

En el ejemplo anterior, se ilustra lo siguiente:

  • project_id es el ID del proyecto.
  • dataset es el nombre del conjunto de datos que contiene la tabla que deseas actualizar.
  • table es el nombre de la tabla que deseas actualizar.
  • schema es la ruta al archivo de esquema JSON en tu máquina local.

Cuando especificas el esquema con la herramienta de línea de comandos de bq, no puedes incluir un tipo RECORD (STRUCT) ni una descripción de columna, y tampoco puedes especificar el modo de la columna. Todos los modos están establecidos como NULLABLE de forma predeterminada.

Si intentas agregar columnas con una definición de esquema intercalada, debes suministrar la definición de esquema completa que incluye las columnas nuevas. Debido a que no puedes especificar los modos de columnas con una definición de esquema intercalada, la actualización intentará cambiar cualquier columna REQUIRED existente a NULLABLE. Esto genera el error siguiente: BigQuery error in update operation: Provided Schema does not match Table project_id:dataset.table. Field field has changed mode from REPEATED to NULLABLE.

El método recomendado para agregar columnas a una tabla existente mediante la herramienta de línea de comandos de bq es suministrar un archivo de esquema JSON.

Para agregar columnas vacías al esquema de una tabla con un archivo de esquema JSON, sigue estos pasos:

  1. Primero, ejecuta el comando bq show con la marca --schema y escribe el esquema de tabla existente en un archivo. Si la tabla que actualizas está en un proyecto que no es tu proyecto predeterminado, agrega el ID del proyecto al nombre del conjunto de datos en el siguiente formato: project_id:dataset.

    bq show \
    --schema \
    --format=prettyjson \
    project_id:dataset.table > schema_file
    

    En el ejemplo anterior, se ilustra lo siguiente:

    • project_id es el ID del proyecto.
    • dataset es el nombre del conjunto de datos que contiene la tabla que deseas actualizar.
    • table es el nombre de la tabla que deseas actualizar.
    • schema_file es el archivo de definición de esquema que se escribe en tu máquina local.

    Por ejemplo, para escribir la definición de esquema de mydataset.mytable en un archivo, ingresa el siguiente comando. mydataset.mytable está en tu proyecto predeterminado.

       bq show \
       --schema \
       --format=prettyjson \
       mydataset.mytable > /tmp/myschema.json
    
  2. Abre el archivo del esquema en un editor de texto. El esquema debe verse de la manera siguiente:

    [
      {
        "mode": "REQUIRED",
        "name": "column1",
        "type": "STRING"
      },
      {
        "mode": "REQUIRED",
        "name": "column2",
        "type": "FLOAT"
      },
      {
        "mode": "REPEATED",
        "name": "column3",
        "type": "STRING"
      }
    ]
    
  3. Agrega las columnas nuevas al final de la definición del esquema. Si intentas agregar columnas nuevas en otra parte del arreglo, se muestra el siguiente error: BigQuery error in update operation: Precondition Failed.

    Con un archivo JSON, puedes especificar descripciones, modos NULLABLE o REPEATED, y tipos RECORD para columnas nuevas. Por ejemplo, mediante la definición de esquema del paso anterior, tu arreglo JSON nuevo se vería de la manera siguiente. En este ejemplo, se agrega una columna NULLABLE nueva llamada column4. column4 incluye una descripción.

      [
        {
          "mode": "REQUIRED",
          "name": "column1",
          "type": "STRING"
        },
        {
          "mode": "REQUIRED",
          "name": "column2",
          "type": "FLOAT"
        },
        {
          "mode": "REPEATED",
          "name": "column3",
          "type": "STRING"
        },
        {
          "description": "my new column",
          "mode": "NULLABLE",
          "name": "column4",
          "type": "STRING"
        }
      ]
      

    Para obtener más información sobre cómo trabajar con archivos de esquema JSON, consulta Especifica un archivo de esquema JSON.

  4. Después de actualizar tu archivo de esquema, ejecuta el comando siguiente para actualizar el esquema de la tabla. Si la tabla que actualizas está en un proyecto que no es tu proyecto predeterminado, agrega el ID del proyecto al nombre del conjunto de datos en el siguiente formato: project_id:dataset.

    bq update project_id:dataset.table schema
    

    En el ejemplo anterior, se ilustra lo siguiente:

    • project_id es el ID del proyecto.
    • dataset es el nombre del conjunto de datos que contiene la tabla que deseas actualizar.
    • table es el nombre de la tabla que deseas actualizar.
    • schema es la ruta al archivo de esquema JSON en tu máquina local.

    Por ejemplo, ingresa el siguiente comando para actualizar la definición de esquema de mydataset.mytable en tu proyecto predeterminado. La ruta al archivo de esquema en tu máquina local es /tmp/myschema.json.

    bq update mydataset.mytable /tmp/myschema.json
    

API

Llama al método tables.patch y usa la propiedad schema para agregar columnas vacías a la definición del esquema. Debido a que, con el método tables.update se reemplaza todo el recurso de tabla, es preferible usar el método tables.patch.

Go

import (
	"context"
	"fmt"

	"cloud.google.com/go/bigquery"
)

// updateTableAddColumn demonstrates modifying the schema of a table to append an additional column.
func updateTableAddColumn(projectID, datasetID, tableID string) error {
	// projectID := "my-project-id"
	// datasetID := "mydataset"
	// tableID := "mytable"
	ctx := context.Background()
	client, err := bigquery.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("bigquery.NewClient: %v", err)
	}
	defer client.Close()

	tableRef := client.Dataset(datasetID).Table(tableID)
	meta, err := tableRef.Metadata(ctx)
	if err != nil {
		return err
	}
	newSchema := append(meta.Schema,
		&bigquery.FieldSchema{Name: "phone", Type: bigquery.StringFieldType},
	)
	update := bigquery.TableMetadataToUpdate{
		Schema: newSchema,
	}
	if _, err := tableRef.Update(ctx, update, meta.ETag); err != nil {
		return err
	}
	return nil
}

Java

Antes de probar este ejemplo, sigue las instrucciones de configuración para Java que se encuentran en la guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de BigQuery para Java.

import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.Field;
import com.google.cloud.bigquery.FieldList;
import com.google.cloud.bigquery.LegacySQLTypeName;
import com.google.cloud.bigquery.Schema;
import com.google.cloud.bigquery.StandardTableDefinition;
import com.google.cloud.bigquery.Table;
import java.util.ArrayList;
import java.util.List;

public class AddEmptyColumn {

  public static void runAddEmptyColumn() {
    // TODO(developer): Replace these variables before running the sample.
    String datasetName = "MY_DATASET_NAME";
    String tableId = "MY_TABLE_NAME";
    String newColumnName = "NEW_COLUMN_NAME";
    addEmptyColumn(newColumnName, datasetName, tableId);
  }

  public static void addEmptyColumn(String newColumnName, String datasetName, String tableId) {
    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();

      Table table = bigquery.getTable(datasetName, tableId);
      Schema schema = table.getDefinition().getSchema();
      FieldList fields = schema.getFields();

      // Create the new field/column
      Field newField = Field.of(newColumnName, LegacySQLTypeName.STRING);

      // Create a new schema adding the current fields, plus the new one
      List<Field> fieldList = new ArrayList<Field>();
      fields.forEach(fieldList::add);
      fieldList.add(newField);
      Schema newSchema = Schema.of(fieldList);

      // Update the table with the new schema
      Table updatedTable =
          table.toBuilder().setDefinition(StandardTableDefinition.of(newSchema)).build();
      updatedTable.update();
      System.out.println("Empty column successfully added to table");
    } catch (BigQueryException e) {
      System.out.println("Empty column was not added. \n" + e.toString());
    }
  }
}

Node.js

Antes de probar este ejemplo, sigue las instrucciones de configuración para Node.js que se encuentran en la guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de BigQuery para Node.js.


// Import the Google Cloud client library and create a client
const {BigQuery} = require('@google-cloud/bigquery');
const bigquery = new BigQuery();

async function addEmptyColumn() {
  // Adds an empty column to the schema.

  /**
   * TODO(developer): Uncomment the following lines before running the sample.
   */
  // const datasetId = 'my_dataset';
  // const tableId = 'my_table';
  const column = {name: 'size', type: 'STRING'};

  // Retrieve current table metadata
  const table = bigquery.dataset(datasetId).table(tableId);
  const [metadata] = await table.getMetadata();

  // Update table schema
  const schema = metadata.schema;
  const new_schema = schema;
  new_schema.fields.push(column);
  metadata.schema = new_schema;

  const [result] = await table.setMetadata(metadata);
  console.log(result.schema.fields);
}

Python

Antes de probar esta muestra, sigue las instrucciones de configuración para Python incluidas en la Guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de BigQuery para Python.

Agrega un objeto SchemaField nuevo a una copia de Table.schema y, luego, reemplaza el valor de la propiedad Table.schema por el esquema actualizado.
from google.cloud import bigquery

# Construct a BigQuery client object.
client = bigquery.Client()

# TODO(developer): Set table_id to the ID of the table
#                  to add an empty column.
# table_id = "your-project.your_dataset.your_table_name"

table = client.get_table(table_id)  # Make an API request.

original_schema = table.schema
new_schema = original_schema[:]  # Creates a copy of the schema.
new_schema.append(bigquery.SchemaField("phone", "STRING"))

table.schema = new_schema
table = client.update_table(table, ["schema"])  # Make an API request.

if len(table.schema) == len(original_schema) + 1 == len(new_schema):
    print("A new column has been added.")
else:
    print("The column has not been added.")

Agrega una columna anidada a RECORD

Además de agregar columnas nuevas al esquema de una tabla, también puedes agregar columnas anidadas nuevas a un RECORD. El proceso a fin de agregar una columna anidada nueva es muy similar al proceso para agregar una columna nueva.

Console

En la actualidad, Cloud Console no admite agregar un nuevo campo anidado a una columna RECORD existente.

IU clásica

Por el momento, agregar un campo anidado nuevo a una columna RECORD existente no es compatible con la IU web clásica de BigQuery.

bq

Ejecuta el comando bq update y proporciona un archivo de esquema JSON que agregue el campo anidado a la definición de esquema de la columna RECORD existente. Si la tabla que actualizas está en un proyecto que no es tu proyecto predeterminado, agrega el ID del proyecto al nombre del conjunto de datos en el siguiente formato: project_id:dataset.

bq update project_id:dataset.table schema

En el ejemplo anterior, se ilustra lo siguiente:

  • project_id es el ID del proyecto.
  • dataset es el nombre del conjunto de datos que contiene la tabla que deseas actualizar.
  • table es el nombre de la tabla que deseas actualizar.
  • schema es la ruta al archivo de esquema JSON en tu máquina local.

Cuando especificas el esquema con la herramienta de línea de comandos de bq, no puedes incluir un tipo RECORD (STRUCT) ni una descripción de columna, y tampoco puedes especificar el modo de la columna. Todos los modos están establecidos como NULLABLE de forma predeterminada. Como resultado, si agregas una columna anidada nueva a RECORD, debes proporcionar un archivo de esquema JSON.

Para agregar una columna anidada a RECORD mediante un archivo de esquema JSON, haz lo siguiente:

  1. Primero, ejecuta el comando bq show con la marca --schema y escribe el esquema de tabla existente en un archivo. Si la tabla que actualizas está en un proyecto que no es tu proyecto predeterminado, agrega el ID del proyecto al nombre del conjunto de datos en el siguiente formato: project_id:dataset.table.

    bq show \
    --schema \
    --format=prettyjson \
    project_id:dataset.table > schema_file
    

    En el ejemplo anterior, se ilustra lo siguiente:

    • project_id es el ID del proyecto.
    • dataset es el nombre del conjunto de datos que contiene la tabla que deseas actualizar.
    • table es el nombre de la tabla que deseas actualizar.
    • schema_file es el archivo de definición de esquema que se escribe en tu máquina local.

    Por ejemplo, para escribir la definición de esquema de mydataset.mytable en un archivo, ingresa el siguiente comando. mydataset.mytable está en tu proyecto predeterminado.

    bq show \
    --schema \
    --format=prettyjson \
    mydataset.mytable > /tmp/myschema.json
    
  2. Abre el archivo del esquema en un editor de texto. El esquema debe verse de la manera siguiente. En este ejemplo, column3 es una columna repetida anidada. Las columnas anidadas son nested1 y nested2. El arreglo fields enumera los campos anidados en column3.

    [
      {
        "mode": "REQUIRED",
        "name": "column1",
        "type": "STRING"
      },
      {
        "mode": "REQUIRED",
        "name": "column2",
        "type": "FLOAT"
      },
      {
        "fields": [
          {
            "mode": "NULLABLE",
            "name": "nested1",
            "type": "STRING"
          },
          {
            "mode": "NULLABLE",
            "name": "nested2",
            "type": "STRING"
          }
        ],
        "mode": "REPEATED",
        "name": "column3",
        "type": "RECORD"
      }
    ]
    
  3. Agrega la columna anidada nueva en el final del arreglo fields. En este ejemplo, nested3 es la columna anidada nueva.

      [
        {
          "mode": "REQUIRED",
          "name": "column1",
          "type": "STRING"
        },
        {
          "mode": "REQUIRED",
          "name": "column2",
          "type": "FLOAT"
        },
        {
          "fields": [
            {
              "mode": "NULLABLE",
              "name": "nested1",
              "type": "STRING"
            },
            {
              "mode": "NULLABLE",
              "name": "nested2",
              "type": "STRING"
            },
            {
              "mode": "NULLABLE",
              "name": "nested3",
              "type": "STRING"
            }
          ],
          "mode": "REPEATED",
          "name": "column3",
          "type": "RECORD"
        }
      ]
      

    Para obtener más información sobre cómo trabajar con archivos de esquema JSON, consulta Especifica un archivo de esquema JSON.

  4. Después de actualizar tu archivo de esquema, ejecuta el comando siguiente para actualizar el esquema de la tabla. Si la tabla que actualizas está en un proyecto que no es tu proyecto predeterminado, agrega el ID del proyecto al nombre del conjunto de datos en el siguiente formato: project_id:dataset.

    bq update project_id:dataset.table schema
    

    En el ejemplo anterior, se ilustra lo siguiente:

    • project_id es el ID del proyecto.
    • dataset es el nombre del conjunto de datos que contiene la tabla que deseas actualizar.
    • table es el nombre de la tabla que deseas actualizar.
    • schema es la ruta al archivo de esquema JSON en tu máquina local.

    Por ejemplo, ingresa el siguiente comando para actualizar la definición de esquema de mydataset.mytable en tu proyecto predeterminado. La ruta al archivo de esquema en tu máquina local es /tmp/myschema.json.

    bq update mydataset.mytable /tmp/myschema.json
    

API

Llama al método tables.patch y usa la propiedad schema para agregar las columnas anidadas a tu definición de esquema. Debido a que, con el método tables.update se reemplaza todo el recurso de tabla, es preferible usar el método tables.patch.

Agrega una columna cuando reemplazas o agregas datos

Puedes agregar columnas nuevas a una tabla existente cuando cargas datos en esta y eliges reemplazar la tabla existente. Cuando reemplazas una tabla existente, el esquema de los datos que cargaste se usa para reemplazar el esquema de la tabla existente. Para obtener información sobre cómo reemplazar una tabla con un trabajo de carga, consulta:

También puedes agregar columnas nuevas a una tabla existente cuando agregas datos a esta con un trabajo de carga o consulta.

Agrega una columna en un trabajo de carga de anexo

Puedes agregar columnas a una tabla mientras le anexas datos en un trabajo de carga con uno de los siguientes métodos:

  • Mediante el comando bq load de la herramienta de línea de comandos de bq
  • Llamar al método jobs.insert de la API y configurar un trabajo load
  • Usar bibliotecas cliente

Por el momento, Cloud Console o la IU web clásica de BigQuery no admiten agregar una columna a una tabla existente durante una operación de anexo.

Cuando agregas columnas con una operación de anexo en un trabajo de carga, el esquema actualizado puede encontrarse de las siguientes maneras:

  • Detectado de forma automática (para archivos CSV y JSON)
  • Especificado en un archivo de esquema JSON (para archivos CSV y JSON)
  • Recuperado de los datos fuente autodescriptivos de los archivos de exportación de Avro, ORC, Parquet y Datastore

Si especificas el esquema en un archivo JSON, las columnas nuevas se deben definir en él. Si faltan las definiciones nuevas de la columna, se muestra el error siguiente cuando intentas anexar los datos: Error while reading data, error message: parsing error in row starting at position int: No such field: field.

Cuando agregas columnas nuevas durante una operación de anexo, los valores en las columnas nuevas se establecen en NULL para las filas existentes.

Para agregar una columna nueva cuando anexas datos en una tabla durante un trabajo de carga, ten en cuenta esta información:

Console

No puedes agregar columnas nuevas a una tabla existente cuando cargas datos con Cloud Console.

IU clásica

No puedes agregar columnas nuevas a una tabla existente cuando cargas datos con la IU web clásica de BigQuery.

bq

Usa el comando bq load para cargar tus datos y especifica la marca --noreplace a fin de indicar que agregas los datos a una tabla existente.

Si los datos que agregas están en formato CSV o JSON delimitado por saltos de línea, especifica la marca --autodetect para usar la detección automática de esquemas o suministra el esquema en un archivo de esquema JSON. Las columnas agregadas se pueden inferir de forma automática desde los archivos de exportación Avro o Datastore.

Establece la marca --schema_update_option en ALLOW_FIELD_ADDITION para indicar que los datos que anexas contienen nuevas columnas.

Si la tabla que anexas se encuentra en un conjunto de datos de un proyecto distinto a tu proyecto predeterminado, debes agregar el ID del proyecto al nombre del conjunto de datos en el siguiente formato: project_id:dataset.

De forma opcional, puedes proporcionar la marca --location y establecer el valor según tu ubicación.

Ingresa el comando load de la siguiente manera:

bq --location=location load \
--noreplace \
--autodetect \
--schema_update_option=ALLOW_FIELD_ADDITION \
--source_format=format \
project_id:dataset.table \
path_to_source \
schema

En el ejemplo anterior, se ilustra lo siguiente:

  • location es el nombre de tu ubicación. La marca --location es opcional. Por ejemplo, si usas BigQuery en la región de Tokio, configura el valor de la marca como asia-northeast1. Puedes configurar un valor predeterminado para la ubicación con el archivo .bigqueryrc.
  • format es NEWLINE_DELIMITED_JSON, CSV, AVRO, PARQUET, ORC o DATASTORE_BACKUP.
  • project_id es el ID del proyecto.
  • dataset es el nombre del conjunto de datos que contiene la tabla.
  • table es el nombre de la tabla que deseas agregar.
  • path_to_source es un URI de Cloud Storage completamente calificado, una lista de URI separada por comas o la ruta a un archivo de datos en tu máquina local.
  • schema es la ruta a un archivo de esquema JSON local. Solo se requiere un archivo de esquema para los archivos CSV y JSON cuando --autodetect no se especifica. Los esquemas de Avro y Datastore se infieren de los datos de origen.

Ejemplos:

Ingresa el siguiente comando para anexar un archivo de datos de Avro local, /tmp/mydata.avro, a mydataset.mytable mediante un trabajo de carga. Debido a que los esquemas se pueden deducir de forma automática de los datos de Avro, no es necesario usar la marca --autodetect. mydataset está en tu proyecto predeterminado.

bq load \
--noreplace \
--schema_update_option=ALLOW_FIELD_ADDITION \
--source_format=AVRO \
mydataset.mytable \
/tmp/mydata.avro

Ingresa el siguiente comando para anexar un archivo de datos JSON delimitado por saltos de línea en Cloud Storage a mydataset.mytable mediante un trabajo de carga. La marca --autodetect se usa para detectar las columnas nuevas. mydataset está en tu proyecto predeterminado.

bq load \
--noreplace \
--autodetect \
--schema_update_option=ALLOW_FIELD_ADDITION \
--source_format=NEWLINE_DELIMITED_JSON \
mydataset.mytable \
gs://mybucket/mydata.json

Ingresa el siguiente comando para anexar un archivo de datos JSON delimitado por saltos de línea en Cloud Storage a mydataset.mytable mediante un trabajo de carga. El esquema que contiene las columnas nuevas se especifica en un archivo de esquema JSON local, /tmp/myschema.json. mydataset se encuentra en myotherproject, no en tu proyecto predeterminado.

bq load \
--noreplace \
--schema_update_option=ALLOW_FIELD_ADDITION \
--source_format=NEWLINE_DELIMITED_JSON \
myotherproject:mydataset.mytable \
gs://mybucket/mydata.json \
/tmp/myschema.json

API

Realiza una llamada al método jobs.insert. Configura un trabajo load y establece las propiedades siguientes:

  • Haz referencia a tus datos en Cloud Storage mediante la propiedad sourceUris.
  • Para especificar el formato de datos, configura la propiedad sourceFormat.
  • Especifica el esquema en la propiedad schema.
  • Especifica la opción de actualización del esquema con la propiedad schemaUpdateOptions.
  • Establece la disposición de escritura de la tabla de destino en WRITE_APPEND con la propiedad writeDisposition.

Go

import (
	"context"
	"fmt"
	"os"

	"cloud.google.com/go/bigquery"
)

// createTableAndWidenLoad demonstrates augmenting a table's schema to add a new column via a load job.
func createTableAndWidenLoad(projectID, datasetID, tableID, filename string) error {
	// projectID := "my-project-id"
	// datasetID := "mydataset"
	// tableID := "mytable"
	ctx := context.Background()
	client, err := bigquery.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("bigquery.NewClient: %v", err)
	}
	defer client.Close()

	sampleSchema := bigquery.Schema{
		{Name: "full_name", Type: bigquery.StringFieldType},
	}
	meta := &bigquery.TableMetadata{
		Schema: sampleSchema,
	}
	tableRef := client.Dataset(datasetID).Table(tableID)
	if err := tableRef.Create(ctx, meta); err != nil {
		return err
	}
	// Now, import data from a local file, but specify field additions are allowed.
	// Because the data has a second column (age), the schema is amended as part of
	// the load.
	f, err := os.Open(filename)
	if err != nil {
		return err
	}
	source := bigquery.NewReaderSource(f)
	source.AutoDetect = true   // Allow BigQuery to determine schema.
	source.SkipLeadingRows = 1 // CSV has a single header line.

	loader := client.Dataset(datasetID).Table(tableID).LoaderFrom(source)
	loader.SchemaUpdateOptions = []string{"ALLOW_FIELD_ADDITION"}
	job, err := loader.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
	}
	return nil
}

Java

Antes de probar este ejemplo, sigue las instrucciones de configuración para Java que se encuentran en la guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de BigQuery para Java.

import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.Field;
import com.google.cloud.bigquery.FormatOptions;
import com.google.cloud.bigquery.Job;
import com.google.cloud.bigquery.JobId;
import com.google.cloud.bigquery.JobInfo;
import com.google.cloud.bigquery.JobInfo.SchemaUpdateOption;
import com.google.cloud.bigquery.JobInfo.WriteDisposition;
import com.google.cloud.bigquery.LegacySQLTypeName;
import com.google.cloud.bigquery.LoadJobConfiguration;
import com.google.cloud.bigquery.Schema;
import com.google.cloud.bigquery.TableId;
import com.google.common.collect.ImmutableList;
import java.util.UUID;

public class AddColumnLoadAppend {

  public static void runAddColumnLoadAppend() throws Exception {
    // TODO(developer): Replace these variables before running the sample.
    String datasetName = "MY_DATASET_NAME";
    String tableName = "MY_TABLE_NAME";
    String sourceUri = "/path/to/file.csv";
    addColumnLoadAppend(datasetName, tableName, sourceUri);
  }

  public static void addColumnLoadAppend(String datasetName, String tableName, String sourceUri)
      throws Exception {
    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();

      TableId tableId = TableId.of(datasetName, tableName);

      // Add a new column to a BigQuery table while appending rows via a load job.
      // 'REQUIRED' fields cannot  be added to an existing schema, so the additional column must be
      // 'NULLABLE'.
      Schema newSchema =
          Schema.of(
              Field.newBuilder("name", LegacySQLTypeName.STRING)
                  .setMode(Field.Mode.REQUIRED)
                  .build(),
              // Adding below additional column during the load job
              Field.newBuilder("post_abbr", LegacySQLTypeName.STRING)
                  .setMode(Field.Mode.NULLABLE)
                  .build());

      LoadJobConfiguration loadJobConfig =
          LoadJobConfiguration.builder(tableId, sourceUri)
              .setFormatOptions(FormatOptions.csv())
              .setWriteDisposition(WriteDisposition.WRITE_APPEND)
              .setSchema(newSchema)
              .setSchemaUpdateOptions(ImmutableList.of(SchemaUpdateOption.ALLOW_FIELD_ADDITION))
              .build();

      // Create a job ID so that we can safely retry.
      JobId jobId = JobId.of(UUID.randomUUID().toString());
      Job loadJob = bigquery.create(JobInfo.newBuilder(loadJobConfig).setJobId(jobId).build());

      // Load data from a GCS parquet file into the table
      // Blocks until this load table job completes its execution, either failing or succeeding.
      Job completedJob = loadJob.waitFor();

      // Check for errors
      if (completedJob == null) {
        throw new Exception("Job not executed since it no longer exists.");
      } else if (completedJob.getStatus().getError() != null) {
        // You can also look at queryJob.getStatus().getExecutionErrors() for all
        // errors, not just the latest one.
        throw new Exception(
            "BigQuery was unable to load into the table due to an error: \n"
                + loadJob.getStatus().getError());
      }
      System.out.println("Column successfully added during load append job");
    } catch (BigQueryException | InterruptedException e) {
      System.out.println("Column not added during load append \n" + e.toString());
    }
  }
}

Node.js

Antes de probar este ejemplo, sigue las instrucciones de configuración para Node.js que se encuentran en la guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de BigQuery para Node.js.

// Import the Google Cloud client libraries
const {BigQuery} = require('@google-cloud/bigquery');

// Instantiate client
const bigquery = new BigQuery();

async function addColumnLoadAppend() {
  // Adds a new column to a BigQuery table while appending rows via a load job.

  /**
   * TODO(developer): Uncomment the following lines before running the sample.
   */
  // const fileName = '/path/to/file.csv';
  // const datasetId = 'my_dataset';
  // const tableId = 'my_table';

  // In this example, the existing table contains only the 'Name', 'Age',
  // & 'Weight' columns. 'REQUIRED' fields cannot  be added to an existing
  // schema, so the additional column must be 'NULLABLE'.
  const schema = 'Name:STRING, Age:INTEGER, Weight:FLOAT, IsMagic:BOOLEAN';

  // Retrieve destination table reference
  const [table] = await bigquery
    .dataset(datasetId)
    .table(tableId)
    .get();
  const destinationTableRef = table.metadata.tableReference;

  // Set load job options
  const options = {
    schema: schema,
    schemaUpdateOptions: ['ALLOW_FIELD_ADDITION'],
    writeDisposition: 'WRITE_APPEND',
    destinationTable: destinationTableRef,
  };

  // Load data from a local file into the table
  const [job] = await bigquery
    .dataset(datasetId)
    .table(tableId)
    .load(fileName, options);

  console.log(`Job ${job.id} completed.`);
  console.log(`New Schema:`);
  console.log(job.configuration.load.schema.fields);

  // Check the job's status for errors
  const errors = job.status.errors;
  if (errors && errors.length > 0) {
    throw errors;
  }
}

Python

Antes de probar esta muestra, sigue las instrucciones de configuración para Python incluidas en la Guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de BigQuery para Python.

# from google.cloud import bigquery
# client = bigquery.Client()
# project = client.project
# dataset_ref = bigquery.DatasetReference(project, 'my_dataset')
# filepath = 'path/to/your_file.csv'

# Retrieves the destination table and checks the length of the schema
table_id = "my_table"
table_ref = dataset_ref.table(table_id)
table = client.get_table(table_ref)
print("Table {} contains {} columns.".format(table_id, len(table.schema)))

# Configures the load job to append the data to the destination table,
# allowing field addition
job_config = bigquery.LoadJobConfig()
job_config.write_disposition = bigquery.WriteDisposition.WRITE_APPEND
job_config.schema_update_options = [
    bigquery.SchemaUpdateOption.ALLOW_FIELD_ADDITION
]
# In this example, the existing table contains only the 'full_name' column.
# 'REQUIRED' fields cannot be added to an existing schema, so the
# additional column must be 'NULLABLE'.
job_config.schema = [
    bigquery.SchemaField("full_name", "STRING", mode="REQUIRED"),
    bigquery.SchemaField("age", "INTEGER", mode="NULLABLE"),
]
job_config.source_format = bigquery.SourceFormat.CSV
job_config.skip_leading_rows = 1

with open(filepath, "rb") as source_file:
    job = client.load_table_from_file(
        source_file,
        table_ref,
        location="US",  # Must match the destination dataset location.
        job_config=job_config,
    )  # API request

job.result()  # Waits for table load to complete.
print(
    "Loaded {} rows into {}:{}.".format(
        job.output_rows, dataset_id, table_ref.table_id
    )
)

# Checks the updated length of the schema
table = client.get_table(table)
print("Table {} now contains {} columns.".format(table_id, len(table.schema)))

Agrega una columna en un trabajo de anexo de consulta

Puedes agregar columnas a una tabla mientras le anexas resultados de consulta con uno de los siguientes métodos:

  • Mediante el comando bq query de la herramienta de línea de comandos de bq
  • Llamar al método jobs.insert de la API y configurar un trabajo query
  • Usar bibliotecas cliente

En la actualidad, Cloud Console o la IU web clásica de BigQuery no admiten agregar una columna durante una operación de anexo.

Cuando agregas columnas con una operación de anexo a un trabajo de consulta, el esquema de los resultados de la consulta se usa para actualizar el esquema de la tabla de destino. Ten en cuenta que no puedes consultar una tabla en una ubicación y escribir los resultados en una tabla de otra ubicación.

Para agregar una columna nueva cuando anexas datos a una tabla durante un trabajo de consulta, ten en cuenta esta información:

Console

No puedes agregar nuevas columnas a una tabla existente cuando anexas resultados de consulta mediante Cloud Console.

IU clásica

No puedes agregar columnas nuevas a una tabla existente cuando anexas resultados de consultas mediante la IU web clásica de BigQuery.

bq

Usa el comando bq query para consultar tus datos y especifica la marca --destination_table a fin de indicar qué tabla anexas.

Para especificar que anexas resultados de consulta a una tabla de destino existente, agrega la marca --append_table.

Establece la marca --schema_update_option en ALLOW_FIELD_ADDITION para indicar que los resultados de consulta que anexas contienen columnas nuevas.

Especifica la marca use_legacy_sql=false para usar la sintaxis de SQL estándar en la consulta.

Si la tabla que anexas se encuentra en un conjunto de datos de un proyecto distinto a tu proyecto predeterminado, debes agregar el ID del proyecto al nombre del conjunto de datos en el siguiente formato: project_id:dataset. Ten en cuenta que la tabla que consultas y la tabla de destino deben estar en la misma ubicación.

De forma opcional, puedes proporcionar la marca --location y establecer el valor según tu ubicación.

bq --location=location query \
--destination_table project_id:dataset.table \
--append_table \
--schema_update_option=ALLOW_FIELD_ADDITION \
--use_legacy_sql=false \
'query'

En el ejemplo anterior, se ilustra lo siguiente:

  • location es el nombre de tu ubicación. La marca --location es opcional. Por ejemplo, si usas BigQuery en la región de Tokio, configura el valor de la marca como asia-northeast1. Puedes configurar un valor predeterminado para la ubicación con el archivo .bigqueryrc. Ten en cuenta que no puedes agregar resultados de consultas a una tabla en otra ubicación.
  • project_id es el ID del proyecto.
  • dataset es el nombre del conjunto de datos que contiene la tabla que deseas agregar.
  • table es el nombre de la tabla que deseas agregar.
  • query es una consulta en la sintaxis de SQL estándar.

Ejemplos:

Ingresa el siguiente comando para consultar mydataset.mytable en tu proyecto predeterminado y anexar los resultados de consulta a mydataset.mytable2 (que también está en tu proyecto predeterminado).

bq query \
--destination_table mydataset.mytable2 \
--append_table \
--schema_update_option=ALLOW_FIELD_ADDITION \
--use_legacy_sql=false \
'SELECT
   column1,column2
 FROM
   mydataset.mytable'

Ingresa el siguiente comando para consultar mydataset.mytable en tu proyecto predeterminado y anexar los resultados de consulta a mydataset.mytable2 en myotherproject.

bq query \
--destination_table myotherproject:mydataset.mytable2 \
--append_table \
--schema_update_option=ALLOW_FIELD_ADDITION \
--use_legacy_sql=false \
'SELECT
   column1,column2
 FROM
   mydataset.mytable'

API

Realiza una llamada al método jobs.insert. Configura un trabajo query y establece las propiedades siguientes:

  • Especifica la tabla de destino con la propiedad destinationTable.
  • Establece la disposición de escritura de la tabla de destino en WRITE_APPEND con la propiedad writeDisposition.
  • Especifica la opción de actualización del esquema con la propiedad schemaUpdateOptions.
  • Especifica la consulta de SQL estándar mediante la propiedad query.

Go

import (
	"context"
	"fmt"

	"cloud.google.com/go/bigquery"
)

// createTableAndWidenQuery demonstrates how the schema of a table can be modified to add columns by appending
// query results that include the new columns.
func createTableAndWidenQuery(projectID, datasetID, tableID string) error {
	// projectID := "my-project-id"
	// datasetID := "mydataset"
	// tableID := "mytable"
	ctx := context.Background()
	client, err := bigquery.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("bigquery.NewClient: %v", err)
	}
	defer client.Close()

	// First, we create a sample table.
	sampleSchema := bigquery.Schema{
		{Name: "full_name", Type: bigquery.StringFieldType, Required: true},
		{Name: "age", Type: bigquery.IntegerFieldType, Required: true},
	}
	original := &bigquery.TableMetadata{
		Schema: sampleSchema,
	}
	tableRef := client.Dataset(datasetID).Table(tableID)
	if err := tableRef.Create(ctx, original); err != nil {
		return err
	}
	// Our table has two columns.  We'll introduce a new favorite_color column via
	// a subsequent query that appends to the table.
	q := client.Query("SELECT \"Timmy\" as full_name, 85 as age, \"Blue\" as favorite_color")
	q.SchemaUpdateOptions = []string{"ALLOW_FIELD_ADDITION"}
	q.QueryConfig.Dst = client.Dataset(datasetID).Table(tableID)
	q.WriteDisposition = bigquery.WriteAppend
	q.Location = "US"
	job, err := q.Run(ctx)
	if err != nil {
		return err
	}
	_, err = job.Wait(ctx)
	if err != nil {
		return err
	}
	return nil
}

Java

Antes de probar este ejemplo, sigue las instrucciones de configuración para Java que se encuentran en la guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de BigQuery para Java.

import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.Job;
import com.google.cloud.bigquery.JobInfo;
import com.google.cloud.bigquery.JobInfo.SchemaUpdateOption;
import com.google.cloud.bigquery.JobInfo.WriteDisposition;
import com.google.cloud.bigquery.QueryJobConfiguration;
import com.google.cloud.bigquery.TableId;
import com.google.cloud.bigquery.TableResult;
import com.google.common.collect.ImmutableList;

public class RelaxTableQuery {

  public static void runRelaxTableQuery() throws Exception {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "MY_PROJECT_ID";
    String datasetName = "MY_DATASET_NAME";
    String tableName = "MY_TABLE_NAME";
    relaxTableQuery(projectId, datasetName, tableName);
  }

  // To relax all columns in a destination table when you append data to it during a query job
  public static void relaxTableQuery(String projectId, String datasetName, String tableName)
      throws Exception {
    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();

      TableId tableId = TableId.of(datasetName, tableName);

      String sourceTable = "`" + projectId + "." + datasetName + "." + tableName + "`";
      String query = "SELECT word FROM " + sourceTable + " WHERE word like '%is%'";

      QueryJobConfiguration queryConfig =
          QueryJobConfiguration.newBuilder(query)
              // Use standard SQL syntax for queries.
              // See: https://cloud.google.com/bigquery/sql-reference/
              .setUseLegacySql(false)
              .setSchemaUpdateOptions(ImmutableList.of(SchemaUpdateOption.ALLOW_FIELD_RELAXATION))
              .setWriteDisposition(WriteDisposition.WRITE_APPEND)
              .setDestinationTable(tableId)
              .build();

      Job queryJob = bigquery.create(JobInfo.newBuilder(queryConfig).build());

      queryJob = queryJob.waitFor();

      // Check for errors
      if (queryJob == null) {
        throw new Exception("Job no longer exists");
      } else if (queryJob.getStatus().getError() != null) {
        // You can also look at queryJob.getStatus().getExecutionErrors() for all
        // errors, not just the latest one.
        throw new Exception(queryJob.getStatus().getError().toString());
      }

      // Get the results.
      TableResult results = queryJob.getQueryResults();

      // Print all pages of the results.
      results
          .iterateAll()
          .forEach(
              rows -> {
                rows.forEach(row -> System.out.println("row: " + row.toString()));
              });

      System.out.println("Successfully relaxed all columns in destination table during query job");
    } catch (BigQueryException | InterruptedException e) {
      System.out.println("Columns not relaxed during query job \n" + e.toString());
    }
  }
}

Node.js

Antes de probar este ejemplo, sigue las instrucciones de configuración para Node.js que se encuentran en la guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de BigQuery para Node.js.

// Import the Google Cloud client libraries
const {BigQuery} = require('@google-cloud/bigquery');

// Instantiate client
const bigquery = new BigQuery();

async function addColumnQueryAppend() {
  // Adds a new column to a BigQuery table while appending rows via a query job.

  /**
   * TODO(developer): Uncomment the following lines before running the sample.
   */
  // const datasetId = 'my_dataset';
  // const tableId = 'my_table';

  // Retrieve destination table reference
  const [table] = await bigquery
    .dataset(datasetId)
    .table(tableId)
    .get();
  const destinationTableRef = table.metadata.tableReference;

  // In this example, the existing table contains only the 'name' column.
  // 'REQUIRED' fields cannot  be added to an existing schema,
  // so the additional column must be 'NULLABLE'.
  const query = `SELECT name, year
    FROM \`bigquery-public-data.usa_names.usa_1910_2013\`
    WHERE state = 'TX'
    LIMIT 10`;

  // Set load job options
  const options = {
    query: query,
    schemaUpdateOptions: ['ALLOW_FIELD_ADDITION'],
    writeDisposition: 'WRITE_APPEND',
    destinationTable: destinationTableRef,
    // Location must match that of the dataset(s) referenced in the query.
    location: 'US',
  };

  const [job] = await bigquery.createQueryJob(options);
  console.log(`Job ${job.id} started.`);

  // Wait for the query to finish
  const [rows] = await job.getQueryResults();
  console.log(`Job ${job.id} completed.`);

  // Print the results
  console.log('Rows:');
  rows.forEach(row => console.log(row));
}

Python

Antes de probar esta muestra, sigue las instrucciones de configuración para Python incluidas en la Guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de BigQuery para Python.

from google.cloud import bigquery

# Construct a BigQuery client object.
client = bigquery.Client()

# TODO(developer): Set table_id to the ID of the destination table.
# table_id = "your-project.your_dataset.your_table_name"

# Retrieves the destination table and checks the length of the schema.
table = client.get_table(table_id)  # Make an API request.
print("Table {} contains {} columns".format(table_id, len(table.schema)))

# Configures the query to append the results to a destination table,
# allowing field addition.
job_config = bigquery.QueryJobConfig(
    destination=table_id,
    schema_update_options=[bigquery.SchemaUpdateOption.ALLOW_FIELD_ADDITION],
    write_disposition=bigquery.WriteDisposition.WRITE_APPEND,
)

# Start the query, passing in the extra configuration.
query_job = client.query(
    # In this example, the existing table contains only the 'full_name' and
    # 'age' columns, while the results of this query will contain an
    # additional 'favorite_color' column.
    'SELECT "Timmy" as full_name, 85 as age, "Blue" as favorite_color;',
    job_config=job_config,
)  # Make an API request.
query_job.result()  # Wait for the job to complete.

# Checks the updated length of the schema.
table = client.get_table(table_id)  # Make an API request.
print("Table {} now contains {} columns".format(table_id, len(table.schema)))

Disminuye la rigurosidad del modo de una columna

Por el momento, la única modificación que puedes hacer al modo de una columna es cambiar de REQUIRED a NULLABLE. Cambiar el modo de una columna de REQUIRED a NULLABLE se denomina disminución de la rigurosidad del modo de una columna. Puedes disminuir la rigurosidad de las columnas REQUIRED:

  • De forma manual
  • Cuando reemplazas una tabla con un trabajo de carga o consulta.
  • Cuando anexas datos a una tabla con un trabajo de consulta.

Cambia las columnas REQUIRED a NULLABLE de forma manual

Puedes cambiar de forma manual el modo de una columna de REQUIRED a NULLABLE con uno de los siguientes métodos:

  • Mediante Cloud Console o la IU web clásica de BigQuery
  • Mediante el comando bq update de la herramienta de línea de comandos de bq
  • Mediante una llamada al método de la API tables.patch
  • Usar bibliotecas cliente

Para cambiar de forma manual el modo de una columna de REQUIRED a NULLABLE, haz lo siguiente:

Console

En la actualidad, no puedes disminuir la rigurosidad del modo de una columna mediante Cloud Console.

IU clásica

  1. Expande tu conjunto de datos y selecciona tu tabla.

  2. En la página Detalles de la tabla, haz clic en la pestaña Esquema.

  3. Haz clic en la flecha hacia abajo a la derecha de la columna requerida y elige las opciones siguientes:

    • Make NULLABLE: disminuye la rigurosidad del modo de columna individual.
    • All REQUIRED to NULLABLE: cambia todas las columnas REQUIRED en la definición del esquema a NULLABLE.

      Disminuye la rigurosidad del modo de la columna

  4. En el cuadro de diálogo Confirm Mode Change, haz clic en Aceptar para cambiar el modo a NULLABLE. Ten en cuenta que este cambio no se puede deshacer.

bq

  1. Primero, ejecuta el comando bq show con la marca --schema y escribe el esquema de tabla existente en un archivo. Si la tabla que actualizas está en un proyecto que no es tu proyecto predeterminado, agrega el ID del proyecto al nombre del conjunto de datos en el siguiente formato: project_id:dataset.

    bq show \
    --schema \
    --format=prettyjson \
    project_id:dataset.table > schema_file
    

    En el ejemplo anterior, se ilustra lo siguiente:

    • project_id es el ID del proyecto.
    • dataset es el nombre del conjunto de datos que contiene la tabla que deseas actualizar.
    • table es el nombre de la tabla que deseas actualizar.
    • schema_file es el archivo de definición de esquema que se escribe en tu máquina local.

    Por ejemplo, para escribir la definición de esquema de mydataset.mytable en un archivo, ingresa el siguiente comando. mydataset.mytable está en tu proyecto predeterminado.

      bq show \
      --schema \
      --format=prettyjson \
      mydataset.mytable > /tmp/myschema.json
    
  2. Abre el archivo del esquema en un editor de texto. El esquema debe verse de la manera siguiente:

    [
      {
        "mode": "REQUIRED",
        "name": "column1",
        "type": "STRING"
      },
      {
        "mode": "REQUIRED",
        "name": "column2",
        "type": "FLOAT"
      },
      {
        "mode": "REPEATED",
        "name": "column3",
        "type": "STRING"
      }
    ]
    
  3. Cambia el modo de una columna existente de REQUIRED a NULLABLE. En este ejemplo, se disminuye la rigurosidad del modo de column1.

    [
      {
        "mode": "NULLABLE",
        "name": "column1",
        "type": "STRING"
      },
      {
        "mode": "REQUIRED",
        "name": "column2",
        "type": "FLOAT"
      },
      {
        "mode": "REPEATED",
        "name": "column3",
        "type": "STRING"
      }
    ]
    

    Para obtener más información sobre cómo trabajar con archivos de esquema JSON, consulta Especifica un archivo de esquema JSON.

  4. Después de actualizar tu archivo de esquema, ejecuta el comando siguiente para actualizar el esquema de la tabla. Si la tabla que actualizas está en un proyecto que no es tu proyecto predeterminado, agrega el ID del proyecto al nombre del conjunto de datos en el siguiente formato: project_id:dataset.

    bq update project_id:dataset.table schema
    

    En el ejemplo anterior, se ilustra lo siguiente:

    • project_id es el ID del proyecto.
    • dataset es el nombre del conjunto de datos que contiene la tabla que deseas actualizar.
    • table es el nombre de la tabla que deseas actualizar.
    • schema es la ruta al archivo de esquema JSON en tu máquina local.

    Por ejemplo, ingresa el siguiente comando para actualizar la definición de esquema de mydataset.mytable en tu proyecto predeterminado. La ruta al archivo de esquema en tu máquina local es /tmp/myschema.json.

      bq update mydataset.mytable /tmp/myschema.json
    

API

Llama a tables.patch y usa la propiedad schema para cambiar una columna REQUIRED a NULLABLE en tu definición de esquema. Debido a que, con el método tables.update se reemplaza todo el recurso de tabla, es preferible usar el método tables.patch.

Go

import (
	"context"
	"fmt"

	"cloud.google.com/go/bigquery"
)

// relaxTableAPI demonstrates modifying the schema of a table to remove the requirement that columns allow
// no NULL values.
func relaxTableAPI(projectID, datasetID, tableID string) error {
	// projectID := "my-project-id"
	// datasetID := "mydatasetid"
	// tableID := "mytableid"
	ctx := context.Background()

	client, err := bigquery.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("bigquery.NewClient: %v", err)
	}
	defer client.Close()

	// Setup: We first create a table with a schema that's restricts NULL values.
	sampleSchema := bigquery.Schema{
		{Name: "full_name", Type: bigquery.StringFieldType, Required: true},
		{Name: "age", Type: bigquery.IntegerFieldType, Required: true},
	}
	original := &bigquery.TableMetadata{
		Schema: sampleSchema,
	}
	if err := client.Dataset(datasetID).Table(tableID).Create(ctx, original); err != nil {
		return err
	}

	tableRef := client.Dataset(datasetID).Table(tableID)
	meta, err := tableRef.Metadata(ctx)
	if err != nil {
		return err
	}
	// Iterate through the schema to set all Required fields to false (nullable).
	var relaxed bigquery.Schema
	for _, v := range meta.Schema {
		v.Required = false
		relaxed = append(relaxed, v)
	}
	newMeta := bigquery.TableMetadataToUpdate{
		Schema: relaxed,
	}
	if _, err := tableRef.Update(ctx, newMeta, meta.ETag); err != nil {
		return err
	}
	return nil
}

Java

Antes de probar este ejemplo, sigue las instrucciones de configuración para Java que se encuentran en la guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de BigQuery para Java.

import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.Field;
import com.google.cloud.bigquery.LegacySQLTypeName;
import com.google.cloud.bigquery.Schema;
import com.google.cloud.bigquery.StandardTableDefinition;
import com.google.cloud.bigquery.Table;

public class RelaxColumnMode {

  public static void runRelaxColumnMode() {
    // TODO(developer): Replace these variables before running the sample.
    String datasetName = "MY_DATASET_NAME";
    String tableId = "MY_TABLE_NAME";
    relaxColumnMode(datasetName, tableId);
  }

  public static void relaxColumnMode(String datasetName, String tableId) {
    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();

      Table table = bigquery.getTable(datasetName, tableId);

      // Create new relaxed schema based on the existing table schema
      Schema relaxedSchema =
          Schema.of(
              // The only supported modification you can make to a column's mode is changing it from
              // REQUIRED to NULLABLE
              // Changing a column's mode from REQUIRED to NULLABLE is also called column relaxation
              // INFO: LegacySQLTypeName will be updated to StandardSQLTypeName in release 1.103.0
              Field.newBuilder("word", LegacySQLTypeName.STRING)
                  .setMode(Field.Mode.NULLABLE)
                  .build(),
              Field.newBuilder("word_count", LegacySQLTypeName.STRING)
                  .setMode(Field.Mode.NULLABLE)
                  .build(),
              Field.newBuilder("corpus", LegacySQLTypeName.STRING)
                  .setMode(Field.Mode.NULLABLE)
                  .build(),
              Field.newBuilder("corpus_date", LegacySQLTypeName.STRING)
                  .setMode(Field.Mode.NULLABLE)
                  .build());

      // Update the table with the new schema
      Table updatedTable =
          table.toBuilder().setDefinition(StandardTableDefinition.of(relaxedSchema)).build();
      updatedTable.update();
      System.out.println("Table schema successfully relaxed.");
    } catch (BigQueryException e) {
      System.out.println("Table schema not relaxed \n" + e.toString());
    }
  }
}

Node.js

Antes de probar este ejemplo, sigue las instrucciones de configuración para Node.js que se encuentran en la guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de BigQuery para Node.js.

// Import the Google Cloud client library and create a client
const {BigQuery} = require('@google-cloud/bigquery');
const bigquery = new BigQuery();

async function relaxColumn() {
  /**
   * Changes columns from required to nullable.
   * Assumes existing table with the following schema:
   * [{name: 'Name', type: 'STRING', mode: 'REQUIRED'},
   * {name: 'Age', type: 'INTEGER'},
   * {name: 'Weight', type: 'FLOAT'},
   * {name: 'IsMagic', type: 'BOOLEAN'}];
   */

  /**
   * TODO(developer): Uncomment the following lines before running the sample.
   */
  // const datasetId = 'my_dataset';
  // const tableId = 'my_table';

  const newSchema = [
    {name: 'Name', type: 'STRING', mode: 'NULLABLE'},
    {name: 'Age', type: 'INTEGER'},
    {name: 'Weight', type: 'FLOAT'},
    {name: 'IsMagic', type: 'BOOLEAN'},
  ];

  // Retrieve current table metadata
  const table = bigquery.dataset(datasetId).table(tableId);
  const [metadata] = await table.getMetadata();

  // Update schema
  metadata.schema = newSchema;
  const [apiResponse] = await table.setMetadata(metadata);

  console.log(apiResponse.schema.fields);
}

Python

Antes de probar esta muestra, sigue las instrucciones de configuración para Python incluidas en la Guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de BigQuery para Python.

Reemplaza la propiedad Table.schema por una lista de objetos SchemaField que tenga la propiedad mode establecida como 'NULLABLE'

# from google.cloud import bigquery
# client = bigquery.Client()
# dataset_id = 'my_dataset'
# table_id = 'my_table'

original_schema = [
    bigquery.SchemaField("full_name", "STRING", mode="REQUIRED"),
    bigquery.SchemaField("age", "INTEGER", mode="REQUIRED"),
]

dataset_ref = bigquery.DatasetReference(project, dataset_id)
table_ref = dataset_ref.table(table_id)
table = bigquery.Table(table_ref, schema=original_schema)
table = client.create_table(table)
assert all(field.mode == "REQUIRED" for field in table.schema)

# SchemaField properties cannot be edited after initialization.
# To make changes, construct new SchemaField objects.
relaxed_schema = [
    bigquery.SchemaField("full_name", "STRING", mode="NULLABLE"),
    bigquery.SchemaField("age", "INTEGER", mode="NULLABLE"),
]
table.schema = relaxed_schema
table = client.update_table(table, ["schema"])

assert all(field.mode == "NULLABLE" for field in table.schema)

Cambia REQUIRED a NULLABLE en un trabajo de carga o consulta

Puedes disminuir la rigurosidad de las columnas REQUIRED a NULLABLE en un esquema de tabla existente cuando cargas datos en ella y eliges reemplazar la tabla existente. Cuando reemplazas una tabla existente, el esquema de los datos que cargaste se usa para reemplazar el esquema de la tabla existente. Para obtener información sobre cómo reemplazar una tabla con un trabajo de carga, consulta:

También puedes disminuir la rigurosidad de las columnas REQUIRED a NULLABLE en un esquema de tabla existente cuando agregas datos a estas con un trabajo de consulta.

Cambia REQUIRED a NULLABLE en un trabajo agregado de carga

Puedes disminuir la rigurosidad del modo de una columna mientras anexas datos a una tabla en un trabajo de carga con uno de los siguientes métodos:

  • Mediante el comando bq load de la herramienta de línea de comandos de bq
  • Llamar al método jobs.insert de la API y configurar un trabajo de carga
  • Usar bibliotecas cliente

En la actualidad, Cloud Console o la IU web clásica de BigQuery no admiten el cambio del modo de una columna durante una operación de anexo.

Cuando disminuyes la rigurosidad del modo de una columna con una operación de anexo en un trabajo de carga, puedes hacer estas acciones:

  • Disminuir la rigurosidad del modo para las columnas individuales mediante la especificación de un archivo de esquema JSON (cuando agregas datos de los archivos CSV y JSON).
  • Disminuir la rigurosidad de las columnas a null en tu esquema de Avro, ORC o Parquet y permite que la inferencia de esquemas detecte las columnas con rigurosidad disminuida

A la hora de disminuir la rigurosidad de una columna de REQUIRED a NULLABLE cuando agregas datos a una tabla durante un trabajo de carga, ten en cuenta esta información:

Console

En la actualidad, no puedes disminuir la rigurosidad del modo de una columna mediante Cloud Console.

IU clásica

No puedes disminuir la rigurosidad del modo de una columna existente cuando anexas datos a una tabla en un trabajo de carga mediante la IU web clásica de BigQuery.

bq

Usa el comando bq load para cargar tus datos y especifica la marca --noreplace a fin de indicar que agregas los datos a una tabla existente.

Si los datos que agregas están en formato CSV o JSON delimitado por saltos de línea, especifica las columnas con rigurosidad disminuida en un archivo de esquema JSON local o usa la marca --autodetect a fin de usar la detección del esquema para detectar las columnas con rigurosidad disminuida en los datos de origen. Para obtener más información sobre cómo disminuir la rigurosidad de los modos de columna con el archivo de esquema JSON, consulta cómo cambiar las columnas REQUIRED a NULLABLE de forma manual.

Las columnas con rigurosidad disminuida se pueden inferir de forma automática en los archivos Avro, ORC y Parquet. La disminución de la rigurosidad de columnas no se aplica a los anexos de exportación de Datastore. Las columnas en las tablas creadas mediante la carga de archivos de exportación de Datastore siempre son NULLABLE.

Establece la marca --schema_update_option en ALLOW_FIELD_RELAXATION para indicar que los datos que anexas contienen columnas con rigurosidad disminuida.

Si la tabla que anexas se encuentra en un conjunto de datos de un proyecto distinto a tu proyecto predeterminado, debes agregar el ID del proyecto al nombre del conjunto de datos en el siguiente formato: project_id:dataset.

De forma opcional, puedes proporcionar la marca --location y establecer el valor según tu ubicación.

Ingresa el comando load de la siguiente manera:

bq --location=location load \
--noreplace \
--schema_update_option=ALLOW_FIELD_RELAXATION \
--source_format=format \
project_id:dataset.table \
path_to_source \
schema

En el ejemplo anterior, se ilustra lo siguiente:

  • location es el nombre de tu ubicación. La marca --location es opcional. Por ejemplo, si usas BigQuery en la región de Tokio, configura el valor de la marca como asia-northeast1. Puedes configurar un valor predeterminado para la ubicación con el archivo .bigqueryrc.
  • format es NEWLINE_DELIMITED_JSON, CSV PARQUET, ORC o AVRO. Los archivos DATASTORE_BACKUP no requieren disminuir la rigurosidad de las columnas. Las columnas de las tablas creadas a partir de archivos de exportación de Datastore siempre son NULLABLE.
  • project_id es el ID del proyecto.
  • dataset es el nombre del conjunto de datos que contiene la tabla.
  • table es el nombre de la tabla que deseas agregar.
  • path_to_source es un URI de Cloud Storage completamente calificado, una lista de URI separada por comas o la ruta a un archivo de datos en tu máquina local.
  • schema es la ruta a un archivo de esquema JSON local. Esta opción se usa solo para los archivos CSV y JSON. Las columnas con rigurosidad disminuida se infieren de forma automática desde los archivos Avro.

Ejemplos:

Ingresa el siguiente comando para anexar un archivo de datos de Avro local, /tmp/mydata.avro, a mydataset.mytable mediante un trabajo de carga. Debido a que las columnas con rigurosidad disminuida se pueden inferir de forma automática de los datos de Avro, no necesitas especificar un archivo de esquema. mydataset está en tu proyecto predeterminado.

bq load \
--noreplace \
--schema_update_option=ALLOW_FIELD_RELAXATION \
--source_format=AVRO \
mydataset.mytable \
/tmp/mydata.avro

Ingresa el siguiente comando para agregar datos de un archivo JSON delimitado por saltos de línea en Cloud Storage a mydataset.mytable mediante un trabajo de carga. El esquema que contiene las columnas con rigurosidad disminuida está en un archivo de esquema JSON local, /tmp/myschema.json. mydataset está en tu proyecto predeterminado.

bq load \
--noreplace \
--schema_update_option=ALLOW_FIELD_RELAXATION \
--source_format=NEWLINE_DELIMITED_JSON \
mydataset.mytable \
gs://mybucket/mydata.json \
/tmp/myschema.json

Ingresa el siguiente comando para anexar datos de un archivo CSV en tu máquina local a mydataset.mytable mediante un trabajo de carga. El comando usa la detección automática de esquemas para detectar las columnas con rigurosidad disminuida en los datos de origen. mydataset se encuentra en myotherproject, no en tu proyecto predeterminado.

bq load \
--noreplace \
--schema_update_option=ALLOW_FIELD_RELAXATION \
--source_format=CSV \
--autodetect \
myotherproject:mydataset.mytable \
mydata.csv

API

Realiza una llamada al método jobs.insert. Configura un trabajo load y establece las propiedades siguientes:

  • Haz referencia a tus datos en Cloud Storage mediante la propiedad sourceUris.
  • Para especificar el formato de datos, configura la propiedad sourceFormat.
  • Especifica el esquema en la propiedad schema.
  • Especifica la opción de actualización del esquema con la propiedad schemaUpdateOptions.
  • Establece la disposición de escritura de la tabla de destino en WRITE_APPEND con la propiedad writeDisposition.

Go

import (
	"context"
	"fmt"
	"os"

	"cloud.google.com/go/bigquery"
)

// relaxTableImport demonstrates amending the schema of a table to relax columns from
// not allowing NULL values to allowing them.
func relaxTableImport(projectID, datasetID, tableID, filename string) error {
	// projectID := "my-project-id"
	// datasetID := "mydataset"
	// tableID := "mytable"
	ctx := context.Background()
	client, err := bigquery.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("bigquery.NewClient: %v", err)
	}
	defer client.Close()

	sampleSchema := bigquery.Schema{
		{Name: "full_name", Type: bigquery.StringFieldType, Required: true},
		{Name: "age", Type: bigquery.IntegerFieldType, Required: true},
	}
	meta := &bigquery.TableMetadata{
		Schema: sampleSchema,
	}
	tableRef := client.Dataset(datasetID).Table(tableID)
	if err := tableRef.Create(ctx, meta); err != nil {
		return err
	}
	// Now, import data from a local file, but specify relaxation of required
	// fields as a side effect while the data is appended.
	f, err := os.Open(filename)
	if err != nil {
		return err
	}
	source := bigquery.NewReaderSource(f)
	source.AutoDetect = true   // Allow BigQuery to determine schema.
	source.SkipLeadingRows = 1 // CSV has a single header line.

	loader := client.Dataset(datasetID).Table(tableID).LoaderFrom(source)
	loader.SchemaUpdateOptions = []string{"ALLOW_FIELD_RELAXATION"}
	job, err := loader.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
	}
	return nil
}

Java

Antes de probar este ejemplo, sigue las instrucciones de configuración para Java que se encuentran en la guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de BigQuery para Java.

import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.CsvOptions;
import com.google.cloud.bigquery.Field;
import com.google.cloud.bigquery.Job;
import com.google.cloud.bigquery.JobInfo;
import com.google.cloud.bigquery.LoadJobConfiguration;
import com.google.cloud.bigquery.Schema;
import com.google.cloud.bigquery.StandardSQLTypeName;
import com.google.cloud.bigquery.Table;
import com.google.cloud.bigquery.TableId;
import com.google.common.collect.ImmutableList;

// Sample to append relax column in a table.
public class RelaxColumnLoadAppend {

  public static void main(String[] args) {
    // TODO(developer): Replace these variables before running the sample.
    String datasetName = "MY_DATASET_NAME";
    String tableName = "MY_TABLE_NAME";
    String sourceUri = "gs://cloud-samples-data/bigquery/us-states/us-states.csv";
    relaxColumnLoadAppend(datasetName, tableName, sourceUri);
  }

  public static void relaxColumnLoadAppend(String datasetName, String tableName, String sourceUri) {
    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();

      // Retrieve destination table reference
      Table table = bigquery.getTable(TableId.of(datasetName, tableName));

      // column as a 'REQUIRED' field.
      Field name =
          Field.newBuilder("name", StandardSQLTypeName.STRING).setMode(Field.Mode.REQUIRED).build();
      Field postAbbr =
          Field.newBuilder("post_abbr", StandardSQLTypeName.STRING)
              .setMode(Field.Mode.REQUIRED)
              .build();
      Schema schema = Schema.of(name, postAbbr);

      // Skip header row in the file.
      CsvOptions csvOptions = CsvOptions.newBuilder().setSkipLeadingRows(1).build();

      // Set job options
      LoadJobConfiguration loadConfig =
          LoadJobConfiguration.newBuilder(table.getTableId(), sourceUri)
              .setSchema(schema)
              .setFormatOptions(csvOptions)
              .setSchemaUpdateOptions(
                  ImmutableList.of(JobInfo.SchemaUpdateOption.ALLOW_FIELD_RELAXATION))
              .setWriteDisposition(JobInfo.WriteDisposition.WRITE_APPEND)
              .build();

      // Create a load job and wait for it to complete.
      Job job = bigquery.create(JobInfo.of(loadConfig));
      job = job.waitFor();
      // Check the job's status for errors
      if (job.isDone() && job.getStatus().getError() == null) {
        System.out.println("Relax column append successfully loaded in a table");
      } else {
        System.out.println(
            "BigQuery was unable to load into the table due to an error:"
                + job.getStatus().getError());
      }
    } catch (BigQueryException | InterruptedException e) {
      System.out.println("Column not added during load append \n" + e.toString());
    }
  }
}

Node.js

Antes de probar este ejemplo, sigue las instrucciones de configuración para Node.js que se encuentran en la guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de BigQuery para Node.js.

// Import the Google Cloud client libraries
const {BigQuery} = require('@google-cloud/bigquery');

// Instantiate client
const bigquery = new BigQuery();

async function relaxColumnLoadAppend() {
  // Changes required column to nullable in load append job.

  /**
   * TODO(developer): Uncomment the following lines before running the sample.
   */
  // const fileName = '/path/to/file.csv';
  // const datasetId = 'my_dataset';
  // const tableId = 'my_table';

  // In this example, the existing table contains the 'Name'
  // column as a 'REQUIRED' field.
  const schema = 'Age:INTEGER, Weight:FLOAT, IsMagic:BOOLEAN';

  // Retrieve destination table reference
  const [table] = await bigquery
    .dataset(datasetId)
    .table(tableId)
    .get();
  const destinationTableRef = table.metadata.tableReference;

  // Set load job options
  const options = {
    schema: schema,
    schemaUpdateOptions: ['ALLOW_FIELD_RELAXATION'],
    writeDisposition: 'WRITE_APPEND',
    destinationTable: destinationTableRef,
  };

  // Load data from a local file into the table
  const [job] = await bigquery
    .dataset(datasetId)
    .table(tableId)
    .load(fileName, options);

  console.log(`Job ${job.id} completed.`);

  // Check the job's status for errors
  const errors = job.status.errors;
  if (errors && errors.length > 0) {
    throw errors;
  }
}

Python

Antes de probar esta muestra, sigue las instrucciones de configuración para Python incluidas en la Guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de BigQuery para Python.

# from google.cloud import bigquery
# client = bigquery.Client()
# project = client.project
# dataset_ref = bigquery.DatasetReference(project, 'my_dataset')
# filepath = 'path/to/your_file.csv'

# Retrieves the destination table and checks the number of required fields
table_id = "my_table"
table_ref = dataset_ref.table(table_id)
table = client.get_table(table_ref)
original_required_fields = sum(field.mode == "REQUIRED" for field in table.schema)
# In this example, the existing table has 3 required fields.
print("{} fields in the schema are required.".format(original_required_fields))

# Configures the load job to append the data to a destination table,
# allowing field relaxation
job_config = bigquery.LoadJobConfig()
job_config.write_disposition = bigquery.WriteDisposition.WRITE_APPEND
job_config.schema_update_options = [
    bigquery.SchemaUpdateOption.ALLOW_FIELD_RELAXATION
]
# In this example, the existing table contains three required fields
# ('full_name', 'age', and 'favorite_color'), while the data to load
# contains only the first two fields.
job_config.schema = [
    bigquery.SchemaField("full_name", "STRING", mode="REQUIRED"),
    bigquery.SchemaField("age", "INTEGER", mode="REQUIRED"),
]
job_config.source_format = bigquery.SourceFormat.CSV
job_config.skip_leading_rows = 1

with open(filepath, "rb") as source_file:
    job = client.load_table_from_file(
        source_file,
        table_ref,
        location="US",  # Must match the destination dataset location.
        job_config=job_config,
    )  # API request

job.result()  # Waits for table load to complete.
print(
    "Loaded {} rows into {}:{}.".format(
        job.output_rows, dataset_id, table_ref.table_id
    )
)

# Checks the updated number of required fields
table = client.get_table(table)
current_required_fields = sum(field.mode == "REQUIRED" for field in table.schema)
print("{} fields in the schema are now required.".format(current_required_fields))

Cambia de REQUIRED a NULLABLE en un trabajo de anexo de consulta

Puedes disminuir la rigurosidad de todas las columnas de una tabla mientras le anexas resultados de consulta con uno de los siguientes métodos:

  • Mediante el comando bq query de la herramienta de línea de comandos de bq
  • Llamar al método jobs.insert de la API y configurar un trabajo de consulta
  • Usar bibliotecas cliente

En la actualidad, Cloud Console o la IU web clásica de BigQuery no admiten disminuir la rigurosidad de columnas durante una operación de anexo.

Cuando disminuyes la rigurosidad de las columnas mediante una operación de anexo en un trabajo de consulta, puedes disminuir la rigurosidad de todos los campos obligatorios en la tabla de destino si estableces la marca --schema_update_option en ALLOW_FIELD_RELAXATION. No puedes reducir la rigurosidad de columnas individuales en una tabla de destino mediante un anexo de consulta.

Para disminuir la rigurosidad de todas las columnas en una tabla de destino cuando agregas los datos a esta durante un trabajo de consulta, haz lo siguiente:

Console

En la actualidad, no puedes disminuir la rigurosidad del modo de una columna mediante Cloud Console.

IU clásica

No puedes disminuir la rigurosidad de las columnas en una tabla de destino cuando agregas los resultados de la consulta mediante la IU web de BigQuery.

bq

Usa el comando bq query para consultar tus datos y especifica la marca --destination_table a fin de indicar qué tabla anexas.

Para especificar que anexas resultados de consulta a una tabla de destino existente, agrega la marca --append_table.

Establece la marca --schema_update_option en ALLOW_FIELD_RELAXATION para indicar que todas las columnas REQUIRED en la tabla que anexas deben cambiarse a NULLABLE.

Especifica la marca use_legacy_sql=false para usar la sintaxis de SQL estándar en la consulta.

Si la tabla que anexas se encuentra en un conjunto de datos de un proyecto distinto a tu proyecto predeterminado, debes agregar el ID del proyecto al nombre del conjunto de datos en el siguiente formato: project_id:dataset.

De forma opcional, puedes proporcionar la marca --location y establecer el valor según tu ubicación.

bq --location=location query \
--destination_table project_id:dataset.table \
--append_table \
--schema_update_option=ALLOW_FIELD_RELAXATION \
--use_legacy_sql=false \
'query'

En el ejemplo anterior, se ilustra lo siguiente:

  • location es el nombre de tu ubicación. La marca --location es opcional. Por ejemplo, si usas BigQuery en la región de Tokio, configura el valor de la marca como asia-northeast1. Puedes configurar un valor predeterminado para la ubicación con el archivo .bigqueryrc.
  • project_id es el ID del proyecto.
  • dataset es el nombre del conjunto de datos que contiene la tabla que deseas agregar.
  • table es el nombre de la tabla que deseas agregar.
  • query es una consulta en la sintaxis de SQL estándar.

Ejemplos:

Ingresa el siguiente comando para consultar mydataset.mytable en tu proyecto predeterminado y anexar los resultados de consulta a mydataset.mytable2 (que también está en tu proyecto predeterminado). El comando cambia todas las columnas REQUIRED de la tabla de destino a NULLABLE.

bq query \
--destination_table mydataset.mytable2 \
--append_table \
--schema_update_option=ALLOW_FIELD_RELAXATION \
--use_legacy_sql=false \
'SELECT
   column1,column2
 FROM
   mydataset.mytable'

Ingresa el siguiente comando para consultar mydataset.mytable en tu proyecto predeterminado y anexar los resultados de consulta a mydataset.mytable2 en myotherproject. El comando cambia todas las columnas REQUIRED de la tabla de destino a NULLABLE.

bq query \
--destination_table myotherproject:mydataset.mytable2 \
--append_table \
--schema_update_option=ALLOW_FIELD_RELAXATION \
--use_legacy_sql=false \
'SELECT
   column1,column2
 FROM
   mydataset.mytable'

API

Realiza una llamada al método jobs.insert. Configura un trabajo query y establece las propiedades siguientes:

  • Especifica la tabla de destino con la propiedad destinationTable.
  • Establece la disposición de escritura de la tabla de destino en WRITE_APPEND con la propiedad writeDisposition.
  • Especifica la opción de actualización del esquema con la propiedad schemaUpdateOptions.
  • Especifica la consulta de SQL estándar mediante la propiedad query.

Go

import (
	"context"
	"fmt"

	"cloud.google.com/go/bigquery"
)

// relaxTableQuery demonstrates relaxing the schema of a table by appending query results to
// enable the table to allow NULL values.
func relaxTableQuery(projectID, datasetID, tableID string) error {
	// projectID := "my-project-id"
	// datasetID := "mydataset"
	// tableID := "mytable"
	ctx := context.Background()
	client, err := bigquery.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("bigquery.NewClient: %v", err)
	}
	defer client.Close()

	sampleSchema := bigquery.Schema{
		{Name: "full_name", Type: bigquery.StringFieldType, Required: true},
		{Name: "age", Type: bigquery.IntegerFieldType, Required: true},
	}
	meta := &bigquery.TableMetadata{
		Schema: sampleSchema,
	}
	tableRef := client.Dataset(datasetID).Table(tableID)
	if err := tableRef.Create(ctx, meta); err != nil {
		return err
	}
	// Now, append a query result that includes nulls, but allow the job to relax
	// all required columns.
	q := client.Query("SELECT \"Beyonce\" as full_name")
	q.QueryConfig.Dst = client.Dataset(datasetID).Table(tableID)
	q.SchemaUpdateOptions = []string{"ALLOW_FIELD_RELAXATION"}
	q.WriteDisposition = bigquery.WriteAppend
	q.Location = "US"
	job, err := q.Run(ctx)
	if err != nil {
		return err
	}
	_, err = job.Wait(ctx)
	if err != nil {
		return err
	}
	return nil
}

Java

Antes de probar este ejemplo, sigue las instrucciones de configuración para Java que se encuentran en la guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de BigQuery para Java.

import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.Job;
import com.google.cloud.bigquery.JobInfo;
import com.google.cloud.bigquery.JobInfo.SchemaUpdateOption;
import com.google.cloud.bigquery.JobInfo.WriteDisposition;
import com.google.cloud.bigquery.QueryJobConfiguration;
import com.google.cloud.bigquery.TableId;
import com.google.cloud.bigquery.TableResult;
import com.google.common.collect.ImmutableList;

public class RelaxTableQuery {

  public static void runRelaxTableQuery() throws Exception {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "MY_PROJECT_ID";
    String datasetName = "MY_DATASET_NAME";
    String tableName = "MY_TABLE_NAME";
    relaxTableQuery(projectId, datasetName, tableName);
  }

  // To relax all columns in a destination table when you append data to it during a query job
  public static void relaxTableQuery(String projectId, String datasetName, String tableName)
      throws Exception {
    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();

      TableId tableId = TableId.of(datasetName, tableName);

      String sourceTable = "`" + projectId + "." + datasetName + "." + tableName + "`";
      String query = "SELECT word FROM " + sourceTable + " WHERE word like '%is%'";

      QueryJobConfiguration queryConfig =
          QueryJobConfiguration.newBuilder(query)
              // Use standard SQL syntax for queries.
              // See: https://cloud.google.com/bigquery/sql-reference/
              .setUseLegacySql(false)
              .setSchemaUpdateOptions(ImmutableList.of(SchemaUpdateOption.ALLOW_FIELD_RELAXATION))
              .setWriteDisposition(WriteDisposition.WRITE_APPEND)
              .setDestinationTable(tableId)
              .build();

      Job queryJob = bigquery.create(JobInfo.newBuilder(queryConfig).build());

      queryJob = queryJob.waitFor();

      // Check for errors
      if (queryJob == null) {
        throw new Exception("Job no longer exists");
      } else if (queryJob.getStatus().getError() != null) {
        // You can also look at queryJob.getStatus().getExecutionErrors() for all
        // errors, not just the latest one.
        throw new Exception(queryJob.getStatus().getError().toString());
      }

      // Get the results.
      TableResult results = queryJob.getQueryResults();

      // Print all pages of the results.
      results
          .iterateAll()
          .forEach(
              rows -> {
                rows.forEach(row -> System.out.println("row: " + row.toString()));
              });

      System.out.println("Successfully relaxed all columns in destination table during query job");
    } catch (BigQueryException | InterruptedException e) {
      System.out.println("Columns not relaxed during query job \n" + e.toString());
    }
  }
}

Python

Antes de probar esta muestra, sigue las instrucciones de configuración para Python incluidas en la Guía de inicio rápido de BigQuery sobre cómo usar bibliotecas cliente. Si deseas obtener más información, consulta la documentación de referencia de la API de BigQuery para Python.

from google.cloud import bigquery

# Construct a BigQuery client object.
client = bigquery.Client()

# TODO(developer): Set table_id to the ID of the destination table.
# table_id = "your-project.your_dataset.your_table_name"

# Retrieves the destination table and checks the number of required fields.
table = client.get_table(table_id)  # Make an API request.
original_required_fields = sum(field.mode == "REQUIRED" for field in table.schema)

# In this example, the existing table has 2 required fields.
print("{} fields in the schema are required.".format(original_required_fields))

# Configures the query to append the results to a destination table,
# allowing field relaxation.
job_config = bigquery.QueryJobConfig(
    destination=table_id,
    schema_update_options=[bigquery.SchemaUpdateOption.ALLOW_FIELD_RELAXATION],
    write_disposition=bigquery.WriteDisposition.WRITE_APPEND,
)

# Start the query, passing in the extra configuration.
query_job = client.query(
    # In this example, the existing table contains 'full_name' and 'age' as
    # required columns, but the query results will omit the second column.
    'SELECT "Beyonce" as full_name;',
    job_config=job_config,
)  # Make an API request.
query_job.result()  # Wait for the job to complete.

# Checks the updated number of required fields.
table = client.get_table(table_id)  # Make an API request.
current_required_fields = sum(field.mode == "REQUIRED" for field in table.schema)
print("{} fields in the schema are now required.".format(current_required_fields))