JDBC

ระบบจะปิดใช้โปรโตคอลความปลอดภัย TLS เวอร์ชัน 1.0 และ 1.1 หากต้องการสร้างการเชื่อมต่อ ให้ใช้ TLS 1.2 ขึ้นไป

Google Apps Script สามารถเชื่อมต่อกับฐานข้อมูลภายนอกผ่านบริการ JDBC ซึ่งเป็น Wrapper รอบเทคโนโลยี Java Database Connectivity มาตรฐาน บริการ JDBC รองรับฐานข้อมูล Google Cloud SQL สำหรับ MySQL, MySQL, Microsoft SQL Server, Oracle และ PostgreSQL

หากสเปรดชีตมีขนาดใหญ่เกินไปหรือคุณพบปัญหาการหมดเวลาในการคำนวณที่ซับซ้อน การย้ายข้อมูลไปยังฐานข้อมูลภายนอกจะช่วยปรับปรุงประสิทธิภาพและความน่าเชื่อถือได้อย่างมาก

หากต้องการอัปเดตฐานข้อมูลภายนอกด้วย JDBC สคริปต์ต้องเปิดการเชื่อมต่อกับฐานข้อมูล แล้วทำการเปลี่ยนแปลงโดยส่งคำสั่ง SQL

ฐานข้อมูล Google Cloud SQL

Google Cloud SQL ช่วยให้คุณสร้างฐานข้อมูลเชิงสัมพันธ์ ที่อยู่ในระบบคลาวด์ของ Google ได้ Cloud SQL อาจเรียกเก็บเงินตามการใช้งานของคุณ

สร้างอินสแตนซ์ Google Cloud SQL โดยทำตามขั้นตอนที่ระบุไว้ในการเริ่มต้นใช้งาน Cloud SQL อย่างรวดเร็ว

สร้างการเชื่อมต่อ Google Cloud SQL

การสร้างการเชื่อมต่อกับฐานข้อมูล Google Cloud SQL โดยใช้บริการ JDBC ของ Apps Script ทำได้ 2 วิธีดังนี้

ทั้ง 2 วิธีใช้ได้ แต่ในวิธีที่ 2 คุณต้องให้สิทธิ์ช่วง IP ชุดหนึ่งเพื่อเข้าถึงฐานข้อมูล

เมธอดนี้สร้างการเชื่อมต่อกับอินสแตนซ์ Google Cloud SQL MySQL โดยใช้เมธอด Jdbc.getCloudSqlConnection URL ฐานข้อมูลมีรูปแบบ jdbc:google:mysql://subname โดยที่ subname คือชื่อการเชื่อมต่ออินสแตนซ์ MySQL ที่แสดงในหน้าภาพรวมของอินสแตนซ์ Cloud SQL ใน Google Cloud Console

หากต้องการเชื่อมต่อกับ SQL Server ใน Cloud SQL โปรดดูที่ Jdbc.getConnection

ใช้ Jdbc.getConnection

หากต้องการใช้วิธีนี้ คุณต้องให้สิทธิ์ช่วงที่อยู่ IP ของ Classless Inter-Domain Routing (CIDR) บางช่วง เพื่อให้เซิร์ฟเวอร์ของ Apps Script เชื่อมต่อกับฐานข้อมูลของคุณได้ ก่อนเรียกใช้สคริปต์ ให้ทำตามขั้นตอนต่อไปนี้

  1. ในอินสแตนซ์ Google Cloud SQL ให้ให้สิทธิ์ช่วง IP ทีละช่วงจากแหล่งข้อมูลนี้

  2. คัดลอก URL ที่กำหนดให้กับฐานข้อมูลของคุณ โดย URL ควรมีรูปแบบ jdbc:mysql:subname

เมื่อให้สิทธิ์ช่วง IP เหล่านี้แล้ว ให้สร้างการเชื่อมต่อกับอินสแตนซ์ SQL ของ Google Cloud โดยใช้วิธีการ Jdbc.getConnection อย่างใดอย่างหนึ่งและ URL ที่คุณคัดลอกไว้ก่อนหน้านี้

ฐานข้อมูลอื่นๆ

หากมีฐานข้อมูล MySQL, Microsoft SQL Server, Oracle หรือ PostgreSQL อยู่แล้ว ให้เชื่อมต่อผ่านบริการ JDBC ของ Apps Script

สร้างการเชื่อมต่อฐานข้อมูลอื่นๆ

หากต้องการสร้างการเชื่อมต่อฐานข้อมูลโดยใช้ JDBC service ของ Apps Script ในการตั้งค่าฐานข้อมูล คุณต้องให้สิทธิ์ช่วง IP จากแหล่งข้อมูลนี้

