Daten mithilfe von Mutationen einfügen, aktualisieren und löschen

Auf dieser Seite wird beschrieben, wie Sie Daten mithilfe von Mutationen einfügen, aktualisieren und löschen. Eine Mutation stellt eine Folge von Einfügungs-, Aktualisierungs- und Löschvorgängen dar, die Cloud Spanner in kleinstmöglichen Schritten auf verschiedene Zeilen und Tabellen in einer Cloud Spanner-Datenbank anwenden kann.

Sie können den Commit von Mutationen zwar mit gRPC oder REST durchführen, meist greift man aber über die Clientbibliotheken auf die APIs zu.

Auf dieser Seite werden die grundlegenden Vorgänge Einfügen, Aktualisieren und Löschen vorgestellt. Weitere Beispiele finden Sie in den Startleitfäden.

Neue Zeilen in eine Tabelle einfügen

C++

Daten werden mit der Funktion InsertMutationBuilder() geschrieben. Mit Client::Commit() fügen Sie einer Tabelle neue Zeilen hinzu. Alle Eingaben in einen einzelnen Batch werden in kleinstmöglichen Schritten angewendet.

Dieser Code zeigt, wie die Daten geschrieben werden:

void InsertData(google::cloud::spanner::Client client) {
  namespace spanner = ::google::cloud::spanner;
  auto insert_singers = spanner::InsertMutationBuilder(
                            "Singers", {"SingerId", "FirstName", "LastName"})
                            .EmplaceRow(1, "Marc", "Richards")
                            .EmplaceRow(2, "Catalina", "Smith")
                            .EmplaceRow(3, "Alice", "Trentor")
                            .EmplaceRow(4, "Lea", "Martin")
                            .EmplaceRow(5, "David", "Lomond")
                            .Build();

  auto insert_albums = spanner::InsertMutationBuilder(
                           "Albums", {"SingerId", "AlbumId", "AlbumTitle"})
                           .EmplaceRow(1, 1, "Total Junk")
                           .EmplaceRow(1, 2, "Go, Go, Go")
                           .EmplaceRow(2, 1, "Green")
                           .EmplaceRow(2, 2, "Forever Hold Your Peace")
                           .EmplaceRow(2, 3, "Terrified")
                           .Build();

  auto commit_result =
      client.Commit(spanner::Mutations{insert_singers, insert_albums});
  if (!commit_result) {
    throw std::runtime_error(commit_result.status().message());
  }
  std::cout << "Insert was successful [spanner_insert_data]\n";
}

C#

Sie können Daten mithilfe der Methode connection.CreateInsertCommand() einfügen. Dadurch wird ein neuer SpannerCommand erstellt, um Zeilen in eine Tabelle einzufügen. Die Methode SpannerCommand.ExecuteNonQueryAsync() fügt der Tabelle neue Zeilen hinzu.

Dieser Code zeigt, wie Daten eingefügt werden:

