JDBC

Các phiên bản 1.0 và 1.1 của giao thức bảo mật TLS bị vô hiệu hoá. Để thiết lập kết nối, hãy sử dụng TLS 1.2 trở lên.

Google Apps Script có thể kết nối với các cơ sở dữ liệu bên ngoài thông qua dịch vụ JDBC, một trình bao bọc xung quanh công nghệ Java Database Connectivity tiêu chuẩn. Dịch vụ JDBC hỗ trợ cơ sở dữ liệu Google Cloud SQL cho MySQL, MySQL, Microsoft SQL Server, Oracle và PostgreSQL.

Nếu bảng tính của bạn đang phát triển quá lớn hoặc bạn gặp phải vấn đề về thời gian chờ với các phép tính phức tạp, thì việc di chuyển dữ liệu sang một cơ sở dữ liệu bên ngoài có thể cải thiện đáng kể hiệu suất và độ tin cậy.

Để cập nhật cơ sở dữ liệu bên ngoài bằng JDBC, tập lệnh của bạn phải mở một kết nối đến cơ sở dữ liệu rồi thực hiện các thay đổi bằng cách gửi câu lệnh SQL.

Cơ sở dữ liệu Google Cloud SQL

Google Cloud SQL cho phép bạn tạo cơ sở dữ liệu quan hệ nằm trong đám mây của Google. Cloud SQL có thể tính phí dựa trên mức sử dụng của bạn.

Tạo một phiên bản Google Cloud SQL bằng cách làm theo các bước được liệt kê trong phần Hướng dẫn nhanh về Cloud SQL.

Tạo kết nối Google Cloud SQL

Có hai cách để thiết lập kết nối với cơ sở dữ liệu Google Cloud SQL bằng dịch vụ JDBC của Apps Script:

Cả hai đều hợp lệ, nhưng phương thức thứ hai yêu cầu bạn uỷ quyền cho một nhóm dải IP để truy cập vào cơ sở dữ liệu của mình.

Phương thức này tạo một kết nối đến một phiên bản MySQL trên Google Cloud SQL bằng phương thức Jdbc.getCloudSqlConnection. URL cơ sở dữ liệu có dạng jdbc:google:mysql://subname, trong đó subnameTên kết nối phiên bản MySQL có trong trang Tổng quan về phiên bản Cloud SQL trong bảng điều khiển Cloud.

Để kết nối với Cloud SQL SQL Server, hãy xem Jdbc.getConnection.

Sử dụng Jdbc.getConnection

Để sử dụng phương thức này, bạn phải uỷ quyền cho một số dải địa chỉ IP Định tuyến liên miền không phân lớp (CIDR) để máy chủ của Apps Script có thể kết nối với cơ sở dữ liệu của bạn. Trước khi chạy tập lệnh, hãy hoàn tất các bước sau:

  1. Trong phiên bản Google Cloud SQL, hãy uỷ quyền cho từng dải IP một lần từ nguồn dữ liệu này.

  2. Sao chép URL được chỉ định cho cơ sở dữ liệu của bạn; URL này phải có dạng jdbc:mysql:subname.

Sau khi bạn uỷ quyền cho các dải IP này, hãy tạo kết nối đến phiên bản Google Cloud SQL bằng một trong các phương thức Jdbc.getConnection và URL mà bạn đã sao chép trước đó.

Các cơ sở dữ liệu khác

Nếu bạn đã có cơ sở dữ liệu MySQL, Microsoft SQL Server, Oracle hoặc PostgreSQL của riêng mình, hãy kết nối với cơ sở dữ liệu đó thông qua dịch vụ JDBC của Apps Script.

Tạo các kết nối cơ sở dữ liệu khác

Để tạo mối kết nối cơ sở dữ liệu bằng dịch vụ JDBC của Apps Script, bạn phải uỷ quyền cho dải IP từ nguồn dữ liệu này trong phần cài đặt cơ sở dữ liệu.

Dịch vụ JDBC chỉ có thể kết nối với các cổng từ 1025 trở lên. Đảm bảo cơ sở dữ liệu của bạn không phân phát từ một cổng thấp hơn.

Sau khi các danh sách cho phép này được thiết lập, hãy tạo một kết nối đến cơ sở dữ liệu bằng một trong các phương thức Jdbc.getConnection và URL của cơ sở dữ liệu.

Mã mẫu