บริการ JDBC จะเชื่อมต่อได้เฉพาะพอร์ต 1025 ขึ้นไปเท่านั้น ตรวจสอบว่า ฐานข้อมูลไม่ได้ให้บริการในพอร์ตที่ต่ำกว่า

เมื่อสร้างรายการที่อนุญาตเหล่านี้แล้ว ให้สร้างการเชื่อมต่อกับฐานข้อมูล โดยใช้วิธีใดวิธีหนึ่งของ Jdbc.getConnection และ URL ของฐานข้อมูล

โค้ดตัวอย่าง

โค้ดตัวอย่างต่อไปนี้ถือว่าคุณกำลังเชื่อมต่อกับฐานข้อมูล Google Cloud SQL และสร้างการเชื่อมต่อฐานข้อมูลโดยใช้เมธอด Jdbc.getCloudSqlConnection สําหรับฐานข้อมูลอื่นๆ คุณต้องใช้วิธี Jdbc.getConnection เพื่อสร้างการเชื่อมต่อฐานข้อมูล

ดูข้อมูลเพิ่มเติมเกี่ยวกับเมธอด JDBC ได้ที่เอกสารประกอบ Java สำหรับ JDBC

สร้างฐานข้อมูล ผู้ใช้ และตาราง

นักพัฒนาซอฟต์แวร์ส่วนใหญ่ใช้เครื่องมือบรรทัดคำสั่ง MySQL เพื่อ สร้างฐานข้อมูล ผู้ใช้ และตาราง อย่างไรก็ตาม คุณสามารถทำสิ่งเดียวกันนี้ใน Apps Script ได้ ดังตัวอย่างต่อไปนี้ สร้างผู้ใช้รายอื่นอย่างน้อย 1 รายเพื่อให้สคริปต์ไม่ต้องเชื่อมต่อกับฐานข้อมูลในฐานะ 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);
  }
}

เขียนไปยังฐานข้อมูล

ตัวอย่างต่อไปนี้แสดงวิธีเขียนระเบียนเดียวลงในฐานข้อมูล รวมถึงระเบียน 500 รายการในชุด การประมวลผลเป็นชุดเป็นสิ่งสำคัญสำหรับการดำเนินการแบบกลุ่ม

ใช้คำสั่งที่มีพารามิเตอร์ ซึ่งจะระบุตัวแปรด้วย ? หากต้องการป้องกันการโจมตีด้วยการแทรก SQL ให้ใช้คำสั่งที่มีพารามิเตอร์เพื่อหลีกเลี่ยงข้อมูลทั้งหมดที่ผู้ใช้ระบุ

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);
  }
}

อ่านจากฐานข้อมูล

ตัวอย่างนี้แสดงวิธีอ่านระเบียนจำนวนมากจากฐานข้อมูล โดยวนซ้ำชุดผลลัพธ์ตามที่จำเป็น

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);
  }
}

Close connections

การเชื่อมต่อ JDBC จะปิดโดยอัตโนมัติเมื่อสคริปต์ทำงานเสร็จ (การเรียกใช้ google.script.run รายการเดียวจะถือเป็นการดำเนินการที่สมบูรณ์ แม้ว่าหน้าบริการ HTML ที่ทำการเรียกใช้จะยังเปิดอยู่ก็ตาม)

อย่างไรก็ตาม หากคุณทราบว่าการเชื่อมต่อ คำสั่ง หรือชุดผลลัพธ์เสร็จสิ้นแล้ว ก่อนสิ้นสุดสคริปต์ ให้ปิดด้วยตนเองโดยเรียกใช้ JdbcConnection.close JdbcStatement.close หรือ JdbcResultSet.close

การแสดงกล่องโต้ตอบการแจ้งเตือนหรือข้อความแจ้ง จะปิดการเชื่อมต่อ JDBC ที่เปิดอยู่ด้วย แต่องค์ประกอบ UI อื่นๆ ที่แสดง เช่น เมนูหรือกล่องโต้ตอบที่กำหนดเอง รวมถึงแถบด้านข้างที่มีเนื้อหาที่กำหนดเอง ไม่แสดง

Google, Google Workspace รวมถึงเครื่องหมายและโลโก้ที่เกี่ยวข้องเป็นเครื่องหมายการค้าของ Google LLC ชื่อบริษัทและชื่อผลิตภัณฑ์อื่นๆ ทั้งหมดเป็นเครื่องหมายการค้าของบริษัทที่เกี่ยวข้อง