public class Singer
{
    public int SingerId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

public class Album
{
    public int SingerId { get; set; }
    public int AlbumId { get; set; }
    public string AlbumTitle { get; set; }
}
public static async Task InsertSampleDataAsync(
    string projectId, string instanceId, string databaseId)
{
    const int firstSingerId = 1;
    const int secondSingerId = 2;
    string connectionString =
    $"Data Source=projects/{projectId}/instances/{instanceId}"
    + $"/databases/{databaseId}";
    List<Singer> singers = new List<Singer>
    {
        new Singer { SingerId = firstSingerId, FirstName = "Marc",
            LastName = "Richards" },
        new Singer { SingerId = secondSingerId, FirstName = "Catalina",
            LastName = "Smith" },
        new Singer { SingerId = 3, FirstName = "Alice",
            LastName = "Trentor" },
        new Singer { SingerId = 4, FirstName = "Lea",
            LastName = "Martin" },
        new Singer { SingerId = 5, FirstName = "David",
            LastName = "Lomond" },
    };
    List<Album> albums = new List<Album>
    {
        new Album { SingerId = firstSingerId, AlbumId = 1,
            AlbumTitle = "Total Junk" },
        new Album { SingerId = firstSingerId, AlbumId = 2,
            AlbumTitle = "Go, Go, Go" },
        new Album { SingerId = secondSingerId, AlbumId = 1,
            AlbumTitle = "Green" },
        new Album { SingerId = secondSingerId, AlbumId = 2,
            AlbumTitle = "Forever Hold your Peace" },
        new Album { SingerId = secondSingerId, AlbumId = 3,
            AlbumTitle = "Terrified" },
    };
    // Create connection to Cloud Spanner.
    using (var connection = new SpannerConnection(connectionString))
    {
        await connection.OpenAsync();

        await connection.RunWithRetriableTransactionAsync(async transaction =>
        {
            // Insert rows into the Singers table.
            var cmd = connection.CreateInsertCommand("Singers",
                new SpannerParameterCollection
                {
                    { "SingerId", SpannerDbType.Int64 },
                    { "FirstName", SpannerDbType.String },
                    { "LastName", SpannerDbType.String }
                });
            cmd.Transaction = transaction;
            await Task.WhenAll(singers.Select(singer =>
            {
                cmd.Parameters["SingerId"].Value = singer.SingerId;
                cmd.Parameters["FirstName"].Value = singer.FirstName;
                cmd.Parameters["LastName"].Value = singer.LastName;
                return cmd.ExecuteNonQueryAsync();
            }));

            // Insert rows into the Albums table.
            cmd = connection.CreateInsertCommand("Albums",
                new SpannerParameterCollection
                {
                    { "SingerId", SpannerDbType.Int64 },
                    { "AlbumId", SpannerDbType.Int64 },
                    { "AlbumTitle", SpannerDbType.String }
                });
            cmd.Transaction = transaction;
            await Task.WhenAll(albums.Select(album =>
            {
                cmd.Parameters["SingerId"].Value = album.SingerId;
                cmd.Parameters["AlbumId"].Value = album.AlbumId;
                cmd.Parameters["AlbumTitle"].Value = album.AlbumTitle;
                return cmd.ExecuteNonQueryAsync();
            }));
        });
        Console.WriteLine("Inserted data.");
    }
}

Go

Sie schreiben Daten mit einer Mutation. Eine Mutation ist ein Container für Mutationsvorgänge. Eine Mutation stellt eine Folge von Einfügungs-, Aktualisierungs- und Löschvorgängen dar, die in kleinstmöglichen Schritten auf verschiedene Zeilen und Tabellen in einer Cloud Spanner-Datenbank angewendet werden können.

Verwenden Sie Mutation.InsertOrUpdate(), um die Mutation INSERT_OR_UPDATE zu erstellen. Damit wird eine neue Zeile hinzugefügt oder Spaltenwerte aktualisiert, falls die Zeile bereits vorhanden ist. Alternativ können Sie die Methode Mutation.Insert() zum Erstellen der Mutation INSERT verwenden, mit der eine neue Zeile hinzugefügt wird.

Durch Client.Apply() werden Mutationen in kleinstmöglichen Schritten auf eine Datenbank angewendet.

Dieser Code zeigt, wie die Daten geschrieben werden:


import (
	"context"
	"io"

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

func write(w io.Writer, db string) error {
	ctx := context.Background()
	client, err := spanner.NewClient(ctx, db)
	if err != nil {
		return err
	}
	defer client.Close()

	singerColumns := []string{"SingerId", "FirstName", "LastName"}
	albumColumns := []string{"SingerId", "AlbumId", "AlbumTitle"}
	m := []*spanner.Mutation{
		spanner.InsertOrUpdate("Singers", singerColumns, []interface{}{1, "Marc", "Richards"}),
		spanner.InsertOrUpdate("Singers", singerColumns, []interface{}{2, "Catalina", "Smith"}),
		spanner.InsertOrUpdate("Singers", singerColumns, []interface{}{3, "Alice", "Trentor"}),
		spanner.InsertOrUpdate("Singers", singerColumns, []interface{}{4, "Lea", "Martin"}),
		spanner.InsertOrUpdate("Singers", singerColumns, []interface{}{5, "David", "Lomond"}),
		spanner.InsertOrUpdate("Albums", albumColumns, []interface{}{1, 1, "Total Junk"}),
		spanner.InsertOrUpdate("Albums", albumColumns, []interface{}{1, 2, "Go, Go, Go"}),
		spanner.InsertOrUpdate("Albums", albumColumns, []interface{}{2, 1, "Green"}),
		spanner.InsertOrUpdate("Albums", albumColumns, []interface{}{2, 2, "Forever Hold Your Peace"}),
		spanner.InsertOrUpdate("Albums", albumColumns, []interface{}{2, 3, "Terrified"}),
	}
	_, err = client.Apply(ctx, m)
	return err
}

Java

Daten werden mit einem Mutation-Objekt geschrieben. Ein Mutation-Objekt ist ein Container für Mutationsvorgänge. Eine Mutation stellt eine Folge von Einfügungs-, Aktualisierungs- und Löschvorgängen dar, die Cloud Spanner in kleinstmöglichen Schritten auf verschiedene Zeilen und Tabellen in einer Cloud Spanner-Datenbank anwenden kann.

Die Methode newInsertBuilder() in der Klasse Mutation erstellt eine INSERT-Mutation, die eine neue Zeile in eine Tabelle einfügt. Wenn die Zeile bereits vorhanden ist, kann der Schreibvorgang nicht durchgeführt werden. In diesem Fall können Sie alternativ mit der Methode newInsertOrUpdateBuilder die Mutation INSERT_OR_UPDATE erstellen, um Spaltenwerte zu aktualisieren, wenn die Zeile bereits vorhanden ist.

Die write()-Methode in der Klasse DatabaseClient schreibt die Mutationen. Alle Mutationen in einem einzelnen Batch werden in kleinstmöglichen Schritten angewendet.

Dieser Code zeigt, wie die Daten geschrieben werden:

static final List<Singer> SINGERS =
    Arrays.asList(
        new Singer(1, "Marc", "Richards"),
        new Singer(2, "Catalina", "Smith"),
        new Singer(3, "Alice", "Trentor"),
        new Singer(4, "Lea", "Martin"),
        new Singer(5, "David", "Lomond"));

static final List<Album> ALBUMS =
    Arrays.asList(
        new Album(1, 1, "Total Junk"),
        new Album(1, 2, "Go, Go, Go"),
        new Album(2, 1, "Green"),
        new Album(2, 2, "Forever Hold Your Peace"),
        new Album(2, 3, "Terrified"));
static void writeExampleData(DatabaseClient dbClient) {
  List<Mutation> mutations = new ArrayList<>();
  for (Singer singer : SINGERS) {
    mutations.add(
        Mutation.newInsertBuilder("Singers")
            .set("SingerId")
            .to(singer.singerId)
            .set("FirstName")
            .to(singer.firstName)
            .set("LastName")
            .to(singer.lastName)
            .build());
  }
  for (Album album : ALBUMS) {
    mutations.add(
        Mutation.newInsertBuilder("Albums")
            .set("SingerId")
            .to(album.singerId)
            .set("AlbumId")
            .to(album.albumId)
            .set("AlbumTitle")
            .to(album.albumTitle)
            .build());
  }
  dbClient.write(mutations);
}

Node.js

Daten werden mit einem Table-Objekt geschrieben. Die Methode Table.insert() fügt der Tabelle neue Zeilen hinzu. Alle Eingaben in einen einzelnen Batch werden in kleinstmöglichen Schritten angewendet.

Dieser Code zeigt, wie die Daten geschrieben werden:

// 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
const spanner = new Spanner({
  projectId: projectId,
});

// Gets a reference to a Cloud Spanner instance and database
const instance = spanner.instance(instanceId);
const database = instance.database(databaseId);

// Instantiate Spanner table objects
const singersTable = database.table('Singers');
const albumsTable = database.table('Albums');

// Inserts rows into the Singers table
// Note: Cloud Spanner interprets Node.js numbers as FLOAT64s, so
// they must be converted to strings before being inserted as INT64s
try {
  await singersTable.insert([
    {SingerId: '1', FirstName: 'Marc', LastName: 'Richards'},
    {SingerId: '2', FirstName: 'Catalina', LastName: 'Smith'},
    {SingerId: '3', FirstName: 'Alice', LastName: 'Trentor'},
    {SingerId: '4', FirstName: 'Lea', LastName: 'Martin'},
    {SingerId: '5', FirstName: 'David', LastName: 'Lomond'},
  ]);

  await albumsTable.insert([
    {SingerId: '1', AlbumId: '1', AlbumTitle: 'Total Junk'},
    {SingerId: '1', AlbumId: '2', AlbumTitle: 'Go, Go, Go'},
    {SingerId: '2', AlbumId: '1', AlbumTitle: 'Green'},
    {SingerId: '2', AlbumId: '2', AlbumTitle: 'Forever Hold your Peace'},
    {SingerId: '2', AlbumId: '3', AlbumTitle: 'Terrified'},
  ]);

  console.log('Inserted data.');
} catch (err) {
  console.error('ERROR:', err);
} finally {
  await database.close();
}

PHP

Daten werden mithilfe der Methode Database::insertBatch geschrieben. Mit insertBatch fügen Sie einer Tabelle neue Zeilen hinzu. Alle Eingaben in einen einzelnen Batch werden in kleinstmöglichen Schritten angewendet.

Dieser Code zeigt, wie die Daten geschrieben werden:

use Google\Cloud\Spanner\SpannerClient;

/**
 * Inserts sample data into the given database.
 *
 * 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($instanceId, $databaseId)
{
    $spanner = new SpannerClient();
    $instance = $spanner->instance($instanceId);
    $database = $instance->database($databaseId);

    $operation = $database->transaction(['singleUse' => true])
        ->insertBatch('Singers', [
            ['SingerId' => 1, 'FirstName' => 'Marc', 'LastName' => 'Richards'],
            ['SingerId' => 2, 'FirstName' => 'Catalina', 'LastName' => 'Smith'],
            ['SingerId' => 3, 'FirstName' => 'Alice', 'LastName' => 'Trentor'],
            ['SingerId' => 4, 'FirstName' => 'Lea', 'LastName' => 'Martin'],
            ['SingerId' => 5, 'FirstName' => 'David', 'LastName' => 'Lomond'],
        ])
        ->insertBatch('Albums', [
            ['SingerId' => 1, 'AlbumId' => 1, 'AlbumTitle' => 'Total Junk'],
            ['SingerId' => 1, 'AlbumId' => 2, 'AlbumTitle' => 'Go, Go, Go'],
            ['SingerId' => 2, 'AlbumId' => 1, 'AlbumTitle' => 'Green'],
            ['SingerId' => 2, 'AlbumId' => 2, 'AlbumTitle' => 'Forever Hold Your Peace'],
            ['SingerId' => 2, 'AlbumId' => 3, 'AlbumTitle' => 'Terrified']
        ])
        ->commit();

    print('Inserted data.' . PHP_EOL);
}

Python

Daten werden mit einem Batch-Objekt geschrieben. Ein Batch-Objekt ist ein Container für Mutationsvorgänge. Eine Mutation stellt eine Folge von Einfügungs-, Aktualisierungs- und Löschvorgängen dar, die in kleinstmöglichen Schritten auf verschiedene Zeilen und Tabellen in einer Cloud Spanner-Datenbank angewendet werden können.

Mit der Methode insert() in der Klasse Batch werden dem Batch eine oder mehrere Insert-Mutationen hinzugefügt. Alle Mutationen in einem einzelnen Batch werden in kleinstmöglichen Schritten angewendet.

Dieser Code zeigt, wie die Daten geschrieben werden:

def insert_data(instance_id, database_id):
    """Inserts sample data into the given database.

    The database and table must already exist and can be created using
    `create_database`.
    """
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)

    with database.batch() as batch:
        batch.insert(
            table="Singers",
            columns=("SingerId", "FirstName", "LastName"),
            values=[
                (1, u"Marc", u"Richards"),
                (2, u"Catalina", u"Smith"),
                (3, u"Alice", u"Trentor"),
                (4, u"Lea", u"Martin"),
                (5, u"David", u"Lomond"),
            ],
        )

        batch.insert(
            table="Albums",
            columns=("SingerId", "AlbumId", "AlbumTitle"),
            values=[
                (1, 1, u"Total Junk"),
                (1, 2, u"Go, Go, Go"),
                (2, 1, u"Green"),
                (2, 2, u"Forever Hold Your Peace"),
                (2, 3, u"Terrified"),
            ],
        )

    print("Inserted data.")

Ruby

Daten werden mit einem Client-Objekt geschrieben. Mit der Methode Client#commit werden Transaktionen für Schreibvorgänge erstellt, die für Spalten, Zeilen und Tabellen in einer Datenbank zu einem einzigen logischen Zeitpunkt als unteilbarer Vorgang ausgeführt werden. Danach werden sie mit Commits festgeschrieben.

Dieser Code zeigt, wie die Daten geschrieben werden:

# 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.new project: project_id
client  = spanner.client instance_id, database_id

client.commit do |c|
  c.insert "Singers", [
    { SingerId: 1, FirstName: "Marc",     LastName: "Richards" },
    { SingerId: 2, FirstName: "Catalina", LastName: "Smith"    },
    { SingerId: 3, FirstName: "Alice",    LastName: "Trentor"  },
    { SingerId: 4, FirstName: "Lea",      LastName: "Martin"   },
    { SingerId: 5, FirstName: "David",    LastName: "Lomond"   }
  ]
  c.insert "Albums", [
    { SingerId: 1, AlbumId: 1, AlbumTitle: "Total Junk"              },
    { SingerId: 1, AlbumId: 2, AlbumTitle: "Go, Go, Go"              },
    { SingerId: 2, AlbumId: 1, AlbumTitle: "Green"                   },
    { SingerId: 2, AlbumId: 2, AlbumTitle: "Forever Hold Your Peace" },
    { SingerId: 2, AlbumId: 3, AlbumTitle: "Terrified"               }
  ]
end

puts "Inserted data"

Zeilen in einer Tabelle aktualisieren

Angenommen, die Verkaufszahlen für Albums(1, 1) sind niedriger als erwartet. Sie möchten deshalb 200.000 $ aus dem Marketingbudget von Albums(2, 2) in Albums(1, 1) verschieben, wenn das Geld im Budget von Albums(2, 2) verfügbar ist.

Da Sie die Daten in den Tabellen lesen müssen, um zu bestimmen, ob neue Werte geschrieben werden sollen, sollten Sie zum Ausführen der Lese- und Schreibvorgänge eine Lese-Schreib-Transaktion verwenden.

C++

Verwenden Sie die Funktion Transaction(), um eine Transaktion für einen Client auszuführen.

Mit diesem Code können Sie die Transaktion ausführen:

void ReadWriteTransaction(google::cloud::spanner::Client client) {
  namespace spanner = ::google::cloud::spanner;
  using ::google::cloud::StatusOr;

  // A helper to read a single album MarketingBudget.
  auto get_current_budget =
      [](spanner::Client client, spanner::Transaction txn,
         std::int64_t singer_id,
         std::int64_t album_id) -> StatusOr<std::int64_t> {
    auto key = spanner::KeySet().AddKey(spanner::MakeKey(singer_id, album_id));
    auto rows = client.Read(std::move(txn), "Albums", std::move(key),
                            {"MarketingBudget"});
    using RowType = std::tuple<std::int64_t>;
    auto row = spanner::GetSingularRow(spanner::StreamOf<RowType>(rows));
    if (!row) return std::move(row).status();
    return std::get<0>(*std::move(row));
  };

  auto commit = client.Commit(
      [&client, &get_current_budget](
          spanner::Transaction const& txn) -> StatusOr<spanner::Mutations> {
        auto b1 = get_current_budget(client, txn, 1, 1);
        if (!b1) return std::move(b1).status();
        auto b2 = get_current_budget(client, txn, 2, 2);
        if (!b2) return std::move(b2).status();
        std::int64_t transfer_amount = 200000;

        return spanner::Mutations{
            spanner::UpdateMutationBuilder(
                "Albums", {"SingerId", "AlbumId", "MarketingBudget"})
                .EmplaceRow(1, 1, *b1 + transfer_amount)
                .EmplaceRow(2, 2, *b2 - transfer_amount)
                .Build()};
      });

  if (!commit) throw std::runtime_error(commit.status().message());
  std::cout << "Transfer was successful [spanner_read_write_transaction]\n";
}

C#

Für .NET Standard 2.0 (oder .NET 4.5) und höher können Sie zur Ausführung einer Transaktion den TransactionScope() des .NET-Frameworks verwenden. Für alle unterstützten .NET-Versionen können Sie eine Transaktion erstellen, indem Sie das Ergebnis von SpannerConnection.BeginTransactionAsync als das Attribut Transaction von SpannerCommand festlegen.

Nachfolgend die zwei Möglichkeiten, die Transaktion auszuführen:

.NET Standard 2.0

public static async Task ReadWriteWithTransactionAsync(
    string projectId,
    string instanceId,
    string databaseId)
{
    // This sample transfers 200,000 from the MarketingBudget
    // field of the second Album to the first Album. Make sure to run
    // the addColumn and writeDataToNewColumn samples first,
    // in that order.

    string connectionString =
    $"Data Source=projects/{projectId}/instances/{instanceId}"
    + $"/databases/{databaseId}";

    using (TransactionScope scope = new TransactionScope(
        TransactionScopeAsyncFlowOption.Enabled))
    {
        decimal transferAmount = 200000;
        decimal secondBudget = 0;
        decimal firstBudget = 0;

        // Create connection to Cloud Spanner.
        using (var connection =
            new SpannerConnection(connectionString))
        {
            // Create statement to select the second album's data.
            var cmdLookup = connection.CreateSelectCommand(
            "SELECT * FROM Albums WHERE SingerId = 2 AND AlbumId = 2");
            // Excecute the select query.
            using (var reader = await cmdLookup.ExecuteReaderAsync())
            {
                while (await reader.ReadAsync())
                {
                    // Read the second album's budget.
                    secondBudget =
                      reader.GetFieldValue<decimal>("MarketingBudget");
                    // Confirm second Album's budget is sufficient and
                    // if not raise an exception. Raising an exception
                    // will automatically roll back the transaction.
                    if (secondBudget < transferAmount)
                    {
                        throw new Exception("The second album's "
                            + $"budget {secondBudget} "
                            + "is less than the "
                            + "amount to transfer.");
                    }
                }
            }
            // Read the first album's budget.
            cmdLookup = connection.CreateSelectCommand(
            "SELECT * FROM Albums WHERE SingerId = 1 and AlbumId = 1");
            using (var reader = await cmdLookup.ExecuteReaderAsync())
            {
                while (await reader.ReadAsync())
                {
                    firstBudget =
                      reader.GetFieldValue<decimal>("MarketingBudget");
                }
            }

            // Specify update command parameters.
            var cmd = connection.CreateUpdateCommand("Albums",
                new SpannerParameterCollection {
                {"SingerId", SpannerDbType.Int64},
                {"AlbumId", SpannerDbType.Int64},
                {"MarketingBudget", SpannerDbType.Int64},
            });
            // Update second album to remove the transfer amount.
            secondBudget -= transferAmount;
            cmd.Parameters["SingerId"].Value = 2;
            cmd.Parameters["AlbumId"].Value = 2;
            cmd.Parameters["MarketingBudget"].Value = secondBudget;
            await cmd.ExecuteNonQueryAsync();
            // Update first album to add the transfer amount.
            firstBudget += transferAmount;
            cmd.Parameters["SingerId"].Value = 1;
            cmd.Parameters["AlbumId"].Value = 1;
            cmd.Parameters["MarketingBudget"].Value = firstBudget;
            await cmd.ExecuteNonQueryAsync();
            scope.Complete();
            Console.WriteLine("Transaction complete.");
        }
    }
}

.NET Standard 1.5

public static async Task ReadWriteWithTransactionCoreAsync(
    string projectId,
    string instanceId,
    string databaseId)
{
    // This sample transfers 200,000 from the MarketingBudget
    // field of the second Album to the first Album. Make sure to run
    // the addColumn and writeDataToNewColumn samples first,
    // in that order.
    string connectionString =
        $"Data Source=projects/{projectId}/instances/{instanceId}"
        + $"/databases/{databaseId}";

    decimal transferAmount = 200000;
    decimal secondBudget = 0;
    decimal firstBudget = 0;

    Console.WriteLine(".NetCore API sample.");

    // Create connection to Cloud Spanner.
    using (var connection =
        new SpannerConnection(connectionString))
    {
        await connection.OpenAsync();

        // Create a readwrite transaction that we'll assign
        // to each SpannerCommand.
        using (var transaction =
                await connection.BeginTransactionAsync())
        {
            // Create statement to select the second album's data.
            var cmdLookup = connection.CreateSelectCommand(
             "SELECT * FROM Albums WHERE SingerId = 2 AND AlbumId = 2");
            cmdLookup.Transaction = transaction;
            // Excecute the select query.
            using (var reader = await cmdLookup.ExecuteReaderAsync())
            {
                while (await reader.ReadAsync())
                {
                    // Read the second album's budget.
                    secondBudget =
                       reader.GetFieldValue<decimal>("MarketingBudget");
                    // Confirm second Album's budget is sufficient and
                    // if not raise an exception. Raising an exception
                    // will automatically roll back the transaction.
                    if (secondBudget < transferAmount)
                    {
                        throw new Exception("The second album's "
                                + $"budget {secondBudget} "
                                + "contains less than the "
                                + "amount to transfer.");
                    }
                }
            }
            // Read the first album's budget.
            cmdLookup = connection.CreateSelectCommand(
             "SELECT * FROM Albums WHERE SingerId = 1 and AlbumId = 1");
            cmdLookup.Transaction = transaction;
            using (var reader = await cmdLookup.ExecuteReaderAsync())
            {
                while (await reader.ReadAsync())
                {
                    firstBudget =
                      reader.GetFieldValue<decimal>("MarketingBudget");
                }
            }

            // Specify update command parameters.
            var cmd = connection.CreateUpdateCommand("Albums",
                new SpannerParameterCollection
                {
                    {"SingerId", SpannerDbType.Int64},
                    {"AlbumId", SpannerDbType.Int64},
                    {"MarketingBudget", SpannerDbType.Int64},
                });
            cmd.Transaction = transaction;
            // Update second album to remove the transfer amount.
            secondBudget -= transferAmount;
            cmd.Parameters["SingerId"].Value = 2;
            cmd.Parameters["AlbumId"].Value = 2;
            cmd.Parameters["MarketingBudget"].Value = secondBudget;
            await cmd.ExecuteNonQueryAsync();
            // Update first album to add the transfer amount.
            firstBudget += transferAmount;
            cmd.Parameters["SingerId"].Value = 1;
            cmd.Parameters["AlbumId"].Value = 1;
            cmd.Parameters["MarketingBudget"].Value = firstBudget;
            await cmd.ExecuteNonQueryAsync();

            await transaction.CommitAsync();
        }
        Console.WriteLine("Transaction complete.");
    }
}

Go

Verwenden Sie den Typ ReadWriteTransaction zum Ausführen eines Arbeitsablaufs im Zusammenhang mit einer Lese-Schreib-Transaktion. Client.ReadWriteTransaction() gibt ein ReadWriteTransaction-Objekt zurück.

Im Beispiel wird ReadWriteTransaction.ReadRow() verwendet, um eine Datenzeile abzurufen.

Im Beispiel wird auch ReadWriteTransaction.BufferWrite() verwendet, wodurch eine Liste von Mutationen zur Gruppe von Aktualisierungen hinzugefügt wird, die beim Commit der Transaktion angewendet werden.

Außerdem kommt im Beispiel der Typ Key zum Einsatz, der einen Zeilenschlüssel in einer Cloud Spanner-Tabelle oder einem -Index darstellt.


import (
	"context"
	"fmt"
	"io"

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

func writeWithTransaction(w io.Writer, db string) error {
	ctx := context.Background()
	client, err := spanner.NewClient(ctx, db)
	if err != nil {
		return err
	}
	defer client.Close()

	_, err = client.ReadWriteTransaction(ctx, func(ctx context.Context, txn *spanner.ReadWriteTransaction) error {
		getBudget := func(key spanner.Key) (int64, error) {
			row, err := txn.ReadRow(ctx, "Albums", key, []string{"MarketingBudget"})
			if err != nil {
				return 0, err
			}
			var budget int64
			if err := row.Column(0, &budget); err != nil {
				return 0, err
			}
			return budget, nil
		}
		album2Budget, err := getBudget(spanner.Key{2, 2})
		if err != nil {
			return err
		}
		const transferAmt = 200000
		if album2Budget >= transferAmt {
			album1Budget, err := getBudget(spanner.Key{1, 1})
			if err != nil {
				return err
			}
			album1Budget += transferAmt
			album2Budget -= transferAmt
			cols := []string{"SingerId", "AlbumId", "MarketingBudget"}
			txn.BufferWrite([]*spanner.Mutation{
				spanner.Update("Albums", cols, []interface{}{1, 1, album1Budget}),
				spanner.Update("Albums", cols, []interface{}{2, 2, album2Budget}),
			})
			fmt.Fprintf(w, "Moved %d from Album2's MarketingBudget to Album1's.", transferAmt)
		}
		return nil
	})
	return err
}

Java

Verwenden Sie die Schnittstelle TransactionRunner zum Ausführen eines Arbeitsablaufs im Zusammenhang mit einer Lese-Schreib-Transaktion. Diese Schnittstelle enthält die Methode run(), mit der Sie eine Lese-Schreib-Transaktion und gegebenenfalls deren Wiederholungen ausführen. Die Methode readWriteTransaction der Klasse DatabaseClient gibt ein TransactionRunner-Objekt zum Ausführen einer einzelnen logischen Transaktion zurück.

Die Klasse TransactionRunner.TransactionCallable enthält eine run()-Methode zum Ausführen eines einzelnen Transaktionsversuchs. run() verwendet ein TransactionContext-Objekt, das ein Kontext für eine Transaktion ist.

Im Beispiel wird die Klasse Struct verwendet, die sich gut zum Speichern der Ergebnisse der readRow()-Aufrufe eignet. Außerdem kommt im Beispiel die Klasse Key zum Einsatz, die einen Zeilenschlüssel in einer Cloud Spanner-Tabelle oder einem -Index darstellt.

Mit diesem Code können Sie die Transaktion ausführen:

static void writeWithTransaction(DatabaseClient dbClient) {
  dbClient
      .readWriteTransaction()
      .run(transaction -> {
        // Transfer marketing budget from one album to another. We do it in a transaction to
        // ensure that the transfer is atomic.
        Struct row =
            transaction.readRow("Albums", Key.of(2, 2), Arrays.asList("MarketingBudget"));
        long album2Budget = row.getLong(0);
        // Transaction will only be committed if this condition still holds at the time of
        // commit. Otherwise it will be aborted and the callable will be rerun by the
        // client library.
        long transfer = 200000;
        if (album2Budget >= transfer) {
          long album1Budget =
              transaction
                  .readRow("Albums", Key.of(1, 1), Arrays.asList("MarketingBudget"))
                  .getLong(0);
          album1Budget += transfer;
          album2Budget -= transfer;
          transaction.buffer(
              Mutation.newUpdateBuilder("Albums")
                  .set("SingerId")
                  .to(1)
                  .set("AlbumId")
                  .to(1)
                  .set("MarketingBudget")
                  .to(album1Budget)
                  .build());
          transaction.buffer(
              Mutation.newUpdateBuilder("Albums")
                  .set("SingerId")
                  .to(2)
                  .set("AlbumId")
                  .to(2)
                  .set("MarketingBudget")
                  .to(album2Budget)
                  .build());
        }
        return null;
      });
}

Node.js

Verwenden Sie Database.runTransaction(), um eine Transaktion auszuführen.

Mit diesem Code können Sie die Transaktion ausführen:

// This sample transfers 200,000 from the MarketingBudget field
// of the second Album to the first Album, as long as the second
// Album has enough money in its budget. Make sure to run the
// addColumn and updateData samples first (in that order).

// 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
const spanner = new Spanner({
  projectId: projectId,
});

// Gets a reference to a Cloud Spanner instance and database
const instance = spanner.instance(instanceId);
const database = instance.database(databaseId);

const transferAmount = 200000;

database.runTransaction(async (err, transaction) => {
  if (err) {
    console.error(err);
    return;
  }
  let firstBudget, secondBudget;
  const queryOne = {
    columns: ['MarketingBudget'],
    keys: [[2, 2]], // SingerId: 2, AlbumId: 2
  };

  const queryTwo = {
    columns: ['MarketingBudget'],
    keys: [[1, 1]], // SingerId: 1, AlbumId: 1
  };

  Promise.all([
    // Reads the second album's budget
    transaction.read('Albums', queryOne).then(results => {
      // Gets second album's budget
      const rows = results[0].map(row => row.toJSON());
      secondBudget = rows[0].MarketingBudget;
      console.log(`The second album's marketing budget: ${secondBudget}`);

      // Makes sure the second album's budget is large enough
      if (secondBudget < transferAmount) {
        throw new Error(
          `The second album's budget (${secondBudget}) is less than the transfer amount (${transferAmount}).`
        );
      }
    }),

    // Reads the first album's budget
    transaction.read('Albums', queryTwo).then(results => {
      // Gets first album's budget
      const rows = results[0].map(row => row.toJSON());
      firstBudget = rows[0].MarketingBudget;
      console.log(`The first album's marketing budget: ${firstBudget}`);
    }),
  ])
    .then(() => {
      console.log(firstBudget, secondBudget);
      // Transfers the budgets between the albums
      firstBudget += transferAmount;
      secondBudget -= transferAmount;

      console.log(firstBudget, secondBudget);

      // Updates the database
      // Note: Cloud Spanner interprets Node.js numbers as FLOAT64s, so they
      // must be converted (back) to strings before being inserted as INT64s.
      transaction.update('Albums', [
        {
          SingerId: '1',
          AlbumId: '1',
          MarketingBudget: firstBudget.toString(),
        },
        {
          SingerId: '2',
          AlbumId: '2',
          MarketingBudget: secondBudget.toString(),
        },
      ]);
    })
    .then(() => {
      // Commits the transaction and send the changes to the database
      return transaction.commit();
    })
    .then(() => {
      console.log(
        `Successfully executed read-write transaction to transfer ${transferAmount} from Album 2 to Album 1.`
      );
    })
    .catch(err => {
      console.error('ERROR:', err);
    })
    .then(() => {
      transaction.end();
      // Closes the database when finished
      return database.close();
    });
});

PHP

Verwenden Sie Database::runTransaction, um eine Transaktion auszuführen.

Mit diesem Code können Sie die Transaktion ausführen:

use Google\Cloud\Spanner\SpannerClient;
use Google\Cloud\Spanner\Transaction;
use UnexpectedValueException;

/**
 * Performs a read-write transaction to update two sample records in the
 * database.
 *
 * This will transfer 200,000 from the `MarketingBudget` field for the second
 * Album to the first Album. If the `MarketingBudget` for the second Album is
 * too low, it will raise an exception.
 *
 * Before running this sample, you will need to run the `update_data` sample
 * to populate the fields.
 * Example:
 * ```
 * read_write_transaction($instanceId, $databaseId);
 * ```
 *
 * @param string $instanceId The Spanner instance ID.
 * @param string $databaseId The Spanner database ID.
 */
function read_write_transaction($instanceId, $databaseId)
{
    $spanner = new SpannerClient();
    $instance = $spanner->instance($instanceId);
    $database = $instance->database($databaseId);

    $database->runTransaction(function (Transaction $t) use ($spanner) {
        $transferAmount = 200000;

        // Read the second album's budget.
        $secondAlbumKey = [2, 2];
        $secondAlbumKeySet = $spanner->keySet(['keys' => [$secondAlbumKey]]);
        $secondAlbumResult = $t->read(
            'Albums',
            $secondAlbumKeySet,
            ['MarketingBudget'],
            ['limit' => 1]
        );

        $firstRow = $secondAlbumResult->rows()->current();
        $secondAlbumBudget = $firstRow['MarketingBudget'];
        if ($secondAlbumBudget < $transferAmount) {
            // Throwing an exception will automatically roll back the transaction.
            throw new UnexpectedValueException(
                'The second album\'s budget is lower than the transfer amount: ' . $transferAmount
            );
        }

        $firstAlbumKey = [1, 1];
        $firstAlbumKeySet = $spanner->keySet(['keys' => [$firstAlbumKey]]);
        $firstAlbumResult = $t->read(
            'Albums',
            $firstAlbumKeySet,
            ['MarketingBudget'],
            ['limit' => 1]
        );

        // Read the first album's budget.
        $firstRow = $firstAlbumResult->rows()->current();
        $firstAlbumBudget = $firstRow['MarketingBudget'];

        // Update the budgets.
        $secondAlbumBudget -= $transferAmount;
        $firstAlbumBudget += $transferAmount;
        printf('Setting first album\'s budget to %s and the second album\'s ' .
            'budget to %s.' . PHP_EOL, $firstAlbumBudget, $secondAlbumBudget);

        // Update the rows.
        $t->updateBatch('Albums', [
            ['SingerId' => 1, 'AlbumId' => 1, 'MarketingBudget' => $firstAlbumBudget],
            ['SingerId' => 2, 'AlbumId' => 2, 'MarketingBudget' => $secondAlbumBudget],
        ]);

        // Commit the transaction!
        $t->commit();

        print('Transaction complete.' . PHP_EOL);
    });
}

Python

Verwenden Sie die Methode run_in_transaction() der Klasse Database, um eine Transaktion auszuführen.

Mit diesem Code können Sie die Transaktion ausführen:

def read_write_transaction(instance_id, database_id):
    """Performs a read-write transaction to update two sample records in the
    database.

    This will transfer 200,000 from the `MarketingBudget` field for the second
    Album to the first Album. If the `MarketingBudget` is too low, it will
    raise an exception.

    Before running this sample, you will need to run the `update_data` sample
    to populate the fields.
    """
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)

