Prepared Statements

Prepared Statements (준비된 구문)

prepared statement는 파라미터화된 쿼리예요. 쿼리는 쿼리의 파라미터를 나타내는 물음표(?)나 달러 기호($1)로 준비돼요. 그런 다음 이 파라미터에 값을 바인딩할 수 있고, 이후 그 파라미터들로 prepared statement를 실행할 수 있어요. 단일 쿼리는 한 번 준비되고 여러 번 실행될 수 있어요.

Prepared statements는 다음에 유용해요:

  • 문자열 연결/SQL 인젝션 공격을 피하면서 함수에 쉽게 파라미터를 공급.
  • 다른 파라미터로 여러 번 실행될 쿼리를 가속화.

출처: 문서

본문

DuckDB는 C API에서 duckdb_prepare 메서드로 prepared statements를 지원해요. duckdb_execute_prepared로 prepared statement의 후속 실행을 위해 값을 공급하는 데 duckdb_bind 함수 계열이 사용돼요. prepared statement 사용을 마친 뒤에는 duckdb_destroy_prepare 메서드로 정리할 수 있어요.

예시

duckdb_prepared_statement stmt;
duckdb_result result;
if (duckdb_prepare(con, "INSERT INTO integers VALUES ($1, $2)", &stmt) == DuckDBError) {
    // 오류 처리
}

duckdb_bind_int32(stmt, 1, 42); // 파라미터 인덱스는 1부터 세기 시작!
duckdb_bind_int32(stmt, 2, 43);
// 두 번째 파라미터로 NULL은 결과 집합을 요청하지 않음을 의미
duckdb_execute_prepared(stmt, NULL);
duckdb_destroy_prepare(&stmt);

// prepared statements로 결과 집합도 쿼리할 수 있음
if (duckdb_prepare(con, "SELECT * FROM integers WHERE i = ?", &stmt) == DuckDBError) {
    // 오류 처리
}
duckdb_bind_int32(stmt, 1, 42);
duckdb_execute_prepared(stmt, &result);

// 결과로 무언가 하기

// 정리
duckdb_destroy_result(&result);
duckdb_destroy_prepare(&stmt);

duckdb_prepare 호출 후 prepared statement 파라미터는 duckdb_nparamsduckdb_param_type으로 검사할 수 있어요. prepare가 실패하면 오류는 duckdb_prepare_error로 얻을 수 있어요.

duckdb_bind 함수 계열이 prepared statement 파라미터 타입과 정확히 일치할 필요는 없어요. 값은 필요에 따라 요구되는 값으로 자동 캐스트돼요. 예를 들어 DUCKDB_TYPE_INTEGER 파라미터 타입에 duckdb_bind_int8을 호출하면 예상대로 동작해요.

경고: DuckDB에 대량의 데이터를 삽입하는 데 prepared statements는 사용하지 마세요. 대신 [Appender]({% link docs/current/clients/c/appender.md %})를 사용하는 것이 좋아요.

API 참조 개요

duckdb_state duckdb_prepare(duckdb_connection connection, const char *query, duckdb_prepared_statement *out_prepared_statement);
void duckdb_destroy_prepare(duckdb_prepared_statement *prepared_statement);
const char *duckdb_prepare_error(duckdb_prepared_statement prepared_statement);
idx_t duckdb_nparams(duckdb_prepared_statement prepared_statement);
const char *duckdb_parameter_name(duckdb_prepared_statement prepared_statement, idx_t index);
duckdb_type duckdb_param_type(duckdb_prepared_statement prepared_statement, idx_t param_idx);
duckdb_logical_type duckdb_param_logical_type(duckdb_prepared_statement prepared_statement, idx_t param_idx);
duckdb_state duckdb_clear_bindings(duckdb_prepared_statement prepared_statement);
duckdb_statement_type duckdb_prepared_statement_type(duckdb_prepared_statement statement);
idx_t duckdb_prepared_statement_column_count(duckdb_prepared_statement prepared_statement);
const char *duckdb_prepared_statement_column_name(duckdb_prepared_statement prepared_statement, idx_t col_idx);
duckdb_logical_type duckdb_prepared_statement_column_logical_type(duckdb_prepared_statement prepared_statement, idx_t col_idx);
duckdb_type duckdb_prepared_statement_column_type(duckdb_prepared_statement prepared_statement, idx_t col_idx);

duckdb_prepare

쿼리에서 prepared statement 객체를 만들기.

duckdb_prepare 호출 후에는 prepare가 실패하더라도 prepared statement가 항상 duckdb_destroy_prepare로 파괴되어야 한다는 점을 주목해요.

prepare가 실패하면 duckdb_prepare_error를 호출해 실패 이유를 얻을 수 있어요.

문법
duckdb_state duckdb_prepare(
  duckdb_connection connection,
  const char *query,
  duckdb_prepared_statement *out_prepared_statement
);
파라미터
  • connection: 연결 객체
  • query: 준비할 SQL 쿼리
  • out_prepared_statement: 결과로 나온 prepared statement 객체
반환 값

성공 시 DuckDBSuccess, 실패 시 DuckDBError.


duckdb_destroy_prepare

prepared statement를 닫고 statement에 할당된 모든 메모리를 해제해요.

문법
void duckdb_destroy_prepare(
  duckdb_prepared_statement *prepared_statement
);
파라미터
  • prepared_statement: 파괴할 prepared statement.

duckdb_prepare_error

