JDBC

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

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

Google Cloud SQL 데이터베이스

Google Cloud SQL을 사용하면 Google 클라우드에 있는 관계형 데이터베이스를 만들 수 있습니다. 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 Console의 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에 대한 자바 문서를 참조하세요.

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

대부분의 개발자는 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의 상표입니다. 기타 모든 회사명 및 제품명은 해당 업체의 상표입니다.