    def update_albums(transaction):
        # Read the second album budget.
        second_album_keyset = spanner.KeySet(keys=[(2, 2)])
        second_album_result = transaction.read(
            table="Albums",
            columns=("MarketingBudget",),
            keyset=second_album_keyset,
            limit=1,
        )
        second_album_row = list(second_album_result)[0]
        second_album_budget = second_album_row[0]

        transfer_amount = 200000

        if second_album_budget < transfer_amount:
            # Raising an exception will automatically roll back the
            # transaction.
            raise ValueError("The second album doesn't have enough funds to transfer")

        # Read the first album's budget.
        first_album_keyset = spanner.KeySet(keys=[(1, 1)])
        first_album_result = transaction.read(
            table="Albums",
            columns=("MarketingBudget",),
            keyset=first_album_keyset,
            limit=1,
        )
        first_album_row = list(first_album_result)[0]
        first_album_budget = first_album_row[0]

        # Update the budgets.
        second_album_budget -= transfer_amount
        first_album_budget += transfer_amount
        print(
            "Setting first album's budget to {} and the second album's "
            "budget to {}.".format(first_album_budget, second_album_budget)
        )

        # Update the rows.
        transaction.update(
            table="Albums",
            columns=("SingerId", "AlbumId", "MarketingBudget"),
            values=[(1, 1, first_album_budget), (2, 2, second_album_budget)],
        )