주어진 prepared statement와 연관된 오류 메시지를 반환해요. prepared statement에 오류 메시지가 없으면 nullptr을 반환해요.

오류 메시지를 해제해서는 안 됩니다. duckdb_destroy_prepare가 호출될 때 해제돼요.

문법
const char *duckdb_prepare_error(
  duckdb_prepared_statement prepared_statement
);
파라미터
  • prepared_statement: 오류를 얻을 prepared statement.
반환 값

오류 메시지, 또는 없으면 nullptr.


duckdb_nparams

주어진 prepared statement에 제공할 수 있는 파라미터 수를 반환해요.

쿼리가 성공적으로 준비되지 않았으면 0을 반환해요.

문법
idx_t duckdb_nparams(
  duckdb_prepared_statement prepared_statement
);
파라미터
  • prepared_statement: 파라미터 수를 얻을 prepared statement.

duckdb_parameter_name

파라미터를 식별하는 데 사용되는 이름을 반환해요. 반환된 문자열은 duckdb_free로 해제해야 해요.

제공된 prepared statement에서 인덱스가 범위를 벗어나면 NULL을 반환해요.

문법
const char *duckdb_parameter_name(
  duckdb_prepared_statement prepared_statement,
  idx_t index
);
파라미터
  • prepared_statement: 파라미터 이름을 얻을 prepared statement.

duckdb_param_type

주어진 인덱스의 파라미터에 대한 파라미터 타입을 반환해요.

파라미터 인덱스가 범위를 벗어나거나 statement가 성공적으로 준비되지 않았으면 DUCKDB_TYPE_INVALID를 반환해요.

문법
duckdb_type duckdb_param_type(
  duckdb_prepared_statement prepared_statement,
  idx_t param_idx
);
파라미터
  • prepared_statement: prepared statement.
  • param_idx: 파라미터 인덱스.
반환 값

파라미터 타입


duckdb_param_logical_type

주어진 인덱스의 파라미터에 대한 논리 타입을 반환해요.

파라미터 인덱스가 범위를 벗어나거나 statement가 성공적으로 준비되지 않았으면 nullptr을 반환해요.

이 호출의 반환 타입은 duckdb_destroy_logical_type으로 파괴해야 해요.

문법
duckdb_logical_type duckdb_param_logical_type(
  duckdb_prepared_statement prepared_statement,
  idx_t param_idx
);
파라미터
  • prepared_statement: prepared statement.
  • param_idx: 파라미터 인덱스.
반환 값

파라미터의 논리 타입


duckdb_clear_bindings

prepared statement에 바인딩된 파라미터를 지워요.

문법
duckdb_state duckdb_clear_bindings(
  duckdb_prepared_statement prepared_statement
);

duckdb_prepared_statement_type

실행될 statement의 statement 타입을 반환해요

문법
duckdb_statement_type duckdb_prepared_statement_type(
  duckdb_prepared_statement statement
);
파라미터
  • statement: prepared statement.
반환 값

duckdb_statement_type 값 또는 DUCKDB_STATEMENT_TYPE_INVALID


duckdb_prepared_statement_column_count

prepared statement 결과에 존재하는 컬럼 수를 반환해요. 컬럼 타입 중 하나라도 유효하지 않으면 결과는 1이에요.

문법
idx_t duckdb_prepared_statement_column_count(
  duckdb_prepared_statement prepared_statement
);
파라미터
  • prepared_statement: prepared statement.
반환 값

prepared statement 결과에 존재하는 컬럼 수.


duckdb_prepared_statement_column_name

prepared_statement의 결과에서 지정된 컬럼의 이름을 반환해요. 반환된 문자열은 duckdb_free로 해제해야 해요.

컬럼이 범위를 벗어나면 nullptr을 반환해요.

문법
const char *duckdb_prepared_statement_column_name(
  duckdb_prepared_statement prepared_statement,
  idx_t col_idx
);
파라미터
  • prepared_statement: prepared statement.
  • col_idx: 컬럼 인덱스.
반환 값

지정된 컬럼의 이름.


duckdb_prepared_statement_column_logical_type

prepared_statement의 결과에서 지정된 컬럼의 컬럼 타입을 반환해요.

컬럼이 범위를 벗어나면 DUCKDB_TYPE_INVALID를 반환해요. 이 호출의 반환 타입은 duckdb_destroy_logical_type으로 파괴해야 해요.

문법
duckdb_logical_type duckdb_prepared_statement_column_logical_type(
  duckdb_prepared_statement prepared_statement,
  idx_t col_idx
);
파라미터
  • prepared_statement: 컬럼 타입을 가져올 prepared statement.
  • col_idx: 컬럼 인덱스.
반환 값

지정된 컬럼의 논리 타입.


duckdb_prepared_statement_column_type

prepared_statement의 결과에서 지정된 컬럼의 컬럼 타입을 반환해요.

컬럼이 범위를 벗어나면 DUCKDB_TYPE_INVALID를 반환해요.

문법
duckdb_type duckdb_prepared_statement_column_type(
  duckdb_prepared_statement prepared_statement,
  idx_t col_idx
);
파라미터
  • prepared_statement: 컬럼 타입을 가져올 prepared statement.
  • col_idx: 컬럼 인덱스.
반환 값

지정된 컬럼의 타입.


더 알아보기 (Learn more)

파라미터 바인딩 함수들의 전체 목록은 [C API]({% link docs/current/clients/c/api.md %}) 문서를 참고해요.