Access historical data
BigQuery lets you query and restore data stored inBigQuery that has been changed or deleted within yourtime travel window.
Query data at a point in time
You can query a table's historical data from any point in time within thetime travel window by using aFOR SYSTEM_TIME AS OFclause. This clause takes a constant timestamp expression and references theversion of the table that was current at that timestamp. The table must bestored in BigQuery; it cannot be an external table. There is nolimit on table size when usingSYSTEM_TIME AS OF.
For example, the following query returns a historical version of the tablefrom one hour ago:
SELECT*FROM`mydataset.mytable`FORSYSTEM_TIMEASOFTIMESTAMP_SUB(CURRENT_TIMESTAMP(),INTERVAL1HOUR);FOR SYSTEM_TIME AS OF clause is supported in GoogleSQL.For legacy SQL,time decorators provideequivalent functionality.If the timestamp specifies a time from prior to the time travel window or frombefore the table was created, then the query fails and returns an error like thefollowing:
Invalid snapshot time 1601168925462 for tablemyproject:mydataset.table1@1601168925462. Cannot read before 1601573410026.
After you replace an existing table by using theCREATE OR REPLACE TABLEstatement, you can useFOR SYSTEM_TIME AS OF to query the previous version ofthe table.
If the table was deleted, then the query fails and returns an error like thefollowing:
Not found: Table myproject:mydataset.table was not found in locationLOCATION
Restore a table from a point in time
You can restore a table from historical data by copying the historical data intoa new table. Copying historical data works even if the table was deleted or hasexpired, as long as you restore the table within the duration of the time travelwindow.
When you restore a table from historical data,tags from the source table aren't copied to the destination table.Table partitioning information also isn't copied to the destination table. Torecreate the partitioning scheme of the original table, you can view the initialtable creation request inCloud Logging and use that information to partition the restored table.
You can restore a table that was deleted but is still within the time travelwindow by copying the table to a new table, using the@<time> time decorator.You can't query a deleted table, even if you use a time decorator. You mustrestore it first.
Use the following syntax with the@<time> time decorator:
tableid@TIMEwhereTIMEisthe number of milliseconds since the Unix epoch.tableid@-TIME_OFFSETwhereTIME_OFFSETis the relative offset from the currenttime, in milliseconds.tableid@0: Specifies the oldest available historical data.
To restore a table, select one of the following options:
Console
You can't undelete a table by using the Google Cloud console.
bq
In the Google Cloud console, activate Cloud Shell.
At the bottom of the Google Cloud console, aCloud 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.
To restore a table, first determine a UNIX timestamp of when the tableexisted (in milliseconds). You can use the Linux
datecommand togenerate the Unix timestamp from a regular timestamp value:date -d '2023-08-04 16:00:34.456789Z' +%s000
Then, use the
bq copycommand with the@<time>time travel decorator to perform the table copy operation.For example, enter the following command to copythe
mydataset.mytabletable at the time1418864998000into a new tablemydataset.newtable.bq cp mydataset.mytable@1418864998000 mydataset.newtable
(Optional) Supply the
--locationflag and set the value to yourlocation.You can also specify a relative offset. The following example copies theversion of a table from one hour ago:
Note: If you attempt to recover data prior to the time travel window orfrom a time before the table was created, you'll receive anbq cp mydataset.mytable@-3600000 mydataset.newtable
Invalid time travel timestamperror. For more information, seeTroubleshoot table recovery.
Go
Before trying this sample, follow theGo setup instructions in theBigQuery quickstart using client libraries. For more information, see theBigQueryGo API reference documentation.
To authenticate to BigQuery, set up Application Default Credentials. For more information, seeSet up authentication for client libraries.
import("context""fmt""time""cloud.google.com/go/bigquery")// deleteAndUndeleteTable demonstrates how to recover a deleted table by copying it from a point in time// that predates the deletion event.funcdeleteAndUndeleteTable(projectID,datasetID,tableIDstring)error{// projectID := "my-project-id"// datasetID := "mydataset"// tableID := "mytable"ctx:=context.Background()client,err:=bigquery.NewClient(ctx,projectID)iferr!=nil{returnfmt.Errorf("bigquery.NewClient: %v",err)}deferclient.Close()ds:=client.Dataset(datasetID)if_,err:=ds.Table(tableID).Metadata(ctx);err!=nil{returnerr}// Record the current time. We'll use this as the snapshot time// for recovering the table.snapTime:=time.Now()// "Accidentally" delete the table.iferr:=client.Dataset(datasetID).Table(tableID).Delete(ctx);err!=nil{returnerr}// Construct the restore-from tableID using a snapshot decorator.snapshotTableID:=fmt.Sprintf("%s@%d",tableID,snapTime.UnixNano()/1e6)// Choose a new table ID for the recovered table data.recoverTableID:=fmt.Sprintf("%s_recovered",tableID)// Construct and run a copy job.copier:=ds.Table(recoverTableID).CopierFrom(ds.Table(snapshotTableID))copier.WriteDisposition=bigquery.WriteTruncatejob,err:=copier.Run(ctx)iferr!=nil{returnerr}status,err:=job.Wait(ctx)iferr!=nil{returnerr}iferr:=status.Err();err!=nil{returnerr}ds.Table(recoverTableID).Delete(ctx)returnnil}Java
Before trying this sample, follow theJava setup instructions in theBigQuery quickstart using client libraries. For more information, see theBigQueryJava API reference documentation. To authenticate to BigQuery, set up Application Default Credentials. For more information, seeSet up authentication for client libraries.importcom.google.cloud.bigquery.BigQuery;importcom.google.cloud.bigquery.BigQueryException;importcom.google.cloud.bigquery.BigQueryOptions;importcom.google.cloud.bigquery.CopyJobConfiguration;importcom.google.cloud.bigquery.Job;importcom.google.cloud.bigquery.JobInfo;importcom.google.cloud.bigquery.TableId;// Sample to undeleting a tablepublicclassUndeleteTable{publicstaticvoidrunUndeleteTable(){// TODO(developer): Replace these variables before running the sample.StringdatasetName="MY_DATASET_NAME";StringtableName="MY_TABLE_TABLE";StringrecoverTableName="MY_RECOVER_TABLE_TABLE";undeleteTable(datasetName,tableName,recoverTableName);}publicstaticvoidundeleteTable(StringdatasetName,StringtableName,StringrecoverTableName){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.BigQuerybigquery=BigQueryOptions.getDefaultInstance().getService();// "Accidentally" delete the table.bigquery.delete(TableId.of(datasetName,tableName));// Record the current time. We'll use this as the snapshot time// for recovering the table.longsnapTime=System.currentTimeMillis();// Construct the restore-from tableID using a snapshot decorator.StringsnapshotTableId=String.format("%s@%d",tableName,snapTime);// Construct and run a copy job.CopyJobConfigurationconfiguration=CopyJobConfiguration.newBuilder(// Choose a new table ID for the recovered table data.TableId.of(datasetName,recoverTableName),TableId.of(datasetName,snapshotTableId)).build();Jobjob=bigquery.create(JobInfo.of(configuration));job=job.waitFor();if(job.isDone() &&job.getStatus().getError()==null){System.out.println("Undelete table recovered successfully.");}else{System.out.println("BigQuery was unable to copy the table due to an error: \n"+job.getStatus().getError());return;}}catch(BigQueryException|InterruptedExceptione){System.out.println("Table not found. \n"+e.toString());}}}
Node.js
Before trying this sample, follow theNode.js setup instructions in theBigQuery quickstart using client libraries. For more information, see theBigQueryNode.js API reference documentation.
To authenticate to BigQuery, set up Application Default Credentials. For more information, seeSet up authentication for client libraries.
// Import the Google Cloud client libraryconst{BigQuery}=require('@google-cloud/bigquery');constbigquery=newBigQuery();asyncfunctionundeleteTable(){// Undeletes "my_table_to_undelete" from "my_dataset"./** * TODO(developer): Uncomment the following lines before running the sample. */// const datasetId = "my_dataset";// const tableId = "my_table_to_undelete";// const recoveredTableId = "my_recovered_table";/** * TODO(developer): Choose an appropriate snapshot point as epoch milliseconds. * For this example, we choose the current time as we're about to delete the * table immediately afterwards. */constsnapshotEpoch=Date.now();// Delete the tableawaitbigquery.dataset(datasetId).table(tableId).delete();console.log(`Table${tableId} deleted.`);// Construct the restore-from table ID using a snapshot decorator.constsnapshotTableId=`${tableId}@${snapshotEpoch}`;// Construct and run a copy job.awaitbigquery.dataset(datasetId).table(snapshotTableId).copy(bigquery.dataset(datasetId).table(recoveredTableId));console.log(`Copied data from deleted table${tableId} to${recoveredTableId}`);}Python
Before trying this sample, follow thePython setup instructions in theBigQuery quickstart using client libraries. For more information, see theBigQueryPython API reference documentation. To authenticate to BigQuery, set up Application Default Credentials. For more information, seeSet up authentication for client libraries.importtimefromgoogle.cloudimportbigquery# Construct a BigQuery client object.client=bigquery.Client()# TODO(developer): Choose a table to recover.# table_id = "your-project.your_dataset.your_table"# TODO(developer): Choose a new table ID for the recovered table data.# recovered_table_id = "your-project.your_dataset.your_table_recovered"# TODO(developer): Choose an appropriate snapshot point as epoch# milliseconds. For this example, we choose the current time as we're about# to delete the table immediately afterwards.snapshot_epoch=int(time.time()*1000)# ...# "Accidentally" delete the table.client.delete_table(table_id)# Make an API request.# Construct the restore-from table ID using a snapshot decorator.snapshot_table_id="{}@{}".format(table_id,snapshot_epoch)# Construct and run a copy job.job=client.copy_table(snapshot_table_id,recovered_table_id,# Must match the source and destination tables location.location="US",)# Make an API request.job.result()# Wait for the job to complete.print("Copied data from deleted table{} to{}".format(table_id,recovered_table_id))
If you anticipate that you might want to restore a table later than what isallowed by the time travel window, then create a table snapshot of the table.For more information, seeIntroduction to table snapshots.
You cannot restore a logical view directly. For more information, seeRestore aview.
What's next
- Learn more abouttable snapshots.
- Learn more aboutData retention with time travel and fail-safe.
- Learn more aboutmanaging tables.
Except as otherwise noted, the content of this page is licensed under theCreative Commons Attribution 4.0 License, and code samples are licensed under theApache 2.0 License. For details, see theGoogle Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2025-12-15 UTC.