    database.run_in_transaction(update_albums)

    print("Transaction complete.")

Ruby

Verwenden Sie die Methode transaction der Klasse Client, um eine Transaktion auszuführen.

Mit diesem Code können Sie die Transaktion ausführen:

# 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.new project: project_id
client          = spanner.client instance_id, database_id
transfer_amount = 200_000

client.transaction do |transaction|
  first_album  = transaction.read("Albums", [:MarketingBudget], keys: [[1, 1]]).rows.first
  second_album = transaction.read("Albums", [:MarketingBudget], keys: [[2, 2]]).rows.first

  raise "The second album does not have enough funds to transfer" if second_album[:MarketingBudget] < transfer_amount

  new_first_album_budget  = first_album[:MarketingBudget] + transfer_amount
  new_second_album_budget = second_album[:MarketingBudget] - transfer_amount

  transaction.update "Albums", [
    { SingerId: 1, AlbumId: 1, MarketingBudget: new_first_album_budget  },
    { SingerId: 2, AlbumId: 2, MarketingBudget: new_second_album_budget }
  ]
end

puts "Transaction complete"

Zeilen in einer Tabelle löschen

Jede Clientbibliothek stellt mehrere Möglichkeiten zum Löschen von Zeilen bereit:

  • Alle Zeilen in einer Tabelle löschen
  • Eine einzelne Zeile löschen, wenn Key-Spaltenwerte für die Zeile angegeben werden
  • Eine Gruppe von Zeilen löschen, wenn ein Schlüsselbereich erstellt wird
  • Zeilen in einer verschränkten Tabelle löschen, wenn die übergeordneten Zeilen gelöscht werden, falls die verschränkte Tabelle ON DELETE CASCADE in ihrer Schemadefinition enthält

C++

Löschen Sie Zeilen mit der Funktion DeleteMutationBuilder() für einen Client.

Dieser Code zeigt, wie die Daten gelöscht werden:

void DeleteData(google::cloud::spanner::Client client) {
  namespace spanner = ::google::cloud::spanner;

  // Delete the albums with key (2,1) and (2,3).
  auto delete_albums = spanner::DeleteMutationBuilder(
                           "Albums", spanner::KeySet()
                                         .AddKey(spanner::MakeKey(2, 1))
                                         .AddKey(spanner::MakeKey(2, 3)))
                           .Build();

  // Delete some singers using the keys in the range [3, 5]
  auto delete_singers_range =
      spanner::DeleteMutationBuilder(
          "Singers", spanner::KeySet().AddRange(spanner::MakeKeyBoundClosed(3),
                                                spanner::MakeKeyBoundOpen(5)))
          .Build();

  // Deletes remaining rows from the Singers table and the Albums table, because
  // the Albums table is defined with ON DELETE CASCADE.
  auto delete_singers_all =
      spanner::MakeDeleteMutation("Singers", spanner::KeySet::All());

  auto commit_result = client.Commit(spanner::Mutations{
      delete_albums, delete_singers_range, delete_singers_all});
  if (!commit_result) {
    throw std::runtime_error(commit_result.status().message());
  }
  std::cout << "Delete was successful [spanner_delete_data]\n";
}

C#

Löschen Sie Zeilen mit der Methode connection.CreateDeleteCommand(). Diese erstellt einen neuen SpannerCommand, um Zeilen zu löschen. Mit der Methode SpannerCommand.ExecuteNonQueryAsync() werden die Zeilen aus der Tabelle gelöscht.

In diesem Beispiel werden die Zeilen in der Tabelle Singers einzeln gelöscht. Die Zeilen in der Tabelle Albums werden gelöscht, da die Tabelle Albums mit der Tabelle Singers verschränkt und mit ON DELETE CASCADE definiert ist.

public static async Task DeleteIndividualRowsAsync(
    string projectId, string instanceId, string databaseId)
{
    const int singerId = 2;
    string connectionString =
        $"Data Source=projects/{projectId}/instances/{instanceId}"
        + $"/databases/{databaseId}";
    List<Album> albums = new List<Album>
    {
        new Album { SingerId = singerId, AlbumId = 1, AlbumTitle = "Green" },
        new Album { SingerId = singerId, AlbumId = 3, AlbumTitle = "Terrified" },
    };
    // Create connection to Cloud Spanner.
    using (var connection = new SpannerConnection(connectionString))
    {
        await connection.OpenAsync();

        // Delete individual rows from the UpcomingAlbums table.
        await Task.WhenAll(albums.Select(album =>
        {
            var cmd = connection.CreateDeleteCommand(
                "UpcomingAlbums",
                new SpannerParameterCollection
                {
                    { "SingerId", SpannerDbType.Int64, album.SingerId },
                    { "AlbumId", SpannerDbType.Int64, album.AlbumId }
                }
            );
            return cmd.ExecuteNonQueryAsync();
        }));

        Console.WriteLine("Deleted individual rows in UpcomingAlbums.");
    }
}

public static async Task DeleteRangeOfRowsAsync(
    string projectId, string instanceId, string databaseId)
{
    string connectionString =
        $"Data Source=projects/{projectId}/instances/{instanceId}"
        + $"/databases/{databaseId}";
    // Create connection to Cloud Spanner.
    using (var connection = new SpannerConnection(connectionString))
    {
        await connection.OpenAsync();

        // Delete a range of rows from the UpcomingSingers table where the column key is >=3 and <5.
        var cmd = connection.CreateDmlCommand(
           "DELETE FROM UpcomingSingers WHERE SingerId >= 3 AND SingerId < 5");
        int rowCount = await cmd.ExecuteNonQueryAsync();
        Console.WriteLine($"{rowCount} row(s) deleted from UpcomingSingers.");
    }
}

public static async Task DeleteAllRowsAsync(
    string projectId, string instanceId, string databaseId)
{
    string connectionString =
        $"Data Source=projects/{projectId}/instances/{instanceId}"
        + $"/databases/{databaseId}";
    // Create connection to Cloud Spanner.
    using (var connection = new SpannerConnection(connectionString))
    {
        await connection.OpenAsync();

        // Delete remaining UpcomingSingers rows, which will also delete the remaining
        // UpcomingAlbums rows since it was defined with ON DELETE CASCADE.
        var cmd = connection.CreateDmlCommand(
           "DELETE FROM UpcomingSingers WHERE true");
        int rowCount = await cmd.ExecuteNonQueryAsync();
        Console.WriteLine($"{rowCount} row(s) deleted from UpcomingSingers.");
    }
}

Go

Zeilen können mit Mutation gelöscht werden. Verwenden Sie dabei die Methode Mutation.Delete() zum Erstellen einer DELETE-Mutation, wodurch eine Zeile gelöscht wird. Die Methode Client.Apply() wendet Mutationen in kleinstmöglichen Schritten auf die Datenbank an.

In diesem Beispiel werden die Zeilen in der Tabelle Albums einzeln gelöscht. Anschließend werden alle Zeilen in der Tabelle Singers mit KeyRange gelöscht.


import (
	"context"
	"io"

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

func delete(w io.Writer, db string) error {
	ctx := context.Background()
	client, err := spanner.NewClient(ctx, db)
	if err != nil {
		return err
	}
	defer client.Close()

	m := []*spanner.Mutation{
		// Delete individual rows.
		spanner.Delete("Albums", spanner.Key{2, 1}),
		spanner.Delete("Albums", spanner.Key{2, 3}),
		// Delete a range of rows where the column key is >=3 and <5.
		spanner.Delete("Singers", spanner.KeyRange{Start: spanner.Key{3}, End: spanner.Key{5}, Kind: spanner.ClosedOpen}),
		// Delete remaining Singers rows, which will also delete the remaining
		// Albums rows because Albums was defined with ON DELETE CASCADE.
		spanner.Delete("Singers", spanner.AllKeys()),
	}
	_, err = client.Apply(ctx, m)
	return err
}

Java

Zeilen können mit der Methode Mutation.delete() gelöscht werden.

In diesem Beispiel werden mithilfe der Methode KeySet.all() alle Zeilen in der Tabelle Albums gelöscht. Nachdem die Zeilen in der Tabelle Albums gelöscht wurden, werden in diesem Beispiel die Zeilen aus der Tabelle Singers einzeln gelöscht. Dabei werden Schlüssel verwendet, die mit der Methode KeySet.singleKey() erstellt wurden.

static void deleteExampleData(DatabaseClient dbClient) {
  List<Mutation> mutations = new ArrayList<>();

  // KeySet.Builder can be used to delete a specific set of rows.
  // Delete the Albums with the key values (2,1) and (2,3).
  mutations.add(
      Mutation.delete(
          "Albums", KeySet.newBuilder().addKey(Key.of(2, 1)).addKey(Key.of(2, 3)).build()));

  // KeyRange can be used to delete rows with a key in a specific range.
  // Delete a range of rows where the column key is >=3 and <5
  mutations.add(
      Mutation.delete("Singers", KeySet.range(KeyRange.closedOpen(Key.of(3), Key.of(5)))));

  // KeySet.all() can be used to delete all the rows in a table.
  // Delete remaining Singers rows, which will also delete the remaining Albums rows since it was
  // defined with ON DELETE CASCADE.
  mutations.add(Mutation.delete("Singers", KeySet.all()));

  dbClient.write(mutations);
  System.out.printf("Records deleted.\n");
}

Node.js

Zeilen können mit der Methode table.deleteRows() gelöscht werden.

In diesem Beispiel werden mit der Methode table.deleteRows() alle Zeilen aus der Tabelle Singers gelöscht. Die Zeilen in der Tabelle Albums werden gelöscht, da die Tabelle Albums mit der Tabelle Singers verschränkt und mit ON DELETE CASCADE definiert ist.

// 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
const spanner = new Spanner({
  projectId: projectId,
});

// Gets a reference to a Cloud Spanner instance and database
const instance = spanner.instance(instanceId);
const database = instance.database(databaseId);

// Instantiate Spanner table object
const albumsTable = database.table('Albums');

// Deletes individual rows from the Albums table.
try {
  const keys = [
    [2, 1],
    [2, 3],
  ];
  await albumsTable.deleteRows(keys);
  console.log('Deleted individual rows in Albums.');
} catch (err) {
  console.error('ERROR:', err);
}

// Delete a range of rows where the column key is >=3 and <5
database.runTransaction(async (err, transaction) => {
  if (err) {
    console.error(err);
    return;
  }
  try {
    const [rowCount] = await transaction.runUpdate({
      sql: 'DELETE FROM Singers WHERE SingerId >= 3 AND SingerId < 5',
    });
    console.log(`${rowCount} records deleted from Singers.`);
  } catch (err) {
    console.error('ERROR:', err);
  }

  // Deletes remaining rows from the Singers table and the Albums table,
  // because Albums table is defined with ON DELETE CASCADE.
  try {
    // The WHERE clause is required for DELETE statements to prevent
    // accidentally deleting all rows in a table.
    // https://cloud.google.com/spanner/docs/dml-syntax#where_clause
    const [rowCount] = await transaction.runUpdate({
      sql: 'DELETE FROM Singers WHERE true',
    });
    console.log(`${rowCount} records deleted from Singers.`);
    await transaction.commit();
  } catch (err) {
    console.error('ERROR:', err);
  } finally {
    // Close the database when finished.
    await database.close();
  }
});

PHP

Zeilen können mit Database::delete() method gelöscht werden. Auf der Seite für die Methode Database::delete() finden Sie ein Beispiel.

Python

Zeilen können mit der Methode Batch.delete() gelöscht werden.

In diesem Beispiel werden alle Zeilen in den Tabellen Albums und Singers mit einem KeySet-Objekt einzeln gelöscht.

def delete_data(instance_id, database_id):
    """Deletes sample data from the given database.

    The database, table, and data must already exist and can be created using
    `create_database` and `insert_data`.
    """
    spanner_client = spanner.Client()
    instance = spanner_client.instance(instance_id)
    database = instance.database(database_id)

    # Delete individual rows
    albums_to_delete = spanner.KeySet(keys=[[2, 1], [2, 3]])

    # Delete a range of rows where the column key is >=3 and <5
    singers_range = spanner.KeyRange(start_closed=[3], end_open=[5])
    singers_to_delete = spanner.KeySet(ranges=[singers_range])

    # Delete remaining Singers rows, which will also delete the remaining
    # Albums rows because Albums was defined with ON DELETE CASCADE
    remaining_singers = spanner.KeySet(all_=True)

    with database.batch() as batch:
        batch.delete("Albums", albums_to_delete)
        batch.delete("Singers", singers_to_delete)
        batch.delete("Singers", remaining_singers)

    print("Deleted data.")

Ruby

Zeilen können mit der Methode Client#delete gelöscht werden. Auf der Seite Client#delete finden Sie ein Beispiel.

# 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.new project: project_id
client  = spanner.client instance_id, database_id

# Delete individual rows
client.delete "Albums", [[2, 1], [2, 3]]

# Delete a range of rows where the column key is >=3 and <5
key_range = client.range 3, 5, exclude_end: true
client.delete "Singers", key_range

# Delete remaining Singers rows, which will also delete the remaining
# Albums rows because Albums was defined with ON DELETE CASCADE
client.delete "Singers"