JDBC

컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.

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

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

Google Cloud SQL 데이터베이스

Google Cloud SQL을 사용하면 Google 클라우드에 위치한 관계형 데이터베이스를 만들 수 있습니다. Apps Script와 달리 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 Platform Console의 Cloud SQL 인스턴스 개요 페이지에 나열된 MySQL 인스턴스 연결 이름입니다.

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

Jdbc.getConnection(url)을 사용합니다.

이 방법을 사용하려면 Apps Scripts 서버가 데이터베이스에 연결할 수 있도록 특정 CIDR IP 주소 범위를 허용해야 합니다. 스크립트를 실행하기 전에 다음 단계를 완료하세요.

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

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

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

기타 데이터베이스

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

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

JDBC 서비스를 사용하여 데이터베이스 연결을 만들려면 Apps Script가 액세스할 수 있도록 데이터베이스 설정에서 특정 IP 범위를 허용해야 합니다. 다음은 허용 목록에 필요한 IP 주소 범위입니다.

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

샘플 코드

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

JDBC 메서드에 대한 자세한 내용은 JDBC용 자바 문서를 참조하세요.

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

대부분의 개발자는 MySQL 명령줄 도구를 사용하여 데이터베이스, 사용자, 테이블을 만듭니다. 하지만 Apps Script에서는 아래와 같이 동일한 작업을 수행할 수 있습니다. 스크립트가 항상 root과(와) 데이터베이스에 연결하지 않도록 다른 사용자를 한 명 이상 만드는 것이 좋습니다.

서비스/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
    Logger.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
    Logger.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
    Logger.log('Failed with an error %s', err.message);
  }
}

데이터베이스에 쓰기

아래 예시는 한 개의 레코드와 500개의 레코드 배치를 데이터베이스에 쓰는 방법을 보여줍니다. 일괄 처리는 일괄 작업에 필수적입니다.

또한 매개변수가 ?로 표시되는 매개변수화된 문도 사용합니다. SQL 삽입을 방지하려면 매개변수화된 문을 사용하여 사용자가 제공한 모든 데이터를 이스케이프해야 합니다.

서비스/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
    Logger.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();
    Logger.log('Time elapsed: %sms for %s rows.', end - start, batch.length);
  } catch (err) {
    // TODO(developer) - Handle exception from the API
    Logger.log('Failed with an error %s', err.message);
  }
}

데이터베이스에서 읽기

이 예에서는 필요에 따라 결과 세트를 루프 처리하여 데이터베이스에서 많은 수의 레코드를 읽는 방법을 보여줍니다.

서비스/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';
      }
      Logger.log(rowString);
    }

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

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

연결 닫기

스크립트 실행이 완료되면 JDBC 연결이 자동으로 종료됩니다. 호출한 HTML 서비스 페이지가 열려 있는 경우에도 단일 google.script.run 호출이 완전 실행으로 집계된다는 점에 유의하세요.

그럼에도 불구하고 스크립트가 끝나기 전에 연결, 문 또는 결과 집합을 알고 있다면 JdbcConnection.close()JdbcStatement.close() 또는 JdbcResultSet.close()을 호출하여 수동으로 닫는 것이 좋습니다.

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