Mã mẫu sau đây giả định rằng bạn đang kết nối với một cơ sở dữ liệu Google Cloud SQL và tạo các kết nối cơ sở dữ liệu bằng phương thức Jdbc.getCloudSqlConnection. Đối với các cơ sở dữ liệu khác, bạn phải sử dụng phương thức Jdbc.getConnection để tạo kết nối cơ sở dữ liệu.

Để biết thêm thông tin về các phương thức JDBC, hãy xem tài liệu Java cho JDBC.

Tạo cơ sở dữ liệu, người dùng và bảng

Hầu hết nhà phát triển đều sử dụng công cụ dòng lệnh MySQL để tạo cơ sở dữ liệu, người dùng và bảng. Tuy nhiên, bạn có thể làm điều tương tự trong Apps Script, như trong ví dụ sau. Tạo ít nhất một người dùng khác để tập lệnh của bạn không phải lúc nào cũng kết nối với cơ sở dữ liệu dưới dạng root.

service/jdbc.gs
/**
 * Create a new database within a Cloud SQL instance.
 */
function createDatabase() {
  try {
    const conn = Jdbc.getCloudSqlConnection(instanceUrl, root, rootPwd);
    conn.createStatement().execute(`CREATE DATABASE ${db}`);
  } catch (err) {
    // TODO(developer) - Handle exception from the API
    console.log("Failed with an error %s", err.message);
  }
}

/**
 * Create a new user for your database with full privileges.
 */
function createUser() {
  try {
    const conn = Jdbc.getCloudSqlConnection(dbUrl, root, rootPwd);

    const stmt = conn.prepareStatement("CREATE USER ? IDENTIFIED BY ?");
    stmt.setString(1, user);
    stmt.setString(2, userPwd);
    stmt.execute();

    conn.createStatement().execute(`GRANT ALL ON \`%\`.* TO ${user}`);
  } catch (err) {
    // TODO(developer) - Handle exception from the API
    console.log("Failed with an error %s", err.message);
  }
}

/**
 * Create a new table in the database.
 */
function createTable() {
  try {
    const conn = Jdbc.getCloudSqlConnection(dbUrl, user, userPwd);
    conn
      .createStatement()
      .execute(
        "CREATE TABLE entries " +
          "(guestName VARCHAR(255), content VARCHAR(255), " +
          "entryID INT NOT NULL AUTO_INCREMENT, PRIMARY KEY(entryID));",
      );
  } catch (err) {
    // TODO(developer) - Handle exception from the API
    console.log("Failed with an error %s", err.message);
  }
}

Ghi vào cơ sở dữ liệu

Các ví dụ sau đây minh hoạ cách ghi một bản ghi vào cơ sở dữ liệu cũng như một lô gồm 500 bản ghi. Việc xử lý hàng loạt là rất quan trọng đối với các thao tác hàng loạt.

Các câu lệnh có tham số được dùng, trong đó các biến được biểu thị bằng ?. Để ngăn chặn các cuộc tấn công chèn SQL, hãy sử dụng các câu lệnh được tham số hoá để thoát khỏi tất cả dữ liệu do người dùng cung cấp.

service/jdbc.gs
/**
 * Write one row of data to a table.
 */
function writeOneRecord() {
  try {
    const conn = Jdbc.getCloudSqlConnection(dbUrl, user, userPwd);

    const stmt = conn.prepareStatement(
      "INSERT INTO entries " + "(guestName, content) values (?, ?)",
    );
    stmt.setString(1, "First Guest");
    stmt.setString(2, "Hello, world");
    stmt.execute();
  } catch (err) {
    // TODO(developer) - Handle exception from the API
    console.log("Failed with an error %s", err.message);
  }
}

/**
 * Write 500 rows of data to a table in a single batch.
 */
function writeManyRecords() {
  try {
    const conn = Jdbc.getCloudSqlConnection(dbUrl, user, userPwd);
    conn.setAutoCommit(false);

    const start = new Date();
    const stmt = conn.prepareStatement(
      "INSERT INTO entries " + "(guestName, content) values (?, ?)",
    );
    for (let i = 0; i < 500; i++) {
      stmt.setString(1, `Name ${i}`);
      stmt.setString(2, `Hello, world ${i}`);
      stmt.addBatch();
    }

    const batch = stmt.executeBatch();
    conn.commit();
    conn.close();

    const end = new Date();
    console.log("Time elapsed: %sms for %s rows.", end - start, batch.length);
  } catch (err) {
    // TODO(developer) - Handle exception from the API
    console.log("Failed with an error %s", err.message);
  }
}

