Insert, update, and delete data using data manipulation language (DML)

This page describes how to insert, update, and delete Spanner data using Data Manipulation Language (DML) statements. You can run DML statements using the client libraries, the Google Cloud console, and the gcloud command-line tool. You can run Partitioned DML statements using the client libraries and the gcloud command-line tool.

For the complete DML syntax reference, see Data Manipulation Language syntax for GoogleSQL-dialect databases or PostgreSQL data manipulation language for PostgreSQL-dialect databases

Use DML

DML supports INSERT, UPDATE, and DELETE statements in the Google Cloud console, Google Cloud CLI, and client libraries.

Locking

You execute DML statements inside read-write transactions. When Spanner reads data, it acquires shared read locks on limited portions of the row ranges that you read. Specifically, it acquires these locks only on the columns you access. The locks can include data that does not satisfy the filter condition of the WHERE clause.

When Spanner modifies data using DML statements, it acquires exclusive locks on the specific data that you are modifying. In addition, it acquires shared locks in the same way as when you read data. If your request includes large row ranges, or an entire table, the shared locks might prevent other transactions from making progress in parallel.

To modify data as efficiently as possible, use a WHERE clause that enables Spanner to read only the necessary rows. You can achieve this goal with a filter on the primary key, or on the key of a secondary index. The WHERE clause limits the scope of the shared locks and enables Spanner to process the update more efficiently.

For example, suppose that one of the musicians in the Singers table changes their first name, and you need to update the name in your database. You could execute the following DML statement, but it forces Spanner to scan the entire table and acquires shared locks that cover the entire table. As a result, Spanner must read more data than necessary, and concurrent transactions cannot modify the data in parallel:

-- ANTI-PATTERN: SENDING AN UPDATE WITHOUT THE PRIMARY KEY COLUMN
-- IN THE WHERE CLAUSE
UPDATESingersSETFirstName="Marcel"
WHEREFirstName="Marc"ANDLastName="Richards";

To make the update more efficient, include the SingerId column in the WHERE clause. The SingerId column is the only primary key column for the Singers table:

-- ANTI-PATTERN: SENDING AN UPDATE THAT MUST SCAN THE ENTIRE TABLE
UPDATESingersSETFirstName="Marcel"
WHEREFirstName="Marc"ANDLastName="Richards"

If there is no index on FirstName or LastName, you need to scan the entire table to find the target singers. If you don't want to add a secondary index to make the update more efficient, then include the SingerId column in the WHERE clause.

The SingerId column is the only primary key column for the Singers table. To find it, run SELECT in a separate, read-only transaction prior to the update transaction:


SELECTSingerId
FROMSingers
WHEREFirstName="Marc"ANDLastName="Richards"
--Recommended:Includingaseekablefilterinthewhereclause
UPDATESingersSETFirstName="Marcel"
WHERESingerId=1;

Concurrency

Spanner sequentially executes all the SQL statements (SELECT, INSERT, UPDATE, and DELETE) within a transaction. They are not executed concurrently. The only exception is that Spanner might execute multiple SELECT statements concurrently, because they are read-only operations.

Transaction limits

A transaction that includes DML statements has the same limits as any other transaction. If you have large-scale changes, consider using Partitioned DML.

  • If the DML statements in a transaction result in more than 80,000 mutations, the DML statement that pushes the transaction over the limit returns a BadUsage error with a message about too many mutations.

  • If the DML statements in a transaction result in a transaction that is larger than 100 MiB, the DML statement that pushes the transaction over the limit returns a BadUsage error with a message about the transaction exceeding the size limit.

Mutations performed using DML are not returned to the client. They are merged into the commit request when it is committed, and they count towards the maximum size limits. Even if the size of the commit request that you send is small, the transaction might still exceed the allowed size limit.

Run statements in the Google Cloud console

Use the following steps to execute a DML statement in the Google Cloud console.

  1. Go to the Spanner Instances page.

    Go to the instances page

  2. Select your project in the drop-down list in the toolbar.

  3. Click the name of the instance that contains your database to go to the Instance details page.

  4. In the Overview tab, click the name of your database. The Database details page appears.

  5. Click Spanner Studio.

  6. Enter a DML statement. For example, the following statement adds a new row to the Singers table.

    INSERT Singers (SingerId, FirstName, LastName)
    VALUES (1, 'Marc', 'Richards')
    
  7. Click Run query. The Google Cloud console displays the result.

Execute statements with the Google Cloud CLI

To execute DML statements, use the gcloud spanner databases execute-sql command. The following example adds a new row to the Singers table.

gcloudspannerdatabasesexecute-sqlexample-db--instance=test-instance\
--sql="INSERT Singers (SingerId, FirstName, LastName) VALUES (1, 'Marc', 'Richards')"

Modify data using the client library

To execute DML statements using the client library:

  • Create a read-write transaction.
  • Call the client library method for DML execution and pass in the DML statement.
  • Use the return value of the DML execution method to get the number of rows inserted, updated, or deleted.

The following code example inserts a new row into the Singers table.

C++

You use the ExecuteDml() function to execute a DML statement.

voidDmlStandardInsert(google::cloud::spanner::Clientclient){
using::google::cloud::StatusOr;
namespacespanner=::google::cloud::spanner;
std::int64_trows_inserted;
autocommit_result=client.Commit(
[&client,&rows_inserted](
spanner::Transactiontxn)->StatusOr<spanner::Mutations>{
autoinsert=client.ExecuteDml(
std::move(txn),
spanner::SqlStatement(
"INSERT INTO Singers (SingerId, FirstName, LastName)"
" VALUES (10, 'Virginia', 'Watson')"));
if(!insert)returnstd::move(insert).status();
rows_inserted=insert->RowsModified();
returnspanner::Mutations{};
});
if(!commit_result)throwstd::move(commit_result).status();
std::cout << "Rows inserted: " << rows_inserted;
std::cout << "Insert was successful [spanner_dml_standard_insert]\n";
}

C#

You use the ExecuteNonQueryAsync() method to execute a DML statement.


usingGoogle.Cloud.Spanner.Data ;
usingSystem;
usingSystem.Threading.Tasks;
publicclassInsertUsingDmlCoreAsyncSample
{
publicasyncTask<int>InsertUsingDmlCoreAsync(stringprojectId,stringinstanceId,stringdatabaseId)
{
stringconnectionString=$"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}";
usingvarconnection=newSpannerConnection (connectionString);
awaitconnection.OpenAsync ();
usingvarcmd=connection.CreateDmlCommand ("INSERT Singers (SingerId, FirstName, LastName) VALUES (10, 'Virginia', 'Watson')");
introwCount=awaitcmd.ExecuteNonQueryAsync();
Console.WriteLine($"{rowCount} row(s) inserted...");
returnrowCount;
}
}

Go

You use the Update() method to execute a DML statement.


import(
"context"
"fmt"
"io"
"cloud.google.com/go/spanner"
)
funcinsertUsingDML(wio.Writer,dbstring)error{
ctx:=context.Background()
client,err:=spanner.NewClient(ctx,db)
iferr!=nil{
returnerr
}
deferclient.Close()
_,err=client.ReadWriteTransaction(ctx,func(ctxcontext.Context,txn*spanner.ReadWriteTransaction)error{
stmt:=spanner.Statement {
SQL:`INSERT Singers (SingerId, FirstName, LastName)
					VALUES (10, 'Virginia', 'Watson')`,
}
rowCount,err:=txn.Update(ctx,stmt)
iferr!=nil{
returnerr
}
fmt.Fprintf(w,"%d record(s) inserted.\n",rowCount)
returnnil
})
returnerr
}

Java

You use the executeUpdate() method to execute a DML statement.

staticvoidinsertUsingDml(DatabaseClientdbClient){
dbClient
.readWriteTransaction()
.run(transaction->{
Stringsql=
"INSERT INTO Singers (SingerId, FirstName, LastName) "
+" VALUES (10, 'Virginia', 'Watson')";
longrowCount=transaction.executeUpdate(Statement.of(sql));
System.out.printf("%d record inserted.\n",rowCount);
returnnull;
});
}

Node.js

You use the runUpdate() method to execute a DML statement.

// Imports the Google Cloud client library
const{Spanner}=require('@google-cloud/spanner');
/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';
// Creates a client
constspanner=newSpanner ({
projectId:projectId,
});
// Gets a reference to a Cloud Spanner instance and database
constinstance=spanner.instance(instanceId);
constdatabase=instance.database(databaseId);
database.runTransaction (async(err,transaction)=>{
if(err){
console.error(err);
return;
}
try{
const[rowCount]=awaittransaction.runUpdate ({
sql:'INSERT Singers (SingerId, FirstName, LastName) VALUES (10, @firstName, @lastName)',
params:{
firstName:'Virginia',
lastName:'Watson',
},
});
console.log(
`Successfully inserted ${rowCount} record into the Singers table.`,
);
awaittransaction.commit();
}catch(err){
console.error('ERROR:',err);
}finally{
// Close the database when finished.
database.close();
}
});

PHP

You use the executeUpdate() method to execute a DML statement.

