JDBC

Apps Script는 표준 Java 데이터베이스 연결 기술을 둘러싸는 래퍼인 JDBC 서비스를 통해 외부 데이터베이스에 연결할 수 있습니다. JDBC 서비스는 MySQL용 Google Cloud SQL, MySQL, Microsoft SQL Server, Oracle 데이터베이스를 지원합니다.

JDBC로 외부 데이터베이스를 업데이트하려면 스크립트에서 데이터베이스 연결을 연 다음 SQL 문을 전송하여 변경해야 합니다.

Google Cloud SQL 데이터베이스

Google Cloud SQL을 사용하면 Google Cloud에 상주하는 관계형 데이터베이스를 만들 수 있습니다. Cloud SQL은 사용량에 따라 요금이 청구될 수 있습니다.

Cloud SQL 빠른 시작에 나와 있는 단계에 따라 Google Cloud SQL 인스턴스를 만들 수 있습니다.

Google Cloud SQL 연결 만들기

Apps Script의 JDBC 서비스를 사용하여 Google Cloud SQL 데이터베이스와 연결하는 방법에는 두 가지가 있습니다.

이러한 방법은 아래에 설명되어 있습니다. 두 방법 모두 유효하지만 두 번째 방법을 사용하려면 데이터베이스에 액세스할 수 있는 IP 범위 세트를 승인해야 합니다.

이 메서드는 Jdbc.getCloudSqlConnection(url) 메서드를 사용하여 Google Cloud SQL MySQL 인스턴스에 대한 연결을 만듭니다. 데이터베이스 URL은 jdbc:google:mysql://subname 형식이며 여기서 subnameGoogle Cloud 콘솔의 Cloud SQL 인스턴스 개요 페이지에 나열된 MySQL 인스턴스 연결 이름입니다.

Cloud SQL SQL Server에 연결하려면 Jdbc.getConnection(url)을 참고하세요.

Jdbc.getConnection(url) 사용

이 메서드를 사용하려면 Apps Script의 서버가 데이터베이스에 연결할 수 있도록 특정 클래스 없는 도메인 간 라우팅 (CIDR) IP 주소 범위를 승인해야 합니다. 스크립트를 실행하기 전에 다음 단계를 완료합니다.

  1. Google Cloud SQL 인스턴스에서 이 데이터 소스에서 한 번에 하나씩 IP 범위를 승인합니다.

  2. 데이터베이스에 할당된 URL을 복사합니다. URL 형식은 jdbc:mysql:subname입니다.

이러한 IP 범위를 승인하면 Jdbc.getConnection(url) 메서드 중 하나와 위에서 복사한 URL을 사용하여 Google Cloud SQL 인스턴스에 대한 연결을 만들 수 있습니다.

기타 데이터베이스

자체 MySQL, Microsoft SQL Server 또는 Oracle 데이터베이스가 이미 있는 경우 Apps Script의 JDBC 서비스를 통해 연결할 수 있습니다.

다른 데이터베이스 연결 만들기

Apps Script JDBC 서비스를 사용하여 데이터베이스 연결을 만들려면 데이터베이스 설정에서 이 데이터 소스의 IP 범위를 승인해야 합니다.

이러한 허용 목록이 설정되면 Jdbc.getConnection(url) 메서드 중 하나와 데이터베이스의 URL을 사용하여 데이터베이스 연결을 만들 수 있습니다.

샘플 코드

아래 샘플 코드는 Google Cloud SQL 데이터베이스에 연결한다고 가정하고 Jdbc.getCloudSqlConnection(url) 메서드를 사용하여 데이터베이스 연결을 만듭니다. 다른 데이터베이스의 경우 Jdbc.getConnection(url) 메서드를 사용하여 데이터베이스 연결을 만들어야 합니다.

JDBC 메서드에 관한 자세한 내용은 JDBC용 Java 문서를 참고하세요.

데이터베이스, 사용자, 테이블 만들기

대부분의 개발자는 MySQL 명령줄 도구를 사용하여 데이터베이스, 사용자, 테이블을 만듭니다. 하지만 아래와 같이 Apps Script에서도 동일한 작업을 할 수 있습니다. 스크립트가 항상 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);
  }
}

데이터베이스에서 읽기

이 예에서는 필요에 따라 결과 집합을 반복하여 데이터베이스에서 많은 수의 레코드를 읽는 방법을 보여줍니다.

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

연결 닫기

스크립트 실행이 완료되면 JDBC 연결이 자동으로 닫힙니다. 호출을 실행한 HTML 서비스 페이지가 열려 있어도 단일 google.script.run 호출은 전체 실행으로 간주됩니다.

하지만 스크립트가 끝나기 전에 연결, 문이, 결과 집합이 완료되었다는 것을 알고 있다면 JdbcConnection.close(), JdbcStatement.close() 또는 JdbcResultSet.close()를 호출하여 수동으로 닫는 것이 좋습니다.

알림 또는 메시지 대화상자를 표시하면 열려 있는 JDBC 연결도 종료됩니다. 하지만 맞춤 메뉴나 대화상자, 맞춤 콘텐츠가 포함된 사이드바와 같은 다른 표시 UI 요소는 영향을 받지 않습니다.

​Google, Google Workspace 및 관련 마크와 로고는 Google LLC의 상표입니다. 기타 모든 회사명 및 제품명은 해당 업체의 상표입니다.​