/**
 * Write 500 rows of data to a table in a single batch.
 * Recommended for faster writes
 */
function writeManyRecordsUsingExecuteBatch() {
  try {
    const conn = Jdbc.getCloudSqlConnection(dbUrl, user, userPwd);
    conn.setAutoCommit(false);

    const start = new Date();
    const stmt = conn.prepareStatement(
      "INSERT INTO entries " + "(guestName, content) values (?, ?)",
    );
    const params = [];
    for (let i = 0; i < 500; i++) {
      params.push([`Name ${i}`, `Hello, world ${i}`]);
    }

    const batch = stmt.executeBatch(params);
    conn.commit();
    conn.close();

    const end = new Date();
    console.log("Time elapsed: %sms for %s rows.", end - start, batch.length);
  } catch (err) {
    // TODO(developer) - Handle exception from the API
    console.log("Failed with an error %s", err.message);
  }
}

Đọc từ cơ sở dữ liệu

Ví dụ này minh hoạ cách đọc một số lượng lớn bản ghi từ cơ sở dữ liệu, lặp lại trên tập kết quả nếu cần.

service/jdbc.gs
/**
 * Read up to 1000 rows of data from the table and log them.
 */
function readFromTable() {
  try {
    const conn = Jdbc.getCloudSqlConnection(dbUrl, user, userPwd);
    const start = new Date();
    const stmt = conn.createStatement();
    stmt.setMaxRows(1000);
    const results = stmt.executeQuery("SELECT * FROM entries");
    const numCols = results.getMetaData().getColumnCount();

    while (results.next()) {
      let rowString = "";
      for (let col = 0; col < numCols; col++) {
        rowString += `${results.getString(col + 1)}\t`;
      }
      console.log(rowString);
    }

    results.close();
    stmt.close();

    const end = new Date();
    console.log("Time elapsed: %sms", end - start);
  } catch (err) {
    // TODO(developer) - Handle exception from the API
    console.log("Failed with an error %s", err.message);
  }
}

/**
 * Read up to 1000 rows of data from the table and log them.
 * Recommended for faster reads
 */
function readFromTableUsingGetRows() {
  try {
    const conn = Jdbc.getCloudSqlConnection(dbUrl, user, userPwd);
    const start = new Date();
    const stmt = conn.createStatement();
    stmt.setMaxRows(1000);
    const results = stmt.executeQuery("SELECT * FROM entries");
    const numCols = results.getMetaData().getColumnCount();
    const getRowArgs = [];
    for (let col = 0; col < numCols; col++) {
      getRowArgs.push(`getString(${col + 1})`);
    }
    const rows = results.getRows(getRowArgs.join(","));
    for (let i = 0; i < rows.length; i++) {
      console.log(rows[i].join("\t"));
    }

    results.close();
    stmt.close();

    const end = new Date();
    console.log("Time elapsed: %sms", end - start);
  } catch (err) {
    // TODO(developer) - Handle exception from the API
    console.log("Failed with an error %s", err.message);
  }
}

Kết nối lân cận

Các kết nối JDBC sẽ tự động đóng khi một tập lệnh hoàn tất việc thực thi. (Lệnh gọi google.script.run duy nhất được tính là một lần thực thi hoàn chỉnh, ngay cả khi trang dịch vụ HTML đã thực hiện lệnh gọi vẫn mở.)

Tuy nhiên, nếu bạn biết mình đã hoàn tất một kết nối, câu lệnh hoặc tập hợp kết quả trước khi kết thúc tập lệnh, hãy đóng chúng theo cách thủ công bằng cách gọi JdbcConnection.close, JdbcStatement.close hoặc JdbcResultSet.close.

Việc hiện hộp thoại cảnh báo hoặc hộp thoại nhắc cũng sẽ chấm dứt mọi kết nối JDBC đang mở. Tuy nhiên, các thành phần giao diện người dùng khác đang hiển thị (chẳng hạn như trình đơn tuỳ chỉnh hoặc hộp thoại và thanh bên có nội dung tuỳ chỉnh) thì không.

Google, Google Workspace, cũng như những nhãn hiệu và biểu tượng có liên quan là nhãn hiệu của Google LLC. Tất cả các tên sản phẩm và công ty khác là nhãn hiệu của những công ty mà chúng liên kết.