use Google\Cloud\Spanner\SpannerClient;
use Google\Cloud\Spanner\Transaction;
/**
 * Inserts sample data into the given database with a DML statement.
 *
 * The database and table must already exist and can be created using
 * `create_database`.
 * Example:
 * ```
 * insert_data($instanceId, $databaseId);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function insert_data_with_dml(string $instanceId, string $databaseId): void
{
 $spanner = new SpannerClient();
 $instance = $spanner->instance($instanceId);
 $database = $instance->database($databaseId);
 $database->runTransaction(function (Transaction $t) {
 $rowCount = $t->executeUpdate(
 'INSERT Singers (SingerId, FirstName, LastName) '
 . " VALUES (10, 'Virginia', 'Watson')");
 $t->commit();
 printf('Inserted %d row(s).' . PHP_EOL, $rowCount);
 });
}

Python

You use the execute_update() method to execute a DML statement.

# instance_id = "your-spanner-instance"
# database_id = "your-spanner-db-id"
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)
definsert_singers(transaction):
 row_ct = transaction.execute_update(
 "INSERT INTO Singers (SingerId, FirstName, LastName) "
 " VALUES (10, 'Virginia', 'Watson')"
 )
 print("{} record(s) inserted.".format(row_ct))
database.run_in_transaction(insert_singers)

Ruby

You use the execute_update() method to execute a DML statement.

# project_id = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"
require"google/cloud/spanner"
spanner=Google::Cloud::Spanner.newproject:project_id
client=spanner.clientinstance_id,database_id
row_count=0
client.transactiondo|transaction|
row_count=transaction.execute_update(
"INSERT INTO Singers (SingerId, FirstName, LastName) VALUES (10, 'Virginia', 'Watson')"
)
end
puts"#{row_count} record inserted."

The following code example updates the MarketingBudget column of the Albums table based on a WHERE clause.

C++

voidDmlStandardUpdate(google::cloud::spanner::Clientclient){
using::google::cloud::StatusOr;
namespacespanner=::google::cloud::spanner;
autocommit_result=client.Commit(
[&client](spanner::Transactiontxn)->StatusOr<spanner::Mutations>{
autoupdate=client.ExecuteDml(
std::move(txn),
spanner::SqlStatement(
"UPDATE Albums SET MarketingBudget = MarketingBudget * 2"
" WHERE SingerId = 1 AND AlbumId = 1"));
if(!update)returnstd::move(update).status();
returnspanner::Mutations{};
});
if(!commit_result)throwstd::move(commit_result).status();
std::cout << "Update was successful [spanner_dml_standard_update]\n";
}

C#


usingGoogle.Cloud.Spanner.Data ;
usingSystem;
usingSystem.Threading.Tasks;
publicclassUpdateUsingDmlCoreAsyncSample
{
publicasyncTask<int>UpdateUsingDmlCoreAsync(stringprojectId,stringinstanceId,stringdatabaseId)
{
stringconnectionString=$"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}";
usingvarconnection=newSpannerConnection (connectionString);
awaitconnection.OpenAsync ();
usingvarcmd=connection.CreateDmlCommand ("UPDATE Albums SET MarketingBudget = MarketingBudget * 2 WHERE SingerId = 1 and AlbumId = 1");
introwCount=awaitcmd.ExecuteNonQueryAsync();
Console.WriteLine($"{rowCount} row(s) updated...");
returnrowCount;
}
}

Go


import(
"context"
"fmt"
"io"
"cloud.google.com/go/spanner"
)
funcupdateUsingDML(wio.Writer,dbstring)error{
ctx:=context.Background()
client,err:=spanner.NewClient(ctx,db)
iferr!=nil{
returnerr
}
deferclient.Close()
_,err=client.ReadWriteTransaction(ctx,func(ctxcontext.Context,txn*spanner.ReadWriteTransaction)error{
stmt:=spanner.Statement {
SQL:`UPDATE Albums
				SET MarketingBudget = MarketingBudget * 2
				WHERE SingerId = 1 and AlbumId = 1`,
}
rowCount,err:=txn.Update(ctx,stmt)
iferr!=nil{
returnerr
}
fmt.Fprintf(w,"%d record(s) updated.\n",rowCount)
returnnil
})
returnerr
}

Java

staticvoidupdateUsingDml(DatabaseClientdbClient){
dbClient
.readWriteTransaction()
.run(transaction->{
Stringsql=
"UPDATE Albums "
+"SET MarketingBudget = MarketingBudget * 2 "
+"WHERE SingerId = 1 and AlbumId = 1";
longrowCount=transaction.executeUpdate(Statement.of(sql));
System.out.printf("%d record updated.\n",rowCount);
returnnull;
});
}

Node.js

// Imports the Google Cloud client library
const{Spanner}=require('@google-cloud/spanner');
/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';
// Creates a client
constspanner=newSpanner ({
projectId:projectId,
});
// Gets a reference to a Cloud Spanner instance and database
constinstance=spanner.instance(instanceId);
constdatabase=instance.database(databaseId);
database.runTransaction (async(err,transaction)=>{
if(err){
console.error(err);
return;
}
try{
const[rowCount]=awaittransaction.runUpdate ({
sql:`UPDATE Albums SET MarketingBudget = MarketingBudget * 2
 WHERE SingerId = 1 and AlbumId = 1`,
});
console.log(`Successfully updated ${rowCount} record.`);
awaittransaction.commit();
}catch(err){
console.error('ERROR:',err);
}finally{
// Close the database when finished.
database.close();
}
});

PHP

use Google\Cloud\Spanner\SpannerClient;
use Google\Cloud\Spanner\Transaction;
/**
 * Updates sample data in the database with a DML statement.
 *
 * This requires the `MarketingBudget` column which must be created before
 * running this sample. You can add the column by running the `add_column`
 * sample or by running this DDL statement against your database:
 *
 * ALTER TABLE Albums ADD COLUMN MarketingBudget INT64
 *
 * Example:
 * ```
 * update_data($instanceId, $databaseId);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function update_data_with_dml(string $instanceId, string $databaseId): void
{
 $spanner = new SpannerClient();
 $instance = $spanner->instance($instanceId);
 $database = $instance->database($databaseId);
 $database->runTransaction(function (Transaction $t) {
 $rowCount = $t->executeUpdate(
 'UPDATE Albums '
 . 'SET MarketingBudget = MarketingBudget * 2 '
 . 'WHERE SingerId = 1 and AlbumId = 1');
 $t->commit();
 printf('Updated %d row(s).' . PHP_EOL, $rowCount);
 });
}

Python

# instance_id = "your-spanner-instance"
# database_id = "your-spanner-db-id"
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)
defupdate_albums(transaction):
 row_ct = transaction.execute_update(
 "UPDATE Albums "
 "SET MarketingBudget = MarketingBudget * 2 "
 "WHERE SingerId = 1 and AlbumId = 1"
 )
 print("{} record(s) updated.".format(row_ct))
database.run_in_transaction(update_albums)

Ruby

# project_id = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"
require"google/cloud/spanner"
spanner=Google::Cloud::Spanner.newproject:project_id
client=spanner.clientinstance_id,database_id
row_count=0
client.transactiondo|transaction|
row_count=transaction.execute_update(
"UPDATE Albums
 SET MarketingBudget = MarketingBudget * 2
 WHERE SingerId = 1 and AlbumId = 1"
)
end
puts"#{row_count} record updated."

The following code example deletes all the rows in the Singers table where the FirstName column is Alice.

C++

voidDmlStandardDelete(google::cloud::spanner::Clientclient){
using::google::cloud::StatusOr;
namespacespanner=::google::cloud::spanner;
autocommit_result=client.Commit([&client](spanner::Transactiontxn)
->StatusOr<spanner::Mutations>{
autodele=client.ExecuteDml(
std::move(txn),
spanner::SqlStatement("DELETE FROM Singers WHERE FirstName = 'Alice'"));
if(!dele)returnstd::move(dele).status();
returnspanner::Mutations{};
});
if(!commit_result)throwstd::move(commit_result).status();
std::cout << "Delete was successful [spanner_dml_standard_delete]\n";
}

C#


usingGoogle.Cloud.Spanner.Data ;
usingSystem;
usingSystem.Threading.Tasks;
publicclassDeleteUsingDmlCoreAsyncSample
{
publicasyncTask<int>DeleteUsingDmlCoreAsync(stringprojectId,stringinstanceId,stringdatabaseId)
{
stringconnectionString=$"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}";
usingvarconnection=newSpannerConnection (connectionString);
awaitconnection.OpenAsync ();
usingvarcmd=connection.CreateDmlCommand ("DELETE FROM Singers WHERE FirstName = 'Alice'");
introwCount=awaitcmd.ExecuteNonQueryAsync();
Console.WriteLine($"{rowCount} row(s) deleted...");
returnrowCount;
}
}

Go


import(
"context"
"fmt"
"io"
"cloud.google.com/go/spanner"
)
funcdeleteUsingDML(wio.Writer,dbstring)error{
ctx:=context.Background()
client,err:=spanner.NewClient(ctx,db)
iferr!=nil{
returnerr
}
deferclient.Close()
_,err=client.ReadWriteTransaction(ctx,func(ctxcontext.Context,txn*spanner.ReadWriteTransaction)error{
stmt:=spanner.Statement {SQL:`DELETE FROM Singers WHERE FirstName = 'Alice'`}
rowCount,err:=txn.Update(ctx,stmt)
iferr!=nil{
returnerr
}
fmt.Fprintf(w,"%d record(s) deleted.\n",rowCount)
returnnil
})
returnerr
}

Java

staticvoiddeleteUsingDml(DatabaseClientdbClient){
dbClient
.readWriteTransaction()
.run(transaction->{
Stringsql="DELETE FROM Singers WHERE FirstName = 'Alice'";
longrowCount=transaction.executeUpdate(Statement.of(sql));
System.out.printf("%d record deleted.\n",rowCount);
returnnull;
});
}

Node.js

// Imports the Google Cloud client library
const{Spanner}=require('@google-cloud/spanner');
/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';
// Creates a client
constspanner=newSpanner ({
projectId:projectId,
});
// Gets a reference to a Cloud Spanner instance and database
constinstance=spanner.instance(instanceId);
constdatabase=instance.database(databaseId);
database.runTransaction (async(err,transaction)=>{
if(err){
console.error(err);
return;
}
try{
const[rowCount]=awaittransaction.runUpdate ({
sql:"DELETE FROM Singers WHERE FirstName = 'Alice'",
});
console.log(`Successfully deleted ${rowCount} record.`);
awaittransaction.commit();
}catch(err){
console.error('ERROR:',err);
}finally{
// Close the database when finished.
database.close();
}
});

PHP

use Google\Cloud\Spanner\SpannerClient;
use Google\Cloud\Spanner\Transaction;
/**
 * Deletes sample data in the database with a DML statement.
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function delete_data_with_dml(string $instanceId, string $databaseId): void
{
 $spanner = new SpannerClient();
 $instance = $spanner->instance($instanceId);
 $database = $instance->database($databaseId);
 $database->runTransaction(function (Transaction $t) {
 $rowCount = $t->executeUpdate(
 "DELETE FROM Singers WHERE FirstName = 'Alice'");
 $t->commit();
 printf('Deleted %d row(s).' . PHP_EOL, $rowCount);
 });
}

Python

# instance_id = "your-spanner-instance"
# database_id = "your-spanner-db-id"
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)
defdelete_singers(transaction):
 row_ct = transaction.execute_update(
 "DELETE FROM Singers WHERE FirstName = 'Alice'"
 )
 print("{} record(s) deleted.".format(row_ct))
database.run_in_transaction(delete_singers)

Ruby

# project_id = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"
require"google/cloud/spanner"
spanner=Google::Cloud::Spanner.newproject:project_id
client=spanner.clientinstance_id,database_id
row_count=0
client.transactiondo|transaction|
row_count=transaction.execute_update(
"DELETE FROM Singers WHERE FirstName = 'Alice'"
)
end
puts"#{row_count} record deleted."

The following example, for GoogleSQL-dialect databases only, uses a STRUCT with bound parameters to update the LastName in rows filtered by FirstName and LastName.

GoogleSQL

C++

voidDmlStructs(google::cloud::spanner::Clientclient){
namespacespanner=::google::cloud::spanner;
std::int64_trows_modified=0;
autocommit_result=
client.Commit([&client,&rows_modified](spanner::Transactionconst&txn)
->google::cloud::StatusOr<spanner::Mutations>{
autosinger_info=std::make_tuple("Marc","Richards");
autosql=spanner::SqlStatement(
"UPDATE Singers SET FirstName = 'Keith' WHERE "
"STRUCT<FirstName String, LastName String>(FirstName, LastName) "
"= @name",
{{"name", spanner::Value(std::move(singer_info))}});
autodml_result=client.ExecuteDml(txn,std::move(sql));
if(!dml_result)returnstd::move(dml_result).status();
rows_modified=dml_result->RowsModified();
returnspanner::Mutations{};
});
if(!commit_result)throwstd::move(commit_result).status();
std::cout << rows_modified
 << " update was successful [spanner_dml_structs]\n";
}

C#


usingGoogle.Cloud.Spanner.Data ;
usingSystem;
usingSystem.Threading.Tasks;
publicclassUpdateUsingDmlWithStructCoreAsyncSample
{
publicasyncTask<int>UpdateUsingDmlWithStructCoreAsync(stringprojectId,stringinstanceId,stringdatabaseId)
{
varnameStruct=newSpannerStruct
{
{"FirstName",SpannerDbType .String ,"Timothy"},
{"LastName",SpannerDbType .String ,"Campbell"}
};
stringconnectionString=$"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}";
usingvarconnection=newSpannerConnection (connectionString);
awaitconnection.OpenAsync ();
usingvarcmd=connection.CreateDmlCommand ("UPDATE Singers SET LastName = 'Grant' WHERE STRUCT<FirstName STRING, LastName STRING>(FirstName, LastName) = @name");
cmd.Parameters .Add("name",nameStruct.GetSpannerDbType (),nameStruct);
introwCount=awaitcmd.ExecuteNonQueryAsync();
Console.WriteLine($"{rowCount} row(s) updated...");
returnrowCount;
}
}

Go


import(
"context"
"fmt"
"io"
"cloud.google.com/go/spanner"
)
funcupdateUsingDMLStruct(wio.Writer,dbstring)error{
ctx:=context.Background()
client,err:=spanner.NewClient(ctx,db)
iferr!=nil{
returnerr
}
deferclient.Close()
_,err=client.ReadWriteTransaction(ctx,func(ctxcontext.Context,txn*spanner.ReadWriteTransaction)error{
typenamestruct{
FirstNamestring
LastNamestring
}
varsingerInfo=name{"Timothy","Campbell"}
stmt:=spanner.Statement {
SQL:`Update Singers Set LastName = 'Grant'
				WHERE STRUCT<FirstName String, LastName String>(Firstname, LastName) = @name`,
Params:map[string]interface{}{"name":singerInfo},
}
rowCount,err:=txn.Update(ctx,stmt)
iferr!=nil{
returnerr
}
fmt.Fprintf(w,"%d record(s) inserted.\n",rowCount)
returnnil
})
returnerr
}

Java

staticvoidupdateUsingDmlWithStruct(DatabaseClientdbClient){
Structname=
Struct.newBuilder().set("FirstName").to("Timothy").set("LastName").to("Campbell").build();
Statements=
Statement.newBuilder(
"UPDATE Singers SET LastName = 'Grant' "
+"WHERE STRUCT<FirstName STRING, LastName STRING>(FirstName, LastName) "
+"= @name")
.bind("name")
.to(name)
.build();
dbClient
.readWriteTransaction()
.run(transaction->{
longrowCount=transaction.executeUpdate(s);
System.out.printf("%d record updated.\n",rowCount);
returnnull;
});
}

Node.js

// Imports the Google Cloud client library
const{Spanner}=require('@google-cloud/spanner');
constnameStruct=Spanner .struct ({
FirstName:'Timothy',
LastName:'Campbell',
});
/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';
// Creates a client
constspanner=newSpanner ({
projectId:projectId,
});
// Gets a reference to a Cloud Spanner instance and database
constinstance=spanner.instance(instanceId);
constdatabase=instance.database(databaseId);
database.runTransaction (async(err,transaction)=>{
if(err){
console.error(err);
return;
}
try{
const[rowCount]=awaittransaction.runUpdate ({
sql:`UPDATE Singers SET LastName = 'Grant'
 WHERE STRUCT<FirstName STRING, LastName STRING>(FirstName, LastName) = @name`,
params:{
name:nameStruct,
},
});
console.log(`Successfully updated ${rowCount} record.`);
awaittransaction.commit();
}catch(err){
console.error('ERROR:',err);
}finally{
// Close the database when finished.
database.close();
}
});

PHP

use Google\Cloud\Spanner\SpannerClient;
use Google\Cloud\Spanner\Database;
use Google\Cloud\Spanner\Transaction;
use Google\Cloud\Spanner\StructType;
use Google\Cloud\Spanner\StructValue;
/**
 * Update data with a DML statement using Structs.
 *
 * The database and table must already exist and can be created using
 * `create_database`.
 * Example:
 * ```
 * insert_data($instanceId, $databaseId);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function update_data_with_dml_structs(string $instanceId, string $databaseId): void
{
 $spanner = new SpannerClient();
 $instance = $spanner->instance($instanceId);
 $database = $instance->database($databaseId);
 $database->runTransaction(function (Transaction $t) {
 $nameValue = (new StructValue)
 ->add('FirstName', 'Timothy')
 ->add('LastName', 'Campbell');
 $nameType = (new StructType)
 ->add('FirstName', Database::TYPE_STRING)
 ->add('LastName', Database::TYPE_STRING);
 $rowCount = $t->executeUpdate(
 "UPDATE Singers SET LastName = 'Grant' "
 . 'WHERE STRUCT<FirstName STRING, LastName STRING>(FirstName, LastName) '
 . '= @name',
 [
 'parameters' => [
 'name' => $nameValue
 ],
 'types' => [
 'name' => $nameType
 ]
 ]);
 $t->commit();
 printf('Updated %d row(s).' . PHP_EOL, $rowCount);
 });
}

Python

# instance_id = "your-spanner-instance"
# database_id = "your-spanner-db-id"
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)
record_type = param_types.Struct(
 [
 param_types.StructField("FirstName", param_types.STRING),
 param_types.StructField("LastName", param_types.STRING),
 ]
)
record_value = ("Timothy", "Campbell")
defwrite_with_struct(transaction):
 row_ct = transaction.execute_update(
 "UPDATE Singers SET LastName = 'Grant' "
 "WHERE STRUCT<FirstName STRING, LastName STRING>"
 "(FirstName, LastName) = @name",
 params={"name": record_value},
 param_types={"name": record_type},
 )
 print("{} record(s) updated.".format(row_ct))
database.run_in_transaction(write_with_struct)

Ruby

# project_id = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"
require"google/cloud/spanner"
spanner=Google::Cloud::Spanner.newproject:project_id
client=spanner.clientinstance_id,database_id
row_count=0
name_struct={FirstName:"Timothy",LastName:"Campbell"}
client.transactiondo|transaction|
row_count=transaction.execute_update(
"UPDATE Singers SET LastName = 'Grant'
 WHERE STRUCT<FirstName STRING, LastName STRING>(FirstName, LastName) = @name",
params:{name:name_struct}
)
end
puts"#{row_count} record updated."

Modify data with the returning DML statements

The THEN RETURN clause (GoogleSQL-dialect databases) or RETURNING clause (PostgreSQL-dialect databases) is intended for scenarios where you want to fetch data from modified rows. This is especially useful when you want to view unspecified values in the DML statements, default values, or generated columns.

To execute returning DML statements using the client library:

  • Create a read-write transaction.
  • Call the client library method for query execution and pass in the returning DML statement to obtain results.

The following code example inserts a new row into the Singers table, and it returns the generated column FullName of the inserted records.

GoogleSQL

C++

voidInsertUsingDmlReturning(google::cloud::spanner::Clientclient){
//InsertrecordsintoSINGERStableandreturnthegeneratedcolumn
//FullNameoftheinsertedrecordsusing`THEN RETURN FullName`.
autocommit=client.Commit(
[&client](google::cloud::spanner::Transactiontxn)
->google::cloud::StatusOr<google::cloud::spanner::Mutations>{
autosql=google::cloud::spanner::SqlStatement(R"""(
 INSERT INTO Singers (SingerId, FirstName, LastName)
 VALUES (12, 'Melissa', 'Garcia'),
 (13, 'Russell', 'Morales'),
 (14, 'Jacqueline', 'Long'),
 (15, 'Dylan', 'Shaw')
 THEN RETURN FullName
 )""");
usingRowType=std::tuple<std::string>;
autorows=client.ExecuteQuery(std::move(txn),std::move(sql));
//Note:Thismutatormightbere-run,oritseffectsdiscarded,so
//changingnon-transactionalstate(e.g.,byproducingoutput)is,
//ingeneral,notsomethingtobeimitated.
for(auto&row:google::cloud::spanner::StreamOf<RowType>(rows)){
if(!row)returnstd::move(row).status();
std::cout << "FullName: " << std::get<0>(*row) << "\n";
}
std::cout << "Inserted row(s) count: " << rows.RowsModified() << "\n";
returngoogle::cloud::spanner::Mutations{};
});
if(!commit)throwstd::move(commit).status();
}

C#


usingGoogle.Cloud.Spanner.Data ;
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Threading.Tasks;
publicclassInsertUsingDmlReturningAsyncSample
{
publicasyncTask<List<string>>InsertUsingDmlReturningAsync(stringprojectId,stringinstanceId,stringdatabaseId)
{
stringconnectionString=$"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}";
usingvarconnection=newSpannerConnection (connectionString);
awaitconnection.OpenAsync ();
// Insert records into the SINGERS table and return the
// generated column FullName of the inserted records using
// 'THEN RETURN FullName'.
// It is also possible to return all columns of all the
// inserted records by using 'THEN RETURN *'.
usingvarcmd=connection.CreateDmlCommand (
@"INSERT INTO Singers(SingerId, FirstName, LastName) VALUES
 (6, 'Melissa', 'Garcia'), 
 (7, 'Russell', 'Morales'), 
 (8, 'Jacqueline', 'Long'), 
 (9, 'Dylan', 'Shaw') THEN RETURN FullName");
varreader=awaitcmd.ExecuteReaderAsync ();
varinsertedSingerNames=newList<string>();
while(awaitreader.ReadAsync ())
{
insertedSingerNames.Add(reader.GetFieldValue<string>("FullName"));
}
Console.WriteLine($"{insertedSingerNames.Count} row(s) inserted...");
returninsertedSingerNames;
}
}

Go


import(
"context"
"fmt"
"io"
"cloud.google.com/go/spanner"
"google.golang.org/api/iterator"
)
funcinsertUsingDMLReturning(wio.Writer,dbstring)error{
ctx:=context.Background()
client,err:=spanner.NewClient(ctx,db)
iferr!=nil{
returnerr
}
deferclient.Close()
// Insert records into the SINGERS table and returns the
// generated column FullName of the inserted records using
// 'THEN RETURN FullName'.
// It is also possible to return all columns of all the
// inserted records by using 'THEN RETURN *'.
_,err=client.ReadWriteTransaction(ctx,func(ctxcontext.Context,txn*spanner.ReadWriteTransaction)error{
stmt:=spanner.Statement {
SQL:`INSERT INTO Singers (SingerId, FirstName, LastName)
			 VALUES (21, 'Melissa', 'Garcia'),
			 (22, 'Russell', 'Morales'),
			 (23, 'Jacqueline', 'Long'),
			 (24, 'Dylan', 'Shaw')
			 THEN RETURN FullName`,
}
iter:=txn.Query(ctx,stmt)
deferiter.Stop()
for{
row,err:=iter.Next()
iferr==iterator.Done{
break
}
iferr!=nil{
returnerr
}
varfullNamestring
iferr:=row.Columns (&fullName);err!=nil{
returnerr
}
fmt.Fprintf(w,"%s\n",fullName)
}
fmt.Fprintf(w,"%d record(s) inserted.\n",iter.RowCount)
returnnil
})
returnerr
}

Java


importcom.google.cloud.spanner.DatabaseClient ;
importcom.google.cloud.spanner.DatabaseId ;
importcom.google.cloud.spanner.ResultSet ;
importcom.google.cloud.spanner.Spanner ;
importcom.google.cloud.spanner.SpannerOptions ;
importcom.google.cloud.spanner.Statement ;
publicclass InsertUsingDmlReturningSample{
staticvoidinsertUsingDmlReturning(){
// TODO(developer): Replace these variables before running the sample.
finalStringprojectId="my-project";
finalStringinstanceId="my-instance";
finalStringdatabaseId="my-database";
insertUsingDmlReturning(projectId,instanceId,databaseId);
}
staticvoidinsertUsingDmlReturning(StringprojectId,StringinstanceId,StringdatabaseId){
try(Spanner spanner=
SpannerOptions .newBuilder()
.setProjectId(projectId)
.build()
.getService()){
finalDatabaseClient dbClient=
spanner.getDatabaseClient(DatabaseId .of(projectId,instanceId,databaseId));
// Insert records into the SINGERS table and returns the
// generated column FullName of the inserted records using
// ‘THEN RETURN FullName’.
// It is also possible to return all columns of all the
// inserted records by using ‘THEN RETURN *’.
dbClient
.readWritreadWriteTransaction .run(
transaction->{
Stringsql=
"INSERT INTO Singers (SingerId, FirstName, LastName) VALUES "
+"(12, 'Melissa', 'Garcia'), "
+"(13, 'Russell', 'Morales'), "
+"(14, 'Jacqueline', 'Long'), "
+"(15, 'Dylan', 'Shaw') THEN RETURN FullName";
// readWriteTransaction.executeQuery(..) API should be used for executing
// DML statements with RETURNING clause.
try(ResultSeResultSetet=transaction.executeQuery(StatemenStatement )){
while(resultSet.next()){
System.out.println(resultSet.getString(0));
}
System.out.printf(
"Inserted row(s) count: %d\n",resultSet.getStats().getRowCountExact());
}
returnnull;
});
}
}
}

Node.js

// Imports the Google Cloud client library.
const{Spanner}=require('@google-cloud/spanner');
/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';
// Creates a client
constspanner=newSpanner ({
projectId:projectId,
});
functioninsertUsingDmlReturning(instanceId,databaseId){
// Gets a reference to a Cloud Spanner instance and database.
constinstance=spanner.instance(instanceId);
constdatabase=instance.database(databaseId);
database.runTransaction (async(err,transaction)=>{
if(err){
console.error(err);
return;
}
try{
const[rows,stats]=awaittransaction.run({
sql:'INSERT Singers (SingerId, FirstName, LastName) VALUES (@id, @firstName, @lastName) THEN RETURN FullName',
params:{
id:18,
firstName:'Virginia',
lastName:'Watson',
},
});
constrowCount=Math.floor(stats[stats.rowCount ]);
console.log(
`Successfully inserted ${rowCount} record into the Singers table.`,
);
rows.forEach(row=>{
console.log(row.toJSON().FullName);
});
awaittransaction.commit();
}catch(err){
console.error('ERROR:',err);
}finally{
// Close the database when finished.
database.close();
}
});
}
insertUsingDmlReturning(instanceId,databaseId);

PHP

use Google\Cloud\Spanner\SpannerClient;
/**
 * Inserts sample data into the given database using DML returning.
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function insert_dml_returning(string $instanceId, string $databaseId): void
{
 $spanner = new SpannerClient();
 $instance = $spanner->instance($instanceId);
 $database = $instance->database($databaseId);
 // Insert records into SINGERS table and returns the generated column
 // FullName of the inserted records using ‘THEN RETURN FullName’. It is also
 // possible to return all columns of all the inserted records by using
 // ‘THEN RETURN *’.
 $sql = 'INSERT INTO Singers (SingerId, FirstName, LastName) '
 . "VALUES (12, 'Melissa', 'Garcia'), "
 . "(13, 'Russell', 'Morales'), "
 . "(14, 'Jacqueline', 'Long'), "
 . "(15, 'Dylan', 'Shaw') "
 . 'THEN RETURN FullName';
 $transaction = $database->transaction();
 $result = $transaction->execute($sql);
 foreach ($result->rows() as $row) {
 printf(
 '%s inserted.' . PHP_EOL,
 $row['FullName'],
 );
 }
 printf(
 'Inserted row(s) count: %d' . PHP_EOL,
 $result->stats()['rowCountExact']
 );
 $transaction->commit();
}

Python

# instance_id = "your-spanner-instance"
# database_id = "your-spanner-db-id"
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)
# Insert records into the SINGERS table and returns the
# generated column FullName of the inserted records using
# 'THEN RETURN FullName'.
# It is also possible to return all columns of all the
# inserted records by using 'THEN RETURN *'.
definsert_singers(transaction):
 results = transaction.execute_sql(
 "INSERT INTO Singers (SingerId, FirstName, LastName) VALUES "
 "(21, 'Luann', 'Chizoba'), "
 "(22, 'Denis', 'Patricio'), "
 "(23, 'Felxi', 'Ronan'), "
 "(24, 'Dominik', 'Martyna') "
 "THEN RETURN FullName"
 )
 for result in results:
 print("FullName: {}".format(*result))
 print("{} record(s) inserted.".format(results.stats.row_count_exact))
database.run_in_transaction(insert_singers)

Ruby

require"google/cloud/spanner"
##
# This is a snippet for showcasing how to use DML return feature with insert
# operation.
#
# @param project_id [String] The ID of the Google Cloud project.
# @param instance_id [String] The ID of the spanner instance.
# @param database_id [String] The ID of the database.
#
defspanner_insert_dml_returningproject_id:,instance_id:,database_id:
spanner=Google::Cloud::Spanner.newproject:project_id
client=spanner.clientinstance_id,database_id
client.transactiondo|transaction|
# Insert records into the SINGERS table and returns the generated column
# FullName of the inserted records using ‘THEN RETURN FullName’.
# It is also possible to return all columns of all the inserted records
# by using ‘THEN RETURN *’.
results=transaction.execute_query"INSERT INTO Singers (SingerId, FirstName, LastName)
 VALUES (12, 'Melissa', 'Garcia'), (13, 'Russell', 'Morales'), (14, 'Jacqueline', 'Long'), (15, 'Dylan', 'Shaw')
 THEN RETURN FullName"
results.rows.eachdo|row|
puts"Inserted singers with FullName: #{row[:FullName]}"
end
puts"Inserted row(s) count: #{results.row_count}"
end
end

PostgreSQL

C++

voidInsertUsingDmlReturning(google::cloud::spanner::Clientclient){
//InsertrecordsintoSINGERStableandreturnthegeneratedcolumn
//FullNameoftheinsertedrecordsusing`RETURNINGFullName`.
autocommit=client.Commit(
[&client](google::cloud::spanner::Transactiontxn)
->google::cloud::StatusOr<google::cloud::spanner::Mutations>{
autosql=google::cloud::spanner::SqlStatement(R"""(
 INSERT INTO Singers (SingerId, FirstName, LastName)
 VALUES (12, 'Melissa', 'Garcia'),
 (13, 'Russell', 'Morales'),
 (14, 'Jacqueline', 'Long'),
 (15, 'Dylan', 'Shaw')
 RETURNING FullName
 )""");
usingRowType=std::tuple<std::string>;
autorows=client.ExecuteQuery(std::move(txn),std::move(sql));
for(auto&row:google::cloud::spanner::StreamOf<RowType>(rows)){
if(!row)returnstd::move(row).status();
std::cout << "FullName: " << std::get<0>(*row) << "\n";
}
std::cout << "Inserted row(s) count: " << rows.RowsModified() << "\n";
returngoogle::cloud::spanner::Mutations{};
});
if(!commit)throwstd::move(commit).status();
}

C#


usingGoogle.Cloud.Spanner.Data ;
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Threading.Tasks;
publicclassInsertUsingDmlReturningAsyncPostgresSample
{
publicasyncTask<List<string>>InsertUsingDmlReturningAsyncPostgres(stringprojectId,stringinstanceId,stringdatabaseId)
{
stringconnectionString=$"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}";
usingvarconnection=newSpannerConnection (connectionString);
awaitconnection.OpenAsync ();
// Insert records into SINGERS table and return the
// generated column FullName of the inserted records
// using 'RETURNING FullName'.
// It is also possible to return all columns of all the
// inserted records by using 'RETURNING *'.
usingvarcmd=connection.CreateDmlCommand (
@"INSERT INTO Singers(SingerId, FirstName, LastName) VALUES
 (6, 'Melissa', 'Garcia'), 
 (7, 'Russell', 'Morales'), 
 (8, 'Jacqueline', 'Long'), 
 (9, 'Dylan', 'Shaw') RETURNING FullName");
varreader=awaitcmd.ExecuteReaderAsync ();
varinsertedSingerNames=newList<string>();
while(awaitreader.ReadAsync ())
{
insertedSingerNames.Add(reader.GetFieldValue<string>("fullname"));
}
Console.WriteLine($"{insertedSingerNames.Count} row(s) inserted...");
returninsertedSingerNames;
}
}

Go


import(
"context"
"fmt"
"io"
"cloud.google.com/go/spanner"
"google.golang.org/api/iterator"
)
funcpgInsertUsingDMLReturning(wio.Writer,dbstring)error{
ctx:=context.Background()
client,err:=spanner.NewClient(ctx,db)
iferr!=nil{
returnerr
}
deferclient.Close()
// Insert records into the SINGERS table and returns the
// generated column FullName of the inserted records using
// 'RETURNING FullName'.
// It is also possible to return all columns of all the
// inserted records by using 'RETURNING *'.
_,err=client.ReadWriteTransaction(ctx,func(ctxcontext.Context,txn*spanner.ReadWriteTransaction)error{
stmt:=spanner.Statement {
SQL:`INSERT INTO Singers (SingerId, FirstName, LastName)
			 VALUES (21, 'Melissa', 'Garcia'),
			 (22, 'Russell', 'Morales'),
			 (23, 'Jacqueline', 'Long'),
			 (24, 'Dylan', 'Shaw')
			 RETURNING FullName`,
}
iter:=txn.Query(ctx,stmt)
deferiter.Stop()
for{
row,err:=iter.Next()
iferr==iterator.Done{
break
}
iferr!=nil{
returnerr
}
varfullNamestring
iferr:=row.Columns (&fullName);err!=nil{
returnerr
}
fmt.Fprintf(w,"%s\n",fullName)
}
fmt.Fprintf(w,"%d record(s) inserted.\n",iter.RowCount)
returnnil
})
returnerr
}

Java


importcom.google.cloud.spanner.DatabaseClient ;
importcom.google.cloud.spanner.DatabaseId ;
importcom.google.cloud.spanner.ResultSet ;
importcom.google.cloud.spanner.Spanner ;
importcom.google.cloud.spanner.SpannerOptions ;
importcom.google.cloud.spanner.Statement ;
publicclass PgInsertUsingDmlReturningSample{
staticvoidinsertUsingDmlReturning(){
// TODO(developer): Replace these variables before running the sample.
finalStringprojectId="my-project";
finalStringinstanceId="my-instance";
finalStringdatabaseId="my-database";
insertUsingDmlReturning(projectId,instanceId,databaseId);
}
staticvoidinsertUsingDmlReturning(StringprojectId,StringinstanceId,StringdatabaseId){
try(Spanner spanner=
SpannerOptions .newBuilder()
.setProjectId(projectId)
.build()
.getService()){
finalDatabaseClient dbClient=
spanner.getDatabaseClient(DatabaseId .of(projectId,instanceId,databaseId));
// Insert records into SINGERS table and returns the
// generated column FullName of the inserted records
// using ‘RETURNING FullName’.
// It is also possible to return all columns of all the
// inserted records by using ‘RETURNING *’.
dbClient
.readWritreadWriteTransaction .run(
transaction->{
Stringsql=
"INSERT INTO Singers (SingerId, FirstName, LastName) VALUES "
+"(12, 'Melissa', 'Garcia'), "
+"(13, 'Russell', 'Morales'), "
+"(14, 'Jacqueline', 'Long'), "
+"(15, 'Dylan', 'Shaw') RETURNING FullName";
// readWriteTransaction.executeQuery(..) API should be used for executing
// DML statements with RETURNING clause.
try(ResultSeResultSetet=transaction.executeQuery(StatemenStatement )){
while(resultSet.next()){
System.out.println(resultSet.getString(0));
}
System.out.printf(
"Inserted row(s) count: %d\n",resultSet.getStats().getRowCountExact());
}
returnnull;
});
}
}
}

Node.js

// Imports the Google Cloud client library.
const{Spanner}=require('@google-cloud/spanner');
/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';
// Creates a client
constspanner=newSpanner ({
projectId:projectId,
});
functionpgInsertUsingDmlReturning(instanceId,databaseId){
// Gets a reference to a Cloud Spanner instance and database.
constinstance=spanner.instance(instanceId);
constdatabase=instance.database(databaseId);
database.runTransaction (async(err,transaction)=>{
if(err){
console.error(err);
return;
}
try{
const[rows,stats]=awaittransaction.run({
sql:'INSERT Into Singers (SingerId, FirstName, LastName) VALUES (1,ドル 2,ドル 3ドル) RETURNING FullName',
params:{
p1:18,
p2:'Virginia',
p3:'Watson',
},
});
constrowCount=Math.floor(stats[stats.rowCount ]);
console.log(
`Successfully inserted ${rowCount} record into the Singers table.`,
);
rows.forEach(row=>{
console.log(row.toJSON().fullname);
});
awaittransaction.commit();
}catch(err){
console.error('ERROR:',err);
}finally{
// Close the database when finished.
database.close();
}
});
}
pgInsertUsingDmlReturning(instanceId,databaseId);

PHP

use Google\Cloud\Spanner\SpannerClient;
/**
 * Inserts sample data into the given postgresql database using DML returning.
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function pg_insert_dml_returning(string $instanceId, string $databaseId): void
{
 $spanner = new SpannerClient();
 $instance = $spanner->instance($instanceId);
 $database = $instance->database($databaseId);
 // Insert records into SINGERS table and returns the generated column
 // FullName of the inserted records using ‘RETURNING FullName’. It is also
 // possible to return all columns of all the inserted records by using
 // ‘RETURNING *’.
 $sql = 'INSERT INTO Singers (Singerid, FirstName, LastName) '
 . "VALUES (12, 'Melissa', 'Garcia'), "
 . "(13, 'Russell', 'Morales'), "
 . "(14, 'Jacqueline', 'Long'), "
 . "(15, 'Dylan', 'Shaw') "
 . 'RETURNING FullName';
 $transaction = $database->transaction();
 $result = $transaction->execute($sql);
 foreach ($result->rows() as $row) {
 printf(
 '%s inserted.' . PHP_EOL,
 $row['fullname'],
 );
 }
 printf(
 'Inserted row(s) count: %d' . PHP_EOL,
 $result->stats()['rowCountExact']
 );
 $transaction->commit();
}

Python

# instance_id = "your-spanner-instance"
# database_id = "your-spanner-db-id"
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)
# Insert records into the SINGERS table and returns the
# generated column FullName of the inserted records using
# 'RETURNING FullName'.
# It is also possible to return all columns of all the
# inserted records by using 'RETURNING *'.
definsert_singers(transaction):
 results = transaction.execute_sql(
 "INSERT INTO Singers (SingerId, FirstName, LastName) VALUES "
 "(21, 'Luann', 'Chizoba'), "
 "(22, 'Denis', 'Patricio'), "
 "(23, 'Felxi', 'Ronan'), "
 "(24, 'Dominik', 'Martyna') "
 "RETURNING FullName"
 )
 for result in results:
 print("FullName: {}".format(*result))
 print("{} record(s) inserted.".format(results.stats.row_count_exact))
database.run_in_transaction(insert_singers)

Ruby

require"google/cloud/spanner"
##
# This is a snippet for showcasing how to use DML return feature with insert
# operation in PostgreSql.
#
# @param project_id [String] The ID of the Google Cloud project.
# @param instance_id [String] The ID of the spanner instance.
# @param database_id [String] The ID of the database.
#
defspanner_postgresql_insert_dml_returningproject_id:,instance_id:,database_id:
spanner=Google::Cloud::Spanner.newproject:project_id
client=spanner.clientinstance_id,database_id
client.transactiondo|transaction|
# Insert records into SINGERS table and returns the generated column
# FullName of the inserted records using ‘RETURNING FullName’.
# It is also possible to return all columns of all the inserted
# records by using ‘RETURNING *’.
results=transaction.execute_query"INSERT INTO Singers (SingerId, FirstName, LastName)
 VALUES (12, 'Melissa', 'Garcia'), (13, 'Russell', 'Morales'), (14, 'Jacqueline', 'Long'), (15, 'Dylan', 'Shaw')
 RETURNING FullName"
results.rows.eachdo|row|
puts"Inserted singers with FullName: #{row[:fullname]}"
end
puts"Inserted row(s) count: #{results.row_count}"
end
end

The following code example updates the MarketingBudget column of the Albums table based on a WHERE clause, and it returns the modified MarketingBudget column of the updated records.

GoogleSQL

C++

voidUpdateUsingDmlReturning(google::cloud::spanner::Clientclient){
//UpdateMarketingBudgetcolumnforrecordssatisfyingaparticular
//conditionandreturnthemodifiedMarketingBudgetcolumnofthe
//updatedrecordsusing`THEN RETURN MarketingBudget`.
autocommit=client.Commit(
[&client](google::cloud::spanner::Transactiontxn)
->google::cloud::StatusOr<google::cloud::spanner::Mutations>{
autosql=google::cloud::spanner::SqlStatement(R"""(
 UPDATE Albums SET MarketingBudget = MarketingBudget * 2
 WHERE SingerId = 1 AND AlbumId = 1
 THEN RETURN MarketingBudget
 )""");
usingRowType=std::tuple<absl::optional<std::int64_t>>;
autorows=client.ExecuteQuery(std::move(txn),std::move(sql));
//Note:Thismutatormightbere-run,oritseffectsdiscarded,so
//changingnon-transactionalstate(e.g.,byproducingoutput)is,
//ingeneral,notsomethingtobeimitated.
for(auto&row:google::cloud::spanner::StreamOf<RowType>(rows)){
if(!row)returnstd::move(row).status();
std::cout << "MarketingBudget: ";
if(std::get<0>(*row).has_value()){
std::cout << *std::get<0>(*row);
}else{
std::cout << "NULL";
}
std::cout << "\n";
}
std::cout << "Updated row(s) count: " << rows.RowsModified() << "\n";
returngoogle::cloud::spanner::Mutations{};
});
if(!commit)throwstd::move(commit).status();
}

C#


usingGoogle.Cloud.Spanner.Data ;
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Threading.Tasks;
publicclassUpdateUsingDmlReturningAsyncSample
{
publicasyncTask<List<long>>UpdateUsingDmlReturningAsync(stringprojectId,stringinstanceId,stringdatabaseId)
{
stringconnectionString=$"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}";
usingvarconnection=newSpannerConnection (connectionString);
awaitconnection.OpenAsync ();
// Update MarketingBudget column for records satisfying
// a particular condition and return the modified
// MarketingBudget column of the updated records using
// 'THEN RETURN MarketingBudget'.
// It is also possible to return all columns of all the
// updated records by using 'THEN RETURN *'.
usingvarcmd=connection.CreateDmlCommand ("UPDATE Albums SET MarketingBudget = MarketingBudget * 2 WHERE SingerId = 1 and AlbumId = 1 THEN RETURN MarketingBudget");
varreader=awaitcmd.ExecuteReaderAsync ();
varupdatedMarketingBudgets=newList<long>();
while(awaitreader.ReadAsync ())
{
updatedMarketingBudgets.Add(reader.GetFieldValue<long>("MarketingBudget"));
}
Console.WriteLine($"{updatedMarketingBudgets.Count} row(s) updated...");
returnupdatedMarketingBudgets;
}
}

Go


import(
"context"
"fmt"
"io"
"cloud.google.com/go/spanner"
"google.golang.org/api/iterator"
)
funcupdateUsingDMLReturning(wio.Writer,dbstring)error{
ctx:=context.Background()
client,err:=spanner.NewClient(ctx,db)
iferr!=nil{
returnerr
}
deferclient.Close()
// Update MarketingBudget column for records satisfying
// a particular condition and returns the modified
// MarketingBudget column of the updated records using
// 'THEN RETURN MarketingBudget'.
// It is also possible to return all columns of all the
// updated records by using 'THEN RETURN *'.
_,err=client.ReadWriteTransaction(ctx,func(ctxcontext.Context,txn*spanner.ReadWriteTransaction)error{
stmt:=spanner.Statement {
SQL:`UPDATE Albums
				SET MarketingBudget = MarketingBudget * 2
				WHERE SingerId = 1 and AlbumId = 1
				THEN RETURN MarketingBudget`,
}
iter:=txn.Query(ctx,stmt)
deferiter.Stop()
for{
row,err:=iter.Next()
iferr==iterator.Done{
break
}
iferr!=nil{
returnerr
}
varmarketingBudgetint64
iferr:=row.Columns (&marketingBudget);err!=nil{
returnerr
}
fmt.Fprintf(w,"%d\n",marketingBudget)
}
fmt.Fprintf(w,"%d record(s) updated.\n",iter.RowCount)
returnnil
})
returnerr
}

Java


importcom.google.cloud.spanner.DatabaseClient ;
importcom.google.cloud.spanner.DatabaseId ;
importcom.google.cloud.spanner.ResultSet ;
importcom.google.cloud.spanner.Spanner ;
importcom.google.cloud.spanner.SpannerOptions ;
importcom.google.cloud.spanner.Statement ;
publicclass UpdateUsingDmlReturningSample{
staticvoidupdateUsingDmlReturning(){
// TODO(developer): Replace these variables before running the sample.
finalStringprojectId="my-project";
finalStringinstanceId="my-instance";
finalStringdatabaseId="my-database";
updateUsingDmlReturning(projectId,instanceId,databaseId);
}
staticvoidupdateUsingDmlReturning(StringprojectId,StringinstanceId,StringdatabaseId){
try(Spanner spanner=
SpannerOptions .newBuilder()
.setProjectId(projectId)
.build()
.getService()){
finalDatabaseClient dbClient=
spanner.getDatabaseClient(DatabaseId .of(projectId,instanceId,databaseId));
// Update MarketingBudget column for records satisfying
// a particular condition and returns the modified
// MarketingBudget column of the updated records using
// ‘THEN RETURN MarketingBudget’.
// It is also possible to return all columns of all the
// updated records by using ‘THEN RETURN *’.
dbClient
.readWritreadWriteTransaction .run(
transaction->{
Stringsql=
"UPDATE Albums "
+"SET MarketingBudget = MarketingBudget * 2 "
+"WHERE SingerId = 1 and AlbumId = 1 "
+"THEN RETURN MarketingBudget";
// readWriteTransaction.executeQuery(..) API should be used for executing
// DML statements with RETURNING clause.
try(ResultSeResultSetet=transaction.executeQuery(StatemenStatement )){
while(resultSet.next()){
System.out.printf("%d\n",resultSet.getLong(0));
}
System.out.printf(
"Updated row(s) count: %d\n",resultSet.getStats().getRowCountExact());
}
returnnull;
});
}
}
}

Node.js

// Imports the Google Cloud client library.
const{Spanner}=require('@google-cloud/spanner');
/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';
// Creates a client
constspanner=newSpanner ({
projectId:projectId,
});
functionupdateUsingDmlReturning(instanceId,databaseId){
// Gets a reference to a Cloud Spanner instance and database.
constinstance=spanner.instance(instanceId);
constdatabase=instance.database(databaseId);
database.runTransaction (async(err,transaction)=>{
if(err){
console.error(err);
return;
}
try{
const[rows,stats]=awaittransaction.run({
sql:'UPDATE Albums SET MarketingBudget = 2000000 WHERE SingerId = 1 and AlbumId = 1 THEN RETURN MarketingBudget',
});
constrowCount=Math.floor(stats[stats.rowCount ]);
console.log(
`Successfully updated ${rowCount} record into the Albums table.`,
);
rows.forEach(row=>{
console.log(row.toJSON().MarketingBudget);
});
awaittransaction.commit();
}catch(err){
console.error('ERROR:',err);
}finally{
// Close the database when finished.
database.close();
}
});
}
updateUsingDmlReturning(instanceId,databaseId);

PHP

use Google\Cloud\Spanner\SpannerClient;
/**
 * Update the given database using DML returning.
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function update_dml_returning(string $instanceId, string $databaseId): void
{
 $spanner = new SpannerClient();
 $instance = $spanner->instance($instanceId);
 $database = $instance->database($databaseId);
 $transaction = $database->transaction();
 // Update MarketingBudget column for records satisfying a particular
 // condition and returns the modified MarketingBudget column of the updated
 // records using ‘THEN RETURN MarketingBudget’. It is also possible to return
 // all columns of all the updated records by using ‘THEN RETURN *’.
 $result = $transaction->execute(
 'UPDATE Albums '
 . 'SET MarketingBudget = MarketingBudget * 2 '
 . 'WHERE SingerId = 1 and AlbumId = 1 '
 . 'THEN RETURN MarketingBudget'
 );
 foreach ($result->rows() as $row) {
 printf('MarketingBudget: %s' . PHP_EOL, $row['MarketingBudget']);
 }
 printf(
 'Updated row(s) count: %d' . PHP_EOL,
 $result->stats()['rowCountExact']
 );
 $transaction->commit();
}

Python

# instance_id = "your-spanner-instance"
# database_id = "your-spanner-db-id"
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)
# Update MarketingBudget column for records satisfying
# a particular condition and returns the modified
# MarketingBudget column of the updated records using
# 'THEN RETURN MarketingBudget'.
# It is also possible to return all columns of all the
# updated records by using 'THEN RETURN *'.
defupdate_albums(transaction):
 results = transaction.execute_sql(
 "UPDATE Albums "
 "SET MarketingBudget = MarketingBudget * 2 "
 "WHERE SingerId = 1 and AlbumId = 1 "
 "THEN RETURN MarketingBudget"
 )
 for result in results:
 print("MarketingBudget: {}".format(*result))
 print("{} record(s) updated.".format(results.stats.row_count_exact))
database.run_in_transaction(update_albums)

Ruby

require"google/cloud/spanner"
##
# This is a snippet for showcasing how to use DML return feature with update
# operation.
#
# @param project_id [String] The ID of the Google Cloud project.
# @param instance_id [String] The ID of the spanner instance.
# @param database_id [String] The ID of the database.
#
defspanner_update_dml_returningproject_id:,instance_id:,database_id:
spanner=Google::Cloud::Spanner.newproject:project_id
client=spanner.clientinstance_id,database_id
client.transactiondo|transaction|
# Update MarketingBudget column for records satisfying a particular
# condition and returns the modified MarketingBudget column of the
# updated records using ‘THEN RETURN MarketingBudget’.
#
# It is also possible to return all columns of all the updated records
# by using ‘THEN RETURN *’.
results=transaction.execute_query"UPDATE Albums SET MarketingBudget = MarketingBudget * 2
 WHERE SingerId = 1 and AlbumId = 1
 THEN RETURN MarketingBudget"
results.rows.eachdo|row|
puts"Updated Album with MarketingBudget: #{row[:MarketingBudget]}"
end
puts"Updated row(s) count: #{results.row_count}"
end
end

PostgreSQL

C++

voidUpdateUsingDmlReturning(google::cloud::spanner::Clientclient){
//UpdateMarketingBudgetcolumnforrecordssatisfyingaparticular
//conditionandreturnthemodifiedMarketingBudgetcolumnofthe
//updatedrecordsusing`RETURNINGMarketingBudget`.
autocommit=client.Commit(
[&client](google::cloud::spanner::Transactiontxn)
->google::cloud::StatusOr<google::cloud::spanner::Mutations>{
autosql=google::cloud::spanner::SqlStatement(R"""(
 UPDATE Albums SET MarketingBudget = MarketingBudget * 2
 WHERE SingerId = 1 AND AlbumId = 1
 RETURNING MarketingBudget
 )""");
usingRowType=std::tuple<absl::optional<std::int64_t>>;
autorows=client.ExecuteQuery(std::move(txn),std::move(sql));
for(auto&row:google::cloud::spanner::StreamOf<RowType>(rows)){
if(!row)returnstd::move(row).status();
std::cout << "MarketingBudget: ";
if(std::get<0>(*row).has_value()){
std::cout << *std::get<0>(*row);
}else{
std::cout << "NULL";
}
std::cout << "\n";
}
std::cout << "Updated row(s) count: " << rows.RowsModified() << "\n";
returngoogle::cloud::spanner::Mutations{};
});
if(!commit)throwstd::move(commit).status();
}

C#


usingGoogle.Cloud.Spanner.Data ;
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Threading.Tasks;
publicclassUpdateUsingDmlReturningAsyncPostgresSample
{
publicasyncTask<List<long>>UpdateUsingDmlReturningAsyncPostgres(stringprojectId,stringinstanceId,stringdatabaseId)
{
stringconnectionString=$"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}";
usingvarconnection=newSpannerConnection (connectionString);
awaitconnection.OpenAsync ();
// Update MarketingBudget column for records satisfying
// a particular condition and return the modified
// MarketingBudget column of the updated records using
// 'RETURNING MarketingBudget'.
// It is also possible to return all columns of all the
// updated records by using 'RETURNING *'.
usingvarcmd=connection.CreateDmlCommand ("UPDATE Albums SET MarketingBudget = MarketingBudget * 2 WHERE SingerId = 14 and AlbumId = 20 RETURNING MarketingBudget");
varreader=awaitcmd.ExecuteReaderAsync ();
varupdatedMarketingBudgets=newList<long>();
while(awaitreader.ReadAsync ())
{
updatedMarketingBudgets.Add(reader.GetFieldValue<long>("marketingbudget"));
}
Console.WriteLine($"{updatedMarketingBudgets.Count} row(s) updated...");
returnupdatedMarketingBudgets;
}
}

Go


import(
"context"
"fmt"
"io"
"cloud.google.com/go/spanner"
"google.golang.org/api/iterator"
)
funcpgUpdateUsingDMLReturning(wio.Writer,dbstring)error{
ctx:=context.Background()
client,err:=spanner.NewClient(ctx,db)
iferr!=nil{
returnerr
}
deferclient.Close()
// Update MarketingBudget column for records satisfying
// a particular condition and returns the modified
// MarketingBudget column of the updated records using
// 'RETURNING MarketingBudget'.
// It is also possible to return all columns of all the
// updated records by using 'RETURNING *'.
_,err=client.ReadWriteTransaction(ctx,func(ctxcontext.Context,txn*spanner.ReadWriteTransaction)error{
stmt:=spanner.Statement {
SQL:`UPDATE Albums
				SET MarketingBudget = MarketingBudget * 2
				WHERE SingerId = 1 and AlbumId = 1
				RETURNING MarketingBudget`,
}
iter:=txn.Query(ctx,stmt)
deferiter.Stop()
for{
row,err:=iter.Next()
iferr==iterator.Done{
break
}
iferr!=nil{
returnerr
}
varmarketingBudgetint64
iferr:=row.Columns (&marketingBudget);err!=nil{
returnerr
}
fmt.Fprintf(w,"%d\n",marketingBudget)
}
fmt.Fprintf(w,"%d record(s) updated.\n",iter.RowCount)
returnnil
})
returnerr
}

Java


importcom.google.cloud.spanner.DatabaseClient ;
importcom.google.cloud.spanner.DatabaseId ;
importcom.google.cloud.spanner.ResultSet ;
importcom.google.cloud.spanner.Spanner ;
importcom.google.cloud.spanner.SpannerOptions ;
importcom.google.cloud.spanner.Statement ;
publicclass PgUpdateUsingDmlReturningSample{
staticvoidupdateUsingDmlReturning(){
// TODO(developer): Replace these variables before running the sample.
finalStringprojectId="my-project";
finalStringinstanceId="my-instance";
finalStringdatabaseId="my-database";
updateUsingDmlReturning(projectId,instanceId,databaseId);
}
staticvoidupdateUsingDmlReturning(StringprojectId,StringinstanceId,StringdatabaseId){
try(Spanner spanner=
SpannerOptions .newBuilder()
.setProjectId(projectId)
.build()
.getService()){
finalDatabaseClient dbClient=
spanner.getDatabaseClient(DatabaseId .of(projectId,instanceId,databaseId));
// Update MarketingBudget column for records satisfying
// a particular condition and returns the modified
// MarketingBudget column of the updated records using
// ‘RETURNING MarketingBudget’.
// It is also possible to return all columns of all the
// updated records by using ‘RETURNING *’.
dbClient
.readWritreadWriteTransaction .run(
transaction->{
Stringsql=
"UPDATE Albums "
+"SET MarketingBudget = MarketingBudget * 2 "
+"WHERE SingerId = 1 and AlbumId = 1 "
+"RETURNING MarketingBudget";
// readWriteTransaction.executeQuery(..) API should be used for executing
// DML statements with RETURNING clause.
try(ResultSeResultSetet=transaction.executeQuery(StatemenStatement )){
while(resultSet.next()){
System.out.printf("%d\n",resultSet.getLong(0));
}
System.out.printf(
"Updated row(s) count: %d\n",resultSet.getStats().getRowCountExact());
}
returnnull;
});
}
}
}

Node.js

// Imports the Google Cloud client library.
const{Spanner}=require('@google-cloud/spanner');
/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';
// Creates a client
constspanner=newSpanner ({
projectId:projectId,
});
functionpgUpdateUsingDmlReturning(instanceId,databaseId){
// Gets a reference to a Cloud Spanner instance and database.
constinstance=spanner.instance(instanceId);
constdatabase=instance.database(databaseId);
database.runTransaction (async(err,transaction)=>{
if(err){
console.error(err);
return;
}
try{
const[rows,stats]=awaittransaction.run({
sql:'UPDATE singers SET FirstName = 1,ドル LastName = 2ドル WHERE singerid = 3ドル RETURNING FullName',
params:{
p1:'Virginia1',
p2:'Watson1',
p3:18,
},
});
constrowCount=Math.floor(stats[stats.rowCount ]);
console.log(
`Successfully updated ${rowCount} record into the Singers table.`,
);
rows.forEach(row=>{
console.log(row.toJSON().fullname);
});
awaittransaction.commit();
}catch(err){
console.error('ERROR:',err);
}finally{
// Close the database when finished.
database.close();
}
});
}
pgUpdateUsingDmlReturning(instanceId,databaseId);

PHP

use Google\Cloud\Spanner\SpannerClient;
/**
 * Update the given postgresql database using DML returning.
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function pg_update_dml_returning(string $instanceId, string $databaseId): void
{
 $spanner = new SpannerClient();
 $instance = $spanner->instance($instanceId);
 $database = $instance->database($databaseId);
 $transaction = $database->transaction();
 // Update MarketingBudget column for records satisfying a particular
 // condition and returns the modified MarketingBudget column of the updated
 // records using ‘RETURNING MarketingBudget’. It is also possible to return
 // all columns of all the updated records by using ‘RETURNING *’.
 $result = $transaction->execute(
 'UPDATE Albums '
 . 'SET MarketingBudget = MarketingBudget * 2 '
 . 'WHERE SingerId = 1 and AlbumId = 1 '
 . 'RETURNING MarketingBudget'
 );
 foreach ($result->rows() as $row) {
 printf('MarketingBudget: %s' . PHP_EOL, $row['marketingbudget']);
 }
 printf(
 'Updated row(s) count: %d' . PHP_EOL,
 $result->stats()['rowCountExact']
 );
 $transaction->commit();
}

Python

# instance_id = "your-spanner-instance"
# database_id = "your-spanner-db-id"
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)
# Update MarketingBudget column for records satisfying
# a particular condition and returns the modified
# MarketingBudget column of the updated records using
# 'RETURNING MarketingBudget'.
# It is also possible to return all columns of all the
# updated records by using 'RETURNING *'.
defupdate_albums(transaction):
 results = transaction.execute_sql(
 "UPDATE Albums "
 "SET MarketingBudget = MarketingBudget * 2 "
 "WHERE SingerId = 1 and AlbumId = 1 "
 "RETURNING MarketingBudget"
 )
 for result in results:
 print("MarketingBudget: {}".format(*result))
 print("{} record(s) updated.".format(results.stats.row_count_exact))
database.run_in_transaction(update_albums)

Ruby

require"google/cloud/spanner"
##
# This is a snippet for showcasing how to use DML return feature with update
# operation in PostgreSql.
#
# @param project_id [String] The ID of the Google Cloud project.
# @param instance_id [String] The ID of the spanner instance.
# @param database_id [String] The ID of the database.
#
defspanner_postgresql_update_dml_returningproject_id:,instance_id:,database_id:
spanner=Google::Cloud::Spanner.newproject:project_id
client=spanner.clientinstance_id,database_id
client.transactiondo|transaction|
# Update MarketingBudget column for records satisfying a particular
# condition and returns the modified MarketingBudget column of the
# updated records using ‘RETURNING MarketingBudget’.
# It is also possible to return all columns of all the updated records
# by using ‘RETURNING *’.
results=transaction.execute_query"UPDATE Albums SET MarketingBudget = MarketingBudget * 2
 WHERE SingerId = 1 and AlbumId = 1
 RETURNING MarketingBudget"
results.rows.eachdo|row|
puts"Updated Albums with MarketingBudget: #{row[:marketingbudget]}"
end
puts"Updated row(s) count: #{results.row_count}"
end
end

The following code example deletes all the rows in the Singers table where the FirstName column is Alice, and it returns the SingerId and FullName column of the deleted records.

GoogleSQL

C++

voidDeleteUsingDmlReturning(google::cloud::spanner::Clientclient){
//DeleterecordsfromSINGERStablesatisfyingaparticularcondition
//andreturntheSingerIdandFullNamecolumnofthedeletedrecords
//using`THEN RETURN SingerId, FullName'.
 auto commit = client.Commit(
 [&client](google::cloud::spanner::Transaction txn)
 -> google::cloud::StatusOr<google::cloud::spanner::Mutations> {
 auto sql = google::cloud::spanner::SqlStatement(R"""(
 DELETE FROM Singers
 WHERE FirstName = 'Alice'
 THEN RETURN SingerId, FullName
 )""");
 using RowType = std::tuple<std::int64_t, std::string>;
 auto rows = client.ExecuteQuery(std::move(txn), std::move(sql));
 // Note: This mutator might be re-run, or its effects discarded, so
 // changing non-transactional state (e.g., by producing output) is,
 // in general, not something to be imitated.
 for (auto& row : google::cloud::spanner::StreamOf<RowType>(rows)) {
 if (!row) return std::move(row).status();
 std::cout << "SingerId: " << std::get<0>(*row) << " ";
 std::cout << "FullName: " << std::get<1>(*row) << "\n";
 }
 std::cout << "Deleted row(s) count: " << rows.RowsModified() << "\n";
 return google::cloud::spanner::Mutations{};
 });
 if (!commit) throw std::move(commit).status();
}

C#


usingGoogle.Cloud.Spanner.Data ;
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Threading;
usingSystem.Threading.Tasks;
publicclassDeleteUsingDmlReturningAsyncSample
{
publicasyncTask<List<string>>DeleteUsingDmlReturningAsync(stringprojectId,stringinstanceId,stringdatabaseId)
{
stringconnectionString=$"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}";
usingvarconnection=newSpannerConnection (connectionString);
awaitconnection.OpenAsync ();
// Delete records from SINGERS table satisfying a
// particular condition and return the SingerId
// and FullName column of the deleted records using
// 'THEN RETURN SingerId, FullName'.
// It is also possible to return all columns of all the
// deleted records by using 'THEN RETURN *'.
usingvarcmd=connection.CreateDmlCommand ("DELETE FROM Singers WHERE FirstName = 'Alice' THEN RETURN SingerId, FullName");
varreader=awaitcmd.ExecuteReaderAsync ();
vardeletedSingerNames=newList<string>();
while(awaitreader.ReadAsync ())
{
deletedSingerNames.Add(reader.GetFieldValue<string>("FullName"));
}
Console.WriteLine($"{deletedSingerNames.Count} row(s) deleted...");
returndeletedSingerNames;
}
}

Go


import(
"context"
"fmt"
"io"
"cloud.google.com/go/spanner"
"google.golang.org/api/iterator"
)
funcdeleteUsingDMLReturning(wio.Writer,dbstring)error{
ctx:=context.Background()
client,err:=spanner.NewClient(ctx,db)
iferr!=nil{
returnerr
}
deferclient.Close()
// Delete records from SINGERS table satisfying a
// particular condition and returns the SingerId
// and FullName column of the deleted records using
// 'THEN RETURN SingerId, FullName'.
// It is also possible to return all columns of all the
// deleted records by using 'THEN RETURN *'.
_,err=client.ReadWriteTransaction(ctx,func(ctxcontext.Context,txn*spanner.ReadWriteTransaction)error{
stmt:=spanner.Statement {
SQL:`DELETE FROM Singers WHERE FirstName = 'Alice'
			 THEN RETURN SingerId, FullName`,
}
iter:=txn.Query(ctx,stmt)
deferiter.Stop()
for{
row,err:=iter.Next()
iferr==iterator.Done{
break
}
iferr!=nil{
returnerr
}
var(
singerIDint64
fullNamestring
)
iferr:=row.Columns (&singerID,&fullName);err!=nil{
returnerr
}
fmt.Fprintf(w,"%d %s\n",singerID,fullName)
}
fmt.Fprintf(w,"%d record(s) deleted.\n",iter.RowCount)
returnnil
})
returnerr
}

Java


importcom.google.cloud.spanner.DatabaseClient ;
importcom.google.cloud.spanner.DatabaseId ;
importcom.google.cloud.spanner.ResultSet ;
importcom.google.cloud.spanner.Spanner ;
importcom.google.cloud.spanner.SpannerOptions ;
importcom.google.cloud.spanner.Statement ;
publicclass DeleteUsingDmlReturningSample{
staticvoiddeleteUsingDmlReturningSample(){
// TODO(developer): Replace these variables before running the sample.
finalStringprojectId="my-project";
finalStringinstanceId="my-instance";
finalStringdatabaseId="my-database";
deleteUsingDmlReturningSample(projectId,instanceId,databaseId);
}
staticvoiddeleteUsingDmlReturningSample(
StringprojectId,StringinstanceId,StringdatabaseId){
try(Spanner spanner=
SpannerOptions .newBuilder()
.setProjectId(projectId)
.build()
.getService()){
finalDatabaseClient dbClient=
spanner.getDatabaseClient(DatabaseId .of(projectId,instanceId,databaseId));
// Delete records from SINGERS table satisfying a
// particular condition and returns the SingerId
// and FullName column of the deleted records using
// ‘THEN RETURN SingerId, FullName’.
// It is also possible to return all columns of all the
// deleted records by using ‘THEN RETURN *’.
dbClient
.readWritreadWriteTransaction .run(
transaction->{
Stringsql=
"DELETE FROM Singers WHERE FirstName = 'Alice' THEN RETURN SingerId, FullName";
// readWriteTransaction.executeQuery(..) API should be used for executing
// DML statements with RETURNING clause.
try(ResultSeResultSetet=transaction.executeQuery(StatemenStatement )){
while(resultSet.next()){
System.out.printf("%d %s\n",resultSet.getLong(0),resultSet.getString(1));
}
System.out.printf(
"Deleted row(s) count: %d\n",resultSet.getStats().getRowCountExact());
}
returnnull;
});
}
}
}

Node.js

// Imports the Google Cloud client library.
const{Spanner}=require('@google-cloud/spanner');
/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';
// Creates a client
constspanner=newSpanner ({
projectId:projectId,
});
functiondeleteUsingDmlReturning(instanceId,databaseId){
// Gets a reference to a Cloud Spanner instance and database.
constinstance=spanner.instance(instanceId);
constdatabase=instance.database(databaseId);
database.runTransaction (async(err,transaction)=>{
if(err){
console.error(err);
return;
}
try{
const[rows,stats]=awaittransaction.run({
sql:'DELETE FROM Singers WHERE SingerId = 18 THEN RETURN FullName',
});
constrowCount=Math.floor(stats[stats.rowCount ]);
console.log(
`Successfully deleted ${rowCount} record from the Singers table.`,
);
rows.forEach(row=>{
console.log(row.toJSON().FullName);
});
awaittransaction.commit();
}catch(err){
console.error('ERROR:',err);
}finally{
// Close the database when finished.
database.close();
}
});
}
deleteUsingDmlReturning(instanceId,databaseId);

PHP

use Google\Cloud\Spanner\SpannerClient;
/**
 * Delete data from the given database using DML returning.
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function delete_dml_returning(string $instanceId, string $databaseId): void
{
 $spanner = new SpannerClient();
 $instance = $spanner->instance($instanceId);
 $database = $instance->database($databaseId);
 $transaction = $database->transaction();
 // Delete records from SINGERS table satisfying a particular condition and
 // returns the SingerId and FullName column of the deleted records using
 // 'THEN RETURN SingerId, FullName'. It is also possible to return all columns
 // of all the deleted records by using 'THEN RETURN *'.
 $result = $transaction->execute(
 "DELETE FROM Singers WHERE FirstName = 'Alice' "
 . 'THEN RETURN SingerId, FullName',
 );
 foreach ($result->rows() as $row) {
 printf(
 '%d %s.' . PHP_EOL,
 $row['SingerId'],
 $row['FullName']
 );
 }
 printf(
 'Deleted row(s) count: %d' . PHP_EOL,
 $result->stats()['rowCountExact']
 );
 $transaction->commit();
}

Python

# instance_id = "your-spanner-instance"
# database_id = "your-spanner-db-id"
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)
# Delete records from SINGERS table satisfying a
# particular condition and returns the SingerId
# and FullName column of the deleted records using
# 'THEN RETURN SingerId, FullName'.
# It is also possible to return all columns of all the
# deleted records by using 'THEN RETURN *'.
defdelete_singers(transaction):
 results = transaction.execute_sql(
 "DELETE FROM Singers WHERE FirstName = 'David' "
 "THEN RETURN SingerId, FullName"
 )
 for result in results:
 print("SingerId: {}, FullName: {}".format(*result))
 print("{} record(s) deleted.".format(results.stats.row_count_exact))
database.run_in_transaction(delete_singers)

Ruby

require"google/cloud/spanner"
##
# This is a snippet for showcasing how to use DML return feature with delete
# operation.
#
# @param project_id [String] The ID of the Google Cloud project.
# @param instance_id [String] The ID of the spanner instance.
# @param database_id [String] The ID of the database.
#
defspanner_delete_dml_returningproject_id:,instance_id:,database_id:
spanner=Google::Cloud::Spanner.newproject:project_id
client=spanner.clientinstance_id,database_id
client.transactiondo|transaction|
# Delete records from SINGERS table satisfying a particular condition and
# returns the SingerId and FullName column of the deleted records using
# ‘THEN RETURN SingerId, FullName’.
# It is also possible to return all columns of all the deleted records
# by using ‘THEN RETURN *’.
results=transaction.execute_query"DELETE FROM Singers WHERE FirstName = 'Alice' THEN RETURN SingerId, FullName"
results.rows.eachdo|row|
puts"Deleted singer with SingerId: #{row[:SingerId]}, FullName: #{row[:FullName]}"
end
puts"Deleted row(s) count: #{results.row_count}"
end
end

PostgreSQL

C++

voidDeleteUsingDmlReturning(google::cloud::spanner::Clientclient){
//DeleterecordsfromSINGERStablesatisfyingaparticularcondition
//andreturntheSingerIdandFullNamecolumnofthedeletedrecords
//using`RETURNINGSingerId,FullName'.
 auto commit = client.Commit(
 [&client](google::cloud::spanner::Transaction txn)
 -> google::cloud::StatusOr<google::cloud::spanner::Mutations> {
 auto sql = google::cloud::spanner::SqlStatement(R"""(
 DELETE FROM Singers
 WHERE FirstName = 'Alice'
 RETURNING SingerId, FullName
 )""");
 using RowType = std::tuple<std::int64_t, std::string>;
 auto rows = client.ExecuteQuery(std::move(txn), std::move(sql));
 for (auto& row : google::cloud::spanner::StreamOf<RowType>(rows)) {
 if (!row) return std::move(row).status();
 std::cout << "SingerId: " << std::get<0>(*row) << " ";
 std::cout << "FullName: " << std::get<1>(*row) << "\n";
 }
 std::cout << "Deleted row(s) count: " << rows.RowsModified() << "\n";
 return google::cloud::spanner::Mutations{};
 });
 if (!commit) throw std::move(commit).status();
}

C#


usingGoogle.Cloud.Spanner.Data ;
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Threading.Tasks;
publicclassDeleteUsingDmlReturningAsyncPostgresSample
{
publicasyncTask<List<string>>DeleteUsingDmlReturningAsyncPostgres(stringprojectId,stringinstanceId,stringdatabaseId)
{
stringconnectionString=$"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}";
usingvarconnection=newSpannerConnection (connectionString);
awaitconnection.OpenAsync ();
// Delete records from SINGERS table satisfying a
// particular condition and return the SingerId
// and FullName column of the deleted records using
// 'RETURNING SingerId, FullName'.
// It is also possible to return all columns of all the
// deleted records by using 'RETURNING *'.
usingvarcmd=connection.CreateDmlCommand ("DELETE FROM Singers WHERE FirstName = 'Lata' RETURNING SingerId, FullName");
varreader=awaitcmd.ExecuteReaderAsync ();
vardeletedSingerNames=newList<string>();
while(awaitreader.ReadAsync ())
{
deletedSingerNames.Add(reader.GetFieldValue<string>("fullname"));
}
Console.WriteLine($"{deletedSingerNames.Count} row(s) deleted...");
returndeletedSingerNames;
}
}

Go


import(
"context"
"fmt"
"io"
"cloud.google.com/go/spanner"
"google.golang.org/api/iterator"
)
funcpgDeleteUsingDMLReturning(wio.Writer,dbstring)error{
ctx:=context.Background()
client,err:=spanner.NewClient(ctx,db)
iferr!=nil{
returnerr
}
deferclient.Close()
// Delete records from SINGERS table satisfying a
// particular condition and returns the SingerId
// and FullName column of the deleted records using
// 'RETURNING SingerId, FullName'.
// It is also possible to return all columns of all the
// deleted records by using 'RETURNING *'.
_,err=client.ReadWriteTransaction(ctx,func(ctxcontext.Context,txn*spanner.ReadWriteTransaction)error{
stmt:=spanner.Statement {
SQL:`DELETE FROM Singers WHERE FirstName = 'Alice'
			 RETURNING SingerId, FullName`,
}
iter:=txn.Query(ctx,stmt)
deferiter.Stop()
for{
row,err:=iter.Next()
iferr==iterator.Done{
break
}
iferr!=nil{
returnerr
}
var(
singerIDint64
fullNamestring
)
iferr:=row.Columns (&singerID,&fullName);err!=nil{
returnerr
}
fmt.Fprintf(w,"%d %s\n",singerID,fullName)
}
fmt.Fprintf(w,"%d record(s) deleted.\n",iter.RowCount)
returnnil
})
returnerr
}

Java


importcom.google.cloud.spanner.DatabaseClient ;
importcom.google.cloud.spanner.DatabaseId ;
importcom.google.cloud.spanner.ResultSet ;
importcom.google.cloud.spanner.Spanner ;
importcom.google.cloud.spanner.SpannerOptions ;
importcom.google.cloud.spanner.Statement ;
publicclass PgDeleteUsingDmlReturningSample{
staticvoiddeleteUsingDmlReturningSample(){
// TODO(developer): Replace these variables before running the sample.
finalStringprojectId="my-project";
finalStringinstanceId="my-instance";
finalStringdatabaseId="my-database";
deleteUsingDmlReturningSample(projectId,instanceId,databaseId);
}
staticvoiddeleteUsingDmlReturningSample(
StringprojectId,StringinstanceId,StringdatabaseId){
try(Spanner spanner=
SpannerOptions .newBuilder()
.setProjectId(projectId)
.build()
.getService()){
finalDatabaseClient dbClient=
spanner.getDatabaseClient(DatabaseId .of(projectId,instanceId,databaseId));
// Delete records from SINGERS table satisfying a
// particular condition and returns the SingerId
// and FullName column of the deleted records using
// ‘RETURNING SingerId, FullName’.
// It is also possible to return all columns of all the
// deleted records by using ‘RETURNING *’.
dbClient
.readWritreadWriteTransaction .run(
transaction->{
Stringsql=
"DELETE FROM Singers WHERE FirstName = 'Alice' RETURNING SingerId, FullName";
// readWriteTransaction.executeQuery(..) API should be used for executing
// DML statements with RETURNING clause.
try(ResultSeResultSetet=transaction.executeQuery(StatemenStatement )){
while(resultSet.next()){
System.out.printf("%d %s\n",resultSet.getLong(0),resultSet.getString(1));
}
System.out.printf(
"Deleted row(s) count: %d\n",resultSet.getStats().getRowCountExact());
}
returnnull;
});
}
}
}

Node.js

// Imports the Google Cloud client library.
const{Spanner}=require('@google-cloud/spanner');
/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';
// Creates a client
constspanner=newSpanner ({
projectId:projectId,
});
functionpgDeleteUsingDmlReturning(instanceId,databaseId){
// Gets a reference to a Cloud Spanner instance and database.
constinstance=spanner.instance(instanceId);
constdatabase=instance.database(databaseId);
database.runTransaction (async(err,transaction)=>{
if(err){
console.error(err);
return;
}
try{
const[rows,stats]=awaittransaction.run({
sql:'DELETE FROM Singers WHERE SingerId = 18 RETURNING FullName',
});
constrowCount=Math.floor(stats[stats.rowCount ]);
console.log(
`Successfully deleted ${rowCount} record from the Singers table.`,
);
rows.forEach(row=>{
console.log(row.toJSON().fullname);
});
awaittransaction.commit();
}catch(err){
console.error('ERROR:',err);
}finally{
// Close the database when finished.
database.close();
}
});
}
pgDeleteUsingDmlReturning(instanceId,databaseId);

PHP

use Google\Cloud\Spanner\SpannerClient;
/**
 * Delete data from the given postgresql database using DML returning.
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function pg_delete_dml_returning(string $instanceId, string $databaseId): void
{
 $spanner = new SpannerClient();
 $instance = $spanner->instance($instanceId);
 $database = $instance->database($databaseId);
 $transaction = $database->transaction();
 // Delete records from SINGERS table satisfying a particular condition and
 // returns the SingerId and FullName column of the deleted records using
 // ‘RETURNING SingerId, FullName’. It is also possible to return all columns
 // of all the deleted records by using ‘RETURNING *’.
 $result = $transaction->execute(
 "DELETE FROM Singers WHERE FirstName = 'Alice' "
 . 'RETURNING SingerId, FullName',
 );
 foreach ($result->rows() as $row) {
 printf(
 '%d %s.' . PHP_EOL,
 $row['singerid'],
 $row['fullname']
 );
 }
 printf(
 'Deleted row(s) count: %d' . PHP_EOL,
 $result->stats()['rowCountExact']
 );
 $transaction->commit();
}

Python

# instance_id = "your-spanner-instance"
# database_id = "your-spanner-db-id"
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)
# Delete records from SINGERS table satisfying a
# particular condition and returns the SingerId
# and FullName column of the deleted records using
# 'RETURNING SingerId, FullName'.
# It is also possible to return all columns of all the
# deleted records by using 'RETURNING *'.
defdelete_singers(transaction):
 results = transaction.execute_sql(
 "DELETE FROM Singers WHERE FirstName = 'David' "
 "RETURNING SingerId, FullName"
 )
 for result in results:
 print("SingerId: {}, FullName: {}".format(*result))
 print("{} record(s) deleted.".format(results.stats.row_count_exact))
database.run_in_transaction(delete_singers)

Ruby

require"google/cloud/spanner"
##
# This is a snippet for showcasing how to use DML return feature with delete
# operation in PostgreSql.
#
# @param project_id [String] The ID of the Google Cloud project.
# @param instance_id [String] The ID of the spanner instance.
# @param database_id [String] The ID of the database.
#
defspanner_postgresql_delete_dml_returningproject_id:,instance_id:,database_id:
spanner=Google::Cloud::Spanner.newproject:project_id
client=spanner.clientinstance_id,database_id
client.transactiondo|transaction|
# Delete records from SINGERS table satisfying a particular condition and
# returns the SingerId and FullName column of the deleted records using
# ‘RETURNING SingerId, FullName’.
# It is also possible to return all columns of all the deleted records
# by using ‘RETURNING *’.
results=transaction.execute_query"DELETE FROM singers WHERE firstname = 'Alice' RETURNING SingerId, FullName"
results.rows.eachdo|row|
puts"Deleted singer with SingerId: #{row[:singerid]}, FullName: #{row[:fullname]}"
end
puts"Deleted row(s) count: #{results.row_count}"
end
end

Read data written in the same transaction

Changes you make using DML statements are visible to subsequent statements in the same transaction. This is different from using mutations, where changes are not visible until the transaction commits.

Spanner checks the constraints after every DML statement. This is different from using mutations, where Spanner buffers mutations in the client until commit and checks constraints at commit time. Evaluating the constraints after each statement allows Spanner to guarantee that the data that a DML statement returns is consistent with the schema.

The following example updates a row in the Singers table, then executes a SELECT statement to print the new values.

C++

voidDmlWriteThenRead(google::cloud::spanner::Clientclient){
namespacespanner=::google::cloud::spanner;
using::google::cloud::StatusOr;
autocommit_result=client.Commit(
[&client](spanner::Transactiontxn)->StatusOr<spanner::Mutations>{
autoinsert=client.ExecuteDml(
txn,spanner::SqlStatement(
"INSERT INTO Singers (SingerId, FirstName, LastName)"
" VALUES (11, 'Timothy', 'Campbell')"));
if(!insert)returnstd::move(insert).status();
// Read newly inserted record.
spanner::SqlStatementselect(
"SELECT FirstName, LastName FROM Singers where SingerId = 11");
usingRowType=std::tuple<std::string,std::string>;
autorows=client.ExecuteQuery(std::move(txn),std::move(select));
// Note: This mutator might be re-run, or its effects discarded, so
// changing non-transactional state (e.g., by producing output) is,
// in general, not something to be imitated.
for(autoconst&row:spanner::StreamOf<RowType>(rows)){
if(!row)returnstd::move(row).status();
std::cout << "FirstName: " << std::get<0>(*row) << "\t";
std::cout << "LastName: " << std::get<1>(*row) << "\n";
}
returnspanner::Mutations{};
});
if(!commit_result)throwstd::move(commit_result).status();
std::cout << "Write then read succeeded [spanner_dml_write_then_read]\n";
}

C#


usingGoogle.Cloud.Spanner.Data ;
usingSystem;
usingSystem.Threading.Tasks;
publicclassWriteAndReadUsingDmlCoreAsyncSample
{
publicasyncTask<int>WriteAndReadUsingDmlCoreAsync(stringprojectId,stringinstanceId,stringdatabaseId)
{
stringconnectionString=$"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}";
usingvarconnection=newSpannerConnection (connectionString);
awaitconnection.OpenAsync ();
usingvarcreateDmlCmd=connection.CreateDmlCommand (@"INSERT Singers (SingerId, FirstName, LastName) VALUES (11, 'Timothy', 'Campbell')");
introwCount=awaitcreateDmlCmd.ExecuteNonQueryAsync();
Console.WriteLine($"{rowCount} row(s) inserted...");
// Read newly inserted record.
usingvarcreateSelectCmd=connection.CreateSelectCommand (@"SELECT FirstName, LastName FROM Singers WHERE SingerId = 11");
usingvarreader=awaitcreateSelectCmd.ExecuteReaderAsync ();
while(awaitreader.ReadAsync ())
{
Console.WriteLine($"{reader.GetFieldValue<string>("FirstName")} {reader.GetFieldValue<string>("LastName")}");
}
returnrowCount;
}
}

Go


import(
"context"
"fmt"
"io"
"cloud.google.com/go/spanner"
"google.golang.org/api/iterator"
)
funcwriteAndReadUsingDML(wio.Writer,dbstring)error{
ctx:=context.Background()
client,err:=spanner.NewClient(ctx,db)
iferr!=nil{
returnerr
}
deferclient.Close()
_,err=client.ReadWriteTransaction(ctx,func(ctxcontext.Context,txn*spanner.ReadWriteTransaction)error{
// Insert Record
stmt:=spanner.Statement {
SQL:`INSERT Singers (SingerId, FirstName, LastName)
				VALUES (11, 'Timothy', 'Campbell')`,
}
rowCount,err:=txn.Update(ctx,stmt)
iferr!=nil{
returnerr
}
fmt.Fprintf(w,"%d record(s) inserted.\n",rowCount)
// Read newly inserted record
stmt=spanner.Statement {SQL:`SELECT FirstName, LastName FROM Singers WHERE SingerId = 11`}
iter:=txn.Query(ctx,stmt)
deferiter.Stop()
for{
row,err:=iter.Next()
iferr==iterator.Done||err!=nil{
break
}
varfirstName,lastNamestring
iferr:=row.ColumnByName ("FirstName",&firstName);err!=nil{
returnerr
}
iferr:=row.ColumnByName ("LastName",&lastName);err!=nil{
returnerr
}
fmt.Fprintf(w,"Found record name with %s, %s",firstName,lastName)
}
returnerr
})
returnerr
}

Java

staticvoidwriteAndReadUsingDml(DatabaseClientdbClient){
dbClient
.readWriteTransaction()
.run(transaction->{
// Insert record.
Stringsql=
"INSERT INTO Singers (SingerId, FirstName, LastName) "
+" VALUES (11, 'Timothy', 'Campbell')";
longrowCount=transaction.executeUpdate(Statement.of(sql));
System.out.printf("%d record inserted.\n",rowCount);
// Read newly inserted record.
sql="SELECT FirstName, LastName FROM Singers WHERE SingerId = 11";
// We use a try-with-resource block to automatically release resources held by
// ResultSet.
try(ResultSetresultSet=transaction.executeQuery(Statement.of(sql))){
while(resultSet.next()){
System.out.printf(
"%s %s\n",
resultSet.getString("FirstName"),resultSet.getString("LastName"));
}
}
returnnull;
});
}

Node.js

// Imports the Google Cloud client library
const{Spanner}=require('@google-cloud/spanner');
/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';
// Creates a client
constspanner=newSpanner ({
projectId:projectId,
});
// Gets a reference to a Cloud Spanner instance and database
constinstance=spanner.instance(instanceId);
constdatabase=instance.database(databaseId);
database.runTransaction (async(err,transaction)=>{
if(err){
console.error(err);
return;
}
try{
awaittransaction.runUpdate ({
sql:`INSERT Singers (SingerId, FirstName, LastName)
 VALUES (11, 'Timothy', 'Campbell')`,
});
const[rows]=awaittransaction.run({
sql:'SELECT FirstName, LastName FROM Singers',
});
rows.forEach(row=>{
constjson=row.toJSON();
console.log(`${json.FirstName}${json.LastName}`);
});
awaittransaction.commit();
}catch(err){
console.error('ERROR:',err);
}finally{
// Close the database when finished.
database.close();
}
});

PHP

use Google\Cloud\Spanner\SpannerClient;
use Google\Cloud\Spanner\Transaction;
/**
 * Writes then reads data inside a Transaction with a DML statement.
 *
 * The database and table must already exist and can be created using
 * `create_database`.
 * Example:
 * ```
 * insert_data($instanceId, $databaseId);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function write_read_with_dml(string $instanceId, string $databaseId): void
{
 $spanner = new SpannerClient();
 $instance = $spanner->instance($instanceId);
 $database = $instance->database($databaseId);
 $database->runTransaction(function (Transaction $t) {
 $rowCount = $t->executeUpdate(
 'INSERT Singers (SingerId, FirstName, LastName) '
 . " VALUES (11, 'Timothy', 'Campbell')");
 printf('Inserted %d row(s).' . PHP_EOL, $rowCount);
 $results = $t->execute('SELECT FirstName, LastName FROM Singers WHERE SingerId = 11');
 foreach ($results as $row) {
 printf('%s %s' . PHP_EOL, $row['FirstName'], $row['LastName']);
 }
 $t->commit();
 });
}

Python

# instance_id = "your-spanner-instance"
# database_id = "your-spanner-db-id"
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)
defwrite_then_read(transaction):
 # Insert record.
 row_ct = transaction.execute_update(
 "INSERT INTO Singers (SingerId, FirstName, LastName) "
 " VALUES (11, 'Timothy', 'Campbell')"
 )
 print("{} record(s) inserted.".format(row_ct))
 # Read newly inserted record.
 results = transaction.execute_sql(
 "SELECT FirstName, LastName FROM Singers WHERE SingerId = 11"
 )
 for result in results:
 print("FirstName: {}, LastName: {}".format(*result))
database.run_in_transaction(write_then_read)

Ruby

# project_id = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"
require"google/cloud/spanner"
spanner=Google::Cloud::Spanner.newproject:project_id
client=spanner.clientinstance_id,database_id
row_count=0
client.transactiondo|transaction|
row_count=transaction.execute_update(
"INSERT INTO Singers (SingerId, FirstName, LastName) VALUES (11, 'Timothy', 'Campbell')"
)
puts"#{row_count} record updated."
transaction.execute("SELECT FirstName, LastName FROM Singers WHERE SingerId = 11").rows.eachdo|row|
puts"#{row[:FirstName]}#{row[:LastName]}"
end
end

Get the query plan

You can retrieve a query plan using the Google Cloud console, the client libraries, and the gcloud command-line tool.

Use Partitioned DML

Partitioned DML is designed for bulk updates and deletes, particularly periodic cleanup and backfilling.

Execute statements with the Google Cloud CLI

To execute a Partitioned DML statement, use the gcloud spanner databases execute-sql command with the --enable-partitioned-dml option. The following example updates rows in the Albums table.

gcloudspannerdatabasesexecute-sqlexample-db\
--instance=test-instance--enable-partitioned-dml\
--sql='UPDATE Albums SET MarketingBudget = 0 WHERE MarketingBudget IS NULL'

Modify data using the client library

The following code example updates the MarketingBudget column of the Albums table.

C++

You use the ExecutePartitionedDml() function to execute a Partitioned DML statement.

voidDmlPartitionedUpdate(google::cloud::spanner::Clientclient){
namespacespanner=::google::cloud::spanner;
autoresult=client.ExecutePartitionedDml(
spanner::SqlStatement("UPDATE Albums SET MarketingBudget = 100000"
" WHERE SingerId > 1"));
if(!result)throwstd::move(result).status();
std::cout << "Updated at least " << result->row_count_lower_bound
 << " row(s) [spanner_dml_partitioned_update]\n";
}

C#

You use the ExecutePartitionedUpdateAsync() method to execute a Partitioned DML statement.


usingGoogle.Cloud.Spanner.Data ;
usingSystem;
usingSystem.Threading.Tasks;
publicclassUpdateUsingPartitionedDmlCoreAsyncSample
{
publicasyncTask<long>UpdateUsingPartitionedDmlCoreAsync(stringprojectId,stringinstanceId,stringdatabaseId)
{
stringconnectionString=$"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}";
usingvarconnection=newSpannerConnection (connectionString);
awaitconnection.OpenAsync ();
usingvarcmd=connection.CreateDmlCommand ("UPDATE Albums SET MarketingBudget = 100000 WHERE SingerId > 1");
longrowCount=awaitcmd.ExecutePartitionedUpdateAsync ();
Console.WriteLine($"{rowCount} row(s) updated...");
returnrowCount;
}
}

Go

You use the PartitionedUpdate() method to execute a Partitioned DML statement.


import(
"context"
"fmt"
"io"
"cloud.google.com/go/spanner"
)
funcupdateUsingPartitionedDML(wio.Writer,dbstring)error{
ctx:=context.Background()
client,err:=spanner.NewClient(ctx,db)
iferr!=nil{
returnerr
}
deferclient.Close()
stmt:=spanner.Statement {SQL:"UPDATE Albums SET MarketingBudget = 100000 WHERE SingerId > 1"}
rowCount,err:=client.PartitionedUpdate(ctx,stmt)
iferr!=nil{
returnerr
}
fmt.Fprintf(w,"%d record(s) updated.\n",rowCount)
returnnil
}

Java

You use the executePartitionedUpdate() method to execute a Partitioned DML statement.

staticvoidupdateUsingPartitionedDml(DatabaseClientdbClient){
Stringsql="UPDATE Albums SET MarketingBudget = 100000 WHERE SingerId > 1";
longrowCount=dbClient.executePartitionedUpdate(Statement.of(sql));
System.out.printf("%d records updated.\n",rowCount);
}

Node.js

You use the runPartitionedUpdate() method to execute a Partitioned DML statement.

// Imports the Google Cloud client library
const{Spanner}=require('@google-cloud/spanner');
/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';
// Creates a client
constspanner=newSpanner ({
projectId:projectId,
});
// Gets a reference to a Cloud Spanner instance and database
constinstance=spanner.instance(instanceId);
constdatabase=instance.database(databaseId);
try{
const[rowCount]=awaitdatabase.runPartitionedUpdate ({
sql:'UPDATE Albums SET MarketingBudget = 100000 WHERE SingerId > 1',
});
console.log(`Successfully updated ${rowCount} records.`);
}catch(err){
console.error('ERROR:',err);
}finally{
// Close the database when finished.
database.close();
}

PHP

You use the executePartitionedUpdate() method to execute a Partitioned DML statement.

use Google\Cloud\Spanner\SpannerClient;
/**
 * Updates sample data in the database by partition with a DML statement.
 *
 * This updates the `MarketingBudget` column which must be created before
 * running this sample. You can add the column by running the `add_column`
 * sample or by running this DDL statement against your database:
 *
 * ALTER TABLE Albums ADD COLUMN MarketingBudget INT64
 *
 * Example:
 * ```
 * update_data($instanceId, $databaseId);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function update_data_with_partitioned_dml(string $instanceId, string $databaseId): void
{
 $spanner = new SpannerClient();
 $instance = $spanner->instance($instanceId);
 $database = $instance->database($databaseId);
 $rowCount = $database->executePartitionedUpdate(
 'UPDATE Albums SET MarketingBudget = 100000 WHERE SingerId > 1'
 );
 printf('Updated %d row(s).' . PHP_EOL, $rowCount);
}

Python

You use the execute_partitioned_dml() method to execute a Partitioned DML statement.

# instance_id = "your-spanner-instance"
# database_id = "your-spanner-db-id"
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)
row_ct = database.execute_partitioned_dml(
 "UPDATE Albums SET MarketingBudget = 100000 WHERE SingerId > 1"
)
print("{} records updated.".format(row_ct))

Ruby

You use the execute_partitioned_update() method to execute a Partitioned DML statement.

# project_id = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"
require"google/cloud/spanner"
spanner=Google::Cloud::Spanner.newproject:project_id
client=spanner.clientinstance_id,database_id
row_count=client.execute_partition_update(
"UPDATE Albums SET MarketingBudget = 100000 WHERE SingerId > 1"
)
puts"#{row_count} records updated."

The following code example deletes rows from the Singers table, based on the SingerId column.

C++

voidDmlPartitionedDelete(google::cloud::spanner::Clientclient){
namespacespanner=::google::cloud::spanner;
autoresult=client.ExecutePartitionedDml(
spanner::SqlStatement("DELETE FROM Singers WHERE SingerId > 10"));
if(!result)throwstd::move(result).status();
std::cout << "Deleted at least " << result->row_count_lower_bound
 << " row(s) [spanner_dml_partitioned_delete]\n";
}

C#


usingGoogle.Cloud.Spanner.Data ;
usingSystem;
usingSystem.Threading.Tasks;
publicclassDeleteUsingPartitionedDmlCoreAsyncSample
{
publicasyncTask<long>DeleteUsingPartitionedDmlCoreAsync(stringprojectId,stringinstanceId,stringdatabaseId)
{
stringconnectionString=$"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}";
usingvarconnection=newSpannerConnection (connectionString);
awaitconnection.OpenAsync ();
usingvarcmd=connection.CreateDmlCommand ("DELETE FROM Singers WHERE SingerId > 10");
longrowCount=awaitcmd.ExecutePartitionedUpdateAsync ();
Console.WriteLine($"{rowCount} row(s) deleted...");
returnrowCount;
}
}

Go


import(
"context"
"fmt"
"io"
"cloud.google.com/go/spanner"
)
funcdeleteUsingPartitionedDML(wio.Writer,dbstring)error{
ctx:=context.Background()
client,err:=spanner.NewClient(ctx,db)
iferr!=nil{
returnerr
}
deferclient.Close()
stmt:=spanner.Statement {SQL:"DELETE FROM Singers WHERE SingerId > 10"}
rowCount,err:=client.PartitionedUpdate(ctx,stmt)
iferr!=nil{
returnerr
}
fmt.Fprintf(w,"%d record(s) deleted.",rowCount)
returnnil
}

Java

staticvoiddeleteUsingPartitionedDml(DatabaseClientdbClient){
Stringsql="DELETE FROM Singers WHERE SingerId > 10";
longrowCount=dbClient.executePartitionedUpdate(Statement.of(sql));
System.out.printf("%d records deleted.\n",rowCount);
}

Node.js

// Imports the Google Cloud client library
const{Spanner}=require('@google-cloud/spanner');
/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';
// Creates a client
constspanner=newSpanner ({
projectId:projectId,
});
// Gets a reference to a Cloud Spanner instance and database
constinstance=spanner.instance(instanceId);
constdatabase=instance.database(databaseId);
try{
const[rowCount]=awaitdatabase.runPartitionedUpdate ({
sql:'DELETE FROM Singers WHERE SingerId > 10',
});
console.log(`Successfully deleted ${rowCount} records.`);
}catch(err){
console.error('ERROR:',err);
}finally{
// Close the database when finished.
database.close();
}

PHP

use Google\Cloud\Spanner\SpannerClient;
/**
 * Delete sample data in the database by partition with a DML statement.
 *
 * This updates the `MarketingBudget` column which must be created before
 * running this sample. You can add the column by running the `add_column`
 * sample or by running this DDL statement against your database:
 *
 * ALTER TABLE Albums ADD COLUMN MarketingBudget INT64
 *
 * Example:
 * ```
 * update_data($instanceId, $databaseId);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function delete_data_with_partitioned_dml(string $instanceId, string $databaseId): void
{
 $spanner = new SpannerClient();
 $instance = $spanner->instance($instanceId);
 $database = $instance->database($databaseId);
 $rowCount = $database->executePartitionedUpdate(
 'DELETE FROM Singers WHERE SingerId > 10'
 );
 printf('Deleted %d row(s).' . PHP_EOL, $rowCount);
}

Python

# instance_id = "your-spanner-instance"
# database_id = "your-spanner-db-id"
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)
row_ct = database.execute_partitioned_dml("DELETE FROM Singers WHERE SingerId > 10")
print("{} record(s) deleted.".format(row_ct))

Ruby

# project_id = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"
require"google/cloud/spanner"
spanner=Google::Cloud::Spanner.newproject:project_id
client=spanner.clientinstance_id,database_id
row_count=client.execute_partition_update(
"DELETE FROM Singers WHERE SingerId > 10"
)
puts"#{row_count} records deleted."

Use batch DML

If you need to avoid the extra latency incurred from multiple serial requests, use batch DML to send multiple INSERT, UPDATE, or DELETE statements in a single transaction:

C++

Use the ExecuteBatchDml() function to execute a list of DML statements.

voidDmlBatchUpdate(google::cloud::spanner::Clientclient){
namespacespanner=::google::cloud::spanner;
autocommit_result=
client.Commit([&client](spanner::Transactionconst&txn)
->google::cloud::StatusOr<spanner::Mutations>{
std::vector<spanner::SqlStatement>statements={
spanner::SqlStatement("INSERT INTO Albums"
" (SingerId, AlbumId, AlbumTitle,"
" MarketingBudget)"
" VALUES (1, 3, 'Test Album Title', 10000)"),
spanner::SqlStatement("UPDATE Albums"
" SET MarketingBudget = MarketingBudget * 2"
" WHERE SingerId = 1 and AlbumId = 3")};
autoresult=client.ExecuteBatchDml(txn,statements);
if(!result)returnstd::move(result).status();
// Note: This mutator might be re-run, or its effects discarded, so
// changing non-transactional state (e.g., by producing output) is,
// in general, not something to be imitated.
for(std::size_ti=0;i < result->stats.size();++i){
std::cout << result->stats[i].row_count << " rows affected"
 << " for the statement " << (i+1) << ".\n";
}
// Batch operations may have partial failures, in which case
// ExecuteBatchDml returns with success, but the application should
// verify that all statements completed successfully
if(!result->status.ok())returnresult->status;
returnspanner::Mutations{};
});
if(!commit_result)throwstd::move(commit_result).status();
std::cout << "Update was successful [spanner_dml_batch_update]\n";
}

C#

Use the connection.CreateBatchDmlCommand() method to create your batch command, use the Add method to add DML statements, and execute the statements with the ExecuteNonQueryAsync() method.


usingGoogle.Cloud.Spanner.Data ;
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Threading.Tasks;
publicclassUpdateUsingBatchDmlCoreAsyncSample
{
publicasyncTask<int>UpdateUsingBatchDmlCoreAsync(stringprojectId,stringinstanceId,stringdatabaseId)
{
stringconnectionString=$"Data Source=projects/{projectId}/instances/{instanceId}/databases/{databaseId}";
usingvarconnection=newSpannerConnection (connectionString);
awaitconnection.OpenAsync ();
SpannerBatchCommand cmd=connection.CreateBatchDmlCommand();
cmd.Add ("INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget) VALUES (1, 3, 'Test Album Title', 10000)");
cmd.Add ("UPDATE Albums SET MarketingBudget = MarketingBudget * 2 WHERE SingerId = 1 and AlbumId = 3");
IEnumerable<long>affectedRows=awaitcmd.ExecuteNonQueryAsync ();
Console.WriteLine($"Executed {affectedRows.Count()} "+"SQL statements using Batch DML.");
returnaffectedRows.Count();
}
}

Go

Use the BatchUpdate() method to execute an array of DML Statement objects.


import(
"context"
"fmt"
"io"
"cloud.google.com/go/spanner"
)
funcupdateUsingBatchDML(wio.Writer,dbstring)error{
ctx:=context.Background()
client,err:=spanner.NewClient(ctx,db)
iferr!=nil{
returnerr
}
deferclient.Close()
_,err=client.ReadWriteTransaction(ctx,func(ctxcontext.Context,txn*spanner.ReadWriteTransaction)error{
stmts:=[]spanner.Statement {
{SQL:`INSERT INTO Albums
				(SingerId, AlbumId, AlbumTitle, MarketingBudget)
				VALUES (1, 3, 'Test Album Title', 10000)`},
{SQL:`UPDATE Albums
				SET MarketingBudget = MarketingBudget * 2
				WHERE SingerId = 1 and AlbumId = 3`},
}
rowCounts,err:=txn.BatchUpdate (ctx,stmts)
iferr!=nil{
returnerr
}
fmt.Fprintf(w,"Executed %d SQL statements using Batch DML.\n",len(rowCounts))
returnnil
})
returnerr
}

Java

Use the transaction.batchUpdate() method to execute an ArrayList of multiple DML Statement objects.

staticvoidupdateUsingBatchDml(DatabaseClientdbClient){
dbClient
.readWriteTransaction()
.run(transaction->{
List<Statement>stmts=newArrayList<Statement>();
Stringsql=
"INSERT INTO Albums "
+"(SingerId, AlbumId, AlbumTitle, MarketingBudget) "
+"VALUES (1, 3, 'Test Album Title', 10000) ";
stmts.add(Statement.of(sql));
sql=
"UPDATE Albums "
+"SET MarketingBudget = MarketingBudget * 2 "
+"WHERE SingerId = 1 and AlbumId = 3";
stmts.add(Statement.of(sql));
long[]rowCounts;
try{
rowCounts=transaction.batchUpdate(stmts);
}catch(SpannerBatchUpdateExceptione){
rowCounts=e.getUpdateCounts();
}
for(inti=0;i < rowCounts.length;i++){
System.out.printf("%d record updated by stmt %d.\n",rowCounts[i],i);
}
returnnull;
});
}

Node.js

Use transaction.batchUpdate() to execute a list of DML statements.

// Imports the Google Cloud client library
const{Spanner}=require('@google-cloud/spanner');
/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const projectId = 'my-project-id';
// const instanceId = 'my-instance';
// const databaseId = 'my-database';
// Creates a client
constspanner=newSpanner ({
projectId:projectId,
});
// Gets a reference to a Cloud Spanner instance and database
constinstance=spanner.instance(instanceId);
constdatabase=instance.database(databaseId);
constinsert={
sql:`INSERT INTO Albums (SingerId, AlbumId, AlbumTitle, MarketingBudget)
 VALUES (1, 3, "Test Album Title", 10000)`,
};
constupdate={
sql:`UPDATE Albums SET MarketingBudget = MarketingBudget * 2
 WHERE SingerId = 1 and AlbumId = 3`,
};
constdmlStatements=[insert,update];
try{
awaitdatabase.runTransactionAsync (asynctransaction=>{
const[rowCounts]=awaittransaction.batchUpdate(dmlStatements);
awaittransaction.commit();
console.log(
`Successfully executed ${rowCounts.length} SQL statements using Batch DML.`,
);
});
}catch(err){
console.error('ERROR:',err);
throwerr;
}finally{
// Close the database when finished.
database.close();
}

PHP

Use executeUpdateBatch() to create a list of DML statements, then use commit() to execute the statements.

use Google\Cloud\Spanner\SpannerClient;
use Google\Cloud\Spanner\Transaction;
/**
 * Updates sample data in the database with Batch DML.
 *
 * This requires the `MarketingBudget` column which must be created before
 * running this sample. You can add the column by running the `add_column`
 * sample or by running this DDL statement against your database:
 *
 * ALTER TABLE Albums ADD COLUMN MarketingBudget INT64
 *
 * Example:
 * ```
 * update_data_with_batch_dml($instanceId, $databaseId);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function update_data_with_batch_dml(string $instanceId, string $databaseId): void
{
 $spanner = new SpannerClient();
 $instance = $spanner->instance($instanceId);
 $database = $instance->database($databaseId);
 $batchDmlResult = $database->runTransaction(function (Transaction $t) {
 $result = $t->executeUpdateBatch([
 [
 'sql' => 'INSERT INTO Albums '
 . '(SingerId, AlbumId, AlbumTitle, MarketingBudget) '
 . "VALUES (1, 3, 'Test Album Title', 10000)"
 ],
 [
 'sql' => 'UPDATE Albums '
 . 'SET MarketingBudget = MarketingBudget * 2 '
 . 'WHERE SingerId = 1 and AlbumId = 3'
 ],
 ]);
 $t->commit();
 $rowCounts = count($result->rowCounts());
 printf('Executed %s SQL statements using Batch DML.' . PHP_EOL,
 $rowCounts);
 });
}

Python

Use transaction.batch_update() to execute multiple DML statement strings.

fromgoogle.rpc.code_pb2import OK
# instance_id = "your-spanner-instance"
# database_id = "your-spanner-db-id"
spanner_client = spanner.Client()
instance = spanner_client.instance(instance_id)
database = instance.database(database_id)
insert_statement = (
 "INSERT INTO Albums "
 "(SingerId, AlbumId, AlbumTitle, MarketingBudget) "
 "VALUES (1, 3, 'Test Album Title', 10000)"
)
update_statement = (
 "UPDATE Albums "
 "SET MarketingBudget = MarketingBudget * 2 "
 "WHERE SingerId = 1 and AlbumId = 3"
)
defupdate_albums(transaction):
 status, row_cts = transaction.batch_update([insert_statement, update_statement])
 if status.code != OK:
 # Do handling here.
 # Note: the exception will still be raised when
 # `commit` is called by `run_in_transaction`.
 return
 print("Executed {} SQL statements using Batch DML.".format(len(row_cts)))
database.run_in_transaction(update_albums)

Ruby

Use transaction.batch_update to execute multiple DML statement strings.

# project_id = "Your Google Cloud project ID"
# instance_id = "Your Spanner instance ID"
# database_id = "Your Spanner database ID"
require"google/cloud/spanner"
spanner=Google::Cloud::Spanner.newproject:project_id
client=spanner.clientinstance_id,database_id
row_counts=nil
client.transactiondo|transaction|
row_counts=transaction.batch_updatedo|b|
b.batch_update(
"INSERT INTO Albums "\
"(SingerId, AlbumId, AlbumTitle, MarketingBudget) "\
"VALUES (1, 3, 'Test Album Title', 10000)"
)
b.batch_update(
"UPDATE Albums "\
"SET MarketingBudget = MarketingBudget * 2 "\
"WHERE SingerId = 1 and AlbumId = 3"
)
end
end
statement_count=row_counts.count
puts"Executed #{statement_count} SQL statements using Batch DML."

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Last updated 2025年11月24日 UTC.