콘텐츠로 이동

3.LOB 인터페이스#

이 장에서는 CLI에서 LOB 데이터를 처리하는 방식과 LOB 데이터를 처리하는 데 필요한 데이터 타입과 관련 함수를 설명한다.

LOB 데이터 처리 방식#

Altibase는 CLI에서 LOB데이터를 처리하기위해 LOB 위치 입력기(LOB Locator)를 이용한다. LOB Locator는 LOB 데이터에 대응되는 고유값으로 Altibase 서버의 내부 자료구조이다. LOB 데이터를 연산하기 위해서는 먼저 LOB Locator를 획득해야 하며, 이를 통해 LOB 데이터를 읽거나 쓸 수 있다. LOB Locator는 MVCC와 관련하여 특정 시점의 LOB 데이터를 가리키기 때문에, LOB Locator를 발생시킨 트랜잭션과 생명주기를 같이하며, 그 트랜잭션에 종속된다.

자동 커밋 모드 해제#

LOB 위치 입력기는 트랜잭션에 종속적이기 때문에 CLI에서 LOB 위치 입력기를 이용하여 LOB 데이터를 처리하려면 반드시 자동 커밋 모드를 해제해야 한다.

자동 커밋 모드를 해제하면 LOB 위치 입력기를 얻어오는 CLI 함수와 LOB 데이터를 읽고 쓰는 CLI 함수는 하나의 트랜잭션내에서 개별 작업으로 동작되어 LOB 위치 입력기를 공유할 수 있다. 반면, 자동 커밋 모드에서는 각각의 개별 트랜잭션으로 동작하기 때문에 두 트랜잭션 간에 LOB 위치 입력기를 공유할 수 없다.

LOB 위치 입력기를 이용한 트랜잭션 커밋 시 주의사항

  1. 자동 커밋 해제 모드에서 LOB 데이터를 읽고 쓰는 CLI 함수 수행 중 예상치 못한 에러가 발생하면, 내부적으로 초기화된 데이터가 남아 있을 수 있어 반드시 트랜잭션을 롤백해야 한다.
  2. NOT NULL 제약이 있는 LOB 타입 컬럼에 NULL 값을 INSERT 혹은 UPDATE 수행하면 [Unable to insert (or update) NULL into NOT NULL column.] 에러가 발생한다. 이 경우 초기화된 데이터가 남아 있어 반드시 트랜잭션을 롤백해야 한다.

LOB 위치 입력기 얻기#

LOB 위치 입력기는 아래의 CLI 함수들을 실행할 때 얻는다.

  • SQLBindCol / SQLFetch

  • SQLBindParameter / SQLExecute

⚠️ SQLExecute 함수는 INSERT와 UPDATE 문을 실행할 때 LOB 데이터를 초기화하는데, NOT NULL 제약이 없는 경우 널(NULL)로 초기화 한다. 반면, NOT NULL 제약이 있는 경우는 Empty로 초기화한다.

LOB 데이터 읽고 쓰기#

LOB 위치 입력기를 얻은 후에 이것을 이용하여 LOB 데이터를 읽거나 쓸 수 있다. 관련 CLI 함수는 아래와 같다.

  • SQLBindFileToParam
  • SQLGetLob
  • SQLGetLobLength
  • SQLPutLob
  • SQLTrimLob

LOB 데이터의 조회(SELECT)#

LOB 데이터를 SELECT 할때, 내부적으로는 LOB Locator를 얻어와서 처리되기 때문에 연관된 트랜잭션이 열린 상태가 된다. 따라서 사용자는 명시적으로 commit 또는 rollback과 같은 트랜잭션 종료 작업을 추가로 해주어야 한다.

[!CAUTION]

만약, 사용자가 명시적으로 commit 또는 rollback 과 같은 트랜잭션 종료 작업을 하지 않으면, 데이터베이스의 메모리 사용량이 증가할 수 있다.

자원 해제하기#

LOB 데이터와 관련한 작업이 완료된 경우, 관련된 자원을 해제해주어야 한다. 관련 CLI 함수는 아래와 같다.

SQLFreeLob 함수는 Lob Locator와 관련된 자원을 해제할 뿐, 트랜잭션을 종료하지는 않는다.

LOB 데이터 타입#

LOB 데이터 타입을 처리하는데 사용되는 SQL 데이터 타입과 C 데이터 타입을 소개한다.

LOB 데이터 타입 제약 사항#

CLI에서 LOB 데이터를 사용하기 전에 먼저 Altibase의 LOB 데이터 타입에 대한 기본적인 제약 사항을 General Reference에서 확인한다.

SQL 데이터 타입#

다음은 LOB 데이터 타입을 지원하는 SQL 데이터 타입의 식별자이다.

SQL 식별자 Altibase 데이터 타입 설명
SQL_BLOB BLOB BLOB은 가변 길이를 가지는 이진 데이터 타입
SQL_CLOB CLOB CLOB은 가변 길이를 가지는 데이터 타입

[표 3‑1] LOB 데이터 타입을 지원하는 SQL 데이터 타입의 식별자

C 데이터 타입#

다음 표는 LOB 데이터 타입을 지원하는 C 데이터 타입의 식별자이다. 각 식별자에 해당하는 ODBC의 C 데이터 타입과 이 데이터 타입의 정의를 나열한다.

CLOB 데이터는 SQL_C_CHAR를, BLOB 데이터는 SQL_C_BINARY를 사용하여 사용자 변수를 바인딩한다.

SQL_C_CLOB_LOCATOR와 SQL_C_BLOB_LOCATOR는 LOB 위치 입력기를 얻을 때 사용한다.

C 타입 식별자 Altibase 데이터 타입 ODBC C 타입 C 타입 정의
SQL_C_BINARY BLOB SQLCHAR * unsigned char *
SQL_C_CHAR CLOB SQLSCHAR * char *
SQL_C_BLOB_LOCATOR SQLUBIGINT unsigned _int64
SQL_C_CLOB_LOCATOR SQLUBIGINT unsigned _int64

[표 3‑2] LOB 데이터 타입을 지원하는 C 데이터 타입의 식별자

C 타입 식별자로 SQL_C_BLOB, SQL_C_CLOB은 지원하지 않는다.

64비트 정수형의 이름은 플랫폼에 따라 다르다. 위 표에서 사용한 _int64는 일부 플랫폼에서 사용되는 64비트 정수형의 이름이다.

LOB Function Overview#

LOB 데이터를 다루기 위해서 사용되는 함수들은 아래와 같다.

  1. SQLBindFileToCol() (비표준)
    Full Retrieve

  2. SQLBindFileToParam() (비표준)
    Full Insert, Full Update

  3. SQLGetLobLength() (비표준)
    LOB 데이터의 길이를 구한다.

  4. SQLGetLob() (비표준)
    Partial Retrieve

  5. SQLPutLob() (비표준)
    Partial Insert, Partial Update, Partial Delete

  6. SQLFreeLob() (비표준)
    사용중이던 LOB locator를 해제

  7. SQLGetData(), SQLPutData() (표준)
    Full Retrieve/Update

  8. 여타 ODBC 의 모든 표준 함수들

위 함수 중 1 \~ 6번은 Altibase가 LOB을 다루기 위해 제공하는 특수 함수들로써, ODBC 표준에는 없는 함수들이다.

7, 8번과 같이 ODBC API에서 정의하는 함수들을 이용해서 데이터베이스의 칼럼 타입이 LOB 인지의 여부에 무관하게 표준 함수만으로도 LOB 데이터에 접근할 수 있다. 단, ODBC 표준 함수만을 사용했을 경우, 부분 갱신(partial update), 부분 검색(partial retrieve) 등의 기능은 사용할 수 없다.

만약 사용자가 ODBC driver manager를 이용해서 프로그래밍하고자 하면, odbc.ini 파일에 다음과 같은 항목을 추가해야 한다.

LongDataCompat = yes또는
LongDataCompat = on

위의 항목을 odbc.ini 파일에 추가했을 경우, SQL_BLOB, SQL_CLOB 과 같은 타입은 각각 SQL_LONGVARBINARY, SQL_LONGVARCHAR 와 같은 타입으로 변환되어서 사용자에게 전달된다. 따라서 ODBC driver manager를 사용하더라도 투명하게 LOB 데이터를 다룰 수 있다.

SQLBindFileToCol#

BLOB 또는 CLOB 데이터 타입에 대해 파일 또는 파일들을 결과 집합의 열에 바인드한다.

구 문#

SQLRETURN SQLBindFileToCol(
    SQLHSTMT          stmt,
    SQLSMALLINT       col,
    SQLCHAR *         fileName,
    SQLLEN *          fileNameLength,
    SQLUINTEGER *     fileOptions,
    SQLLEN            fileNameBufferSize,
    SQLLEN *          valueLength);

인 자#

자료유형 인자 사용 설명
SQLHSTMT stmt 입력 검색된 결과들에 대한 명령문 핸들
SQLSMALLINT col 입력 바인드할 결과 집합에서의 칼럼의 순서로 1부터 시작.
SQLCHAR * filename 입력 (유예중) 파일 이름 또는 파일 이름의 배열을 저장할 버퍼를 가리키는 포인터로 NULL일 수 없다. SQLFetch() 시 이 버퍼에 파일 이름이 저장되어 있어야 하며, SQLFetch()는 이 파일 또는 파일들에 데이터를 반환한다. 절대 경로(권장)와 상대 경로 모두 가능하다.
SQLLEN * fileNameLength 입력 (유예중) 파일 이름의 길이 또는 길이의 배열을 저장할 버퍼를 가리키는 포인터. SQLFetch() 시 이 버퍼에 파일 이름의 길이가 저장되어 있어야 한다. 본 인자가 NULL일 경우 파일 이름을 NULL 종결 문자열로 간주한다. 즉, SQL_NTS를 본 인자가 가리키는 메모리에 저장시켜 두고 사용하는 것과 같다. 파일 이름의 최대 길이는 255이다.
SQLUINTEGER * fileOptions 입력 (유예중) 파일 옵션 또는 옵션의 배열을 저장할 버퍼를 가리키는 포인터. SQLFetch() 시 이 버퍼에 파일 옵션이 저장되어 있어야 한다. 다음의 옵션이 가능하다. SQL_FILE_CREATE는 파일이 없을 경우 생성하고, 파일이 있을 경우 SQL_ERROR를 리턴한다. SQL_FILE_OVERWRITE는 파일이 없을 경우 생성하고, 파일이 있을 경우 파일을 덮어쓴다. SQL_FILE_APPEND는 파일이 없을 경우 생성하고, 파일이 있을 경우 파일 뒤에 덧붙여 쓴다. 위 옵션 중 한 개만 선택 가능하며, 디폴트 옵션은 정의되어있지 않다. 본 인자는 NULL일 수 없다.
SQLLEN fileNameBufferSize 입력 fileName 버퍼의 길이를 설정한다.
SQLLEN * valueLength 출력 (유예중) 지시자 변수 또는 지시자 변수의 배열을 저장할 버퍼를 가리키는 포인터로 NULL일 수 없다. 파일에 저장된 데이터의 길이를 반환하거나, LOB이 NULL임을 반환하기 위해 사용된다. SQLFetch()는 이 포인터가 가리키는 버퍼에 다음 값을 반환할 수 있다. 1. 데이터 길이, 2. SQL_NULL_DATA.

결과값#

SQL_SUCCESS
SQL_SUCCESS_WITH_INFO
SQL_INVALID_HANDLE
SQL_ERROR

설 명#

SQLBindFileToCol()은 결과 집합의 LOB 데이터를 파일로 바인드하며, SQLBindCol()은 애플리케이션 변수(메모리 버퍼)에 바인드한다.

SQLBindFileToCol() 호출 후 SQLFetch()가 호출되면, DBMS의 LOB 데이터가 파일로 저장되며, valueLength 포인터가 가리키는 버퍼에는 파일에 저장된 데이터의 길이 (바이트 단위) 가 저장된다. 만약, LOB이 NULL일 경우 valueLength 포인터가 가리키는 버퍼에는 SQL_NULL_DATA가 저장된다. fileName, fileNameLength, fileOptions 인자의 값은 SQLFetch() 시 참조되며, 인자의 오류 여부도 FETCH시 보고된다.

FETCH 시 한 번에 여러 개의 LOB을 파일로 가져오는 경우, fileName, fileNameLength, fileOptions, valueLength 인자는 모두 배열이어야 한다.

진 단#

SQLSTATE 설명 부연설명
08S01 통신 회선 장애 (데이터 송수신 실패) Altibase CLI 드라이버와 DB간에 함수 처리가 완료되기 전에 통신 회선 실패
HY000 일반 오류

관련함수#

SQLBindCol
SQLBindFileToParam
SQLDescribeCol
SQLFetch

예 제#

테이블은 다음 DDL에 의해 생성되었다고 가정한다.

CREATE TABLE T1 (i1 INTEGER PRIMARY KEY, i2 BLOB);
한 개의 LOB을 파일에 쓰기#
SQLCHAR fileName[16];
SQLLEN fileNameLength = 15;
SQLUINTEGER fileOptions = SQL_FILE_CREATE;
SQLLEN valueLength;
.
strcpy(query, "SELECT i2 FROM T1 WHERE i1=1");
if (SQLPrepare(stmt, query, SQL_NTS) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, “SQLPrepare : ”);
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

/* Select의 결과값을 가져올 파일 지정 */
strcpy(fileName, "Terminator2.avi");
if (SQLBindFileToCol(stmt, 1, fileName, &fileNameLength, &fileOptions, 16, &valueLength) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, “SQLBindFileToCol : “);
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

if (SQLExecute(stmt) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLExecute : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

if (SQLFetch(stmt) == SQL_SUCCESS)
{
    printf("SQLFetch success!!!\n");
}
else
{
    execute_err(dbc, stmt, “SQLFetch : “);
}
세 개의 LOB을 파일에 쓰기#
SQLCHAR fileName[3][10];
SQLLEN fileNameLength[3];
SQLUINTEGER fileOptions[3];
SQLLEN valueLength[3];
.
.
.
if (SQLSetStmtAttr(stmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) 3, 0) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLSetStmtAttr : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

if (SQLSetStmtAttr(stmt, SQL_ATTR_ROW_BIND_TYPE, SQL_BIND_BY_COLUMN, 0) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLSetStmtAttr : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

strcpy(query, "SELECT i2 FROM T1 WHERE i1 >= 1 AND i1 <= 3");

if (SQLExecDirect(stmt, query, SQL_NTS) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLExecDirect : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

/* Select의 결과값을 가져올 파일 지정 */
strcpy(fileName[0], "Cube.avi");
strcpy(fileName[1], "Movie.avi");
strcpy(fileName[2], "Term.avi");

for (i = 0; i < 3; i++)
{
    fileNameLength[i] = strlen(fileName[i]);
    fileOptions[i] = SQL_FILE_CREATE;
}

if (SQLBindFileToCol(stmt, 1, (SQLCHAR *) fileName, fileNameLength, fileOptions, 10, valueLength) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, “SQLBindFileToCol : “);
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

if (SQLFetch(stmt) == SQL_SUCCESS)
{
    printf("SQLFetch success!!!\n");
}
else
{
    execute_err(dbc, stmt, “SQLFetch : “);
n개의 LOB을 파일에 쓰기#
SQLCHAR fileName[11];
SQLLEN fileNameLength = 10;
SQLUINTEGER fileOptions = SQL_FILE_OVERWRITE;
SQLLEN valueLength;
.
strcpy(query, "SELECT i2 FROM T1");

if (SQLExecDirect(stmt, query, SQL_NTS) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLExecDirect : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

if (SQLBindFileToCol(stmt, 1, fileName, &fileNameLength, &fileOptions, 11, &valueLength) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLBindFileToCol : “);
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

for (i = 0; ; i++)
{
    sprintf(fileName, "Term%02d.avi", i + 1);

    rc = SQLFetch(stmt);
    if (rc == SQL_SUCCESS)
    {
        printf("SQLFetch of file[%02] success!!!\n", i + 1);
    }
    else if (rc == SQL_NO_DATA)
    {
        break;
    }
    else
    {
        execute_err(dbc, stmt, "SQLFetch : ");
        break;
    }
}

SQLBindFileToParam#

SQL 문에서 LOB 데이터 타입을 위해 사용된 매개변수 마커 ‘?’를 파일 또는 파일들에 바인드시킨다. SQLExecute() 또는 SQLExecDirect()가 호출될 때 자료가 파일에서 데이터베이스 관리 시스템으로 전송된다.

구 문#

SQLRETURN SQLBindFileToParam(
    SQLHSTMT         stmt,
    SQLSMALLINT      par,
    SQLSMALLINT      sqlType,
    SQLCHAR *        fileName,
    SQLLEN *         fileNameLength,
    SQLUINTEGER *    fileOptions,
    SQLLEN           maxFileNameLength,
    SQLLEN *         ind);

인 자#

자료유형 인자 사용 설명
SQLHSTMT stmt 입력 검색된 결과들에 대한 명령문 핸들
SQLSMALLINT Par 입력 매개변수의 순서. 1부터 시작.
SQLSMALLINT sqlType 입력 매개변수의 SQL 데이터 타입. 다음과 같은 값을 설정할 수 있다. SQL_BLOB SQL_CLOB
SQLCHAR * fileName 입력 (유예중) 파일 이름 또는 파일 이름의 배열을 저장할 버퍼를 가리키는 포인터. SQLExecute() 또는 SQLExecDirect() 시 이 버퍼에 파일 이름이 저장되어 있어햐 한다. 절대 경로(권장)와 상대 경로 모두 가능하다. 본 인자는 NULL일 수 없다.
SQLLEN * fileNameLength 입력 (유예중) 파일 이름의 길이 또는 길이의 배열을 저장할 버퍼를 가리키는 포인터. SQLExecute() 또는 SQLExecDirect() 시 이 버퍼에 파일 이름의 길이가 저장되어 있어야 한다. 본 인자가 NULL일 경우 파일 이름을 NULL 종결 문자열로 간주한다. 즉, SQL_NTS를 본 인자가 가리키는 메모리에 저장시켜 두고 사용하는 것과 같다. 파일 이름의 최대 길이는 255이다.
SQLUINTEGER * fileOptions 입력 (유예중) 파일 옵션 또는 옵션의 배열을 저장할 버퍼를 가리키는 포인터로 NULL일 수 없다 SQLExecute() 또는 SQLExecDirect() 시 이 버퍼에 파일 옵션이 저장되어 있어햐 한다. 다음과 같은 옵션이 가능하다: SQL_FILE_READ.
SQLLEN fileNameBufferSize 입력 filename의 버퍼 길이를 설정한다.
SQLLEN * Ind 입력 (유예중) 지시자 변수 또는 지시자 변수의 배열을 저장할 버퍼를 가리키는 포인터로 NULL일 수 없다 LOB의 NULL 여부를 지정하기 위해 사용된다. 이 포인터가 가리키는 버퍼에는 다음과 같은 값을 설정할 수 있다. 0, SQL_NULL_DATA.

결과값#

SQL_SUCCESS
SQL_SUCCESS_WITH_INFO
SQL_INVALID_HANDLE
SQL_ERROR

설 명#

SQLBindFileToParam()은 LOB 매개변수 마커를 파일에 바인드시킨다. 매개변수 마커를 애플리케이션 변수(메모리 버퍼)에 바인드시키고 싶을 경우, SQLBindParameter()를 사용하면 된다. SQLBindFileToParam(), SQLBindParameter() 중 어느 것이든 가장 최근에 호출한 바인드 함수에 의한 바인딩만 유효하게 된다.

fileName, fileNameLength, fileOptions, ind 인자의 값은 SQLExecute() 또는 SQLExecDirect() 시 참조되므로 SQLExecute() 또는 SQLExecDirect() 호출 전에 값을 설정해주어야 한다. SQLExecute() 또는 SQLExecDirect()가 호출되면, 데이터가 바인드된 파일로부터 읽혀 DBMS로 전송된다.

LOB이 NULL일 경우 ind 포인터가 가리키는 버퍼에 SQL_NULL_DATA를 설정한 후 SQLExecute() 또는 SQLExecDirect()를 호출한다. 만약, LOB이 NULL이 아닐 경우 ind 포인터가 가리키는 버퍼에는 0을 설정해야 한다. ind 인자는 NULL 포인터여서는 안된다.

파일의 배열을 한 매개변수 마커에 바인드하는 경우, fileName, fileNameLength, fileOptions, ind 인자는 모두 배열이어야 한다.

진 단#

SQLSTATE 설명 부연설명
08S01 통신 회선 장애 (데이터 송수신 실패) Altibase CLI 드라이버와 DB간에 함수 처리가 완료되기 전에 통신 회선 실패
HY000 일반 오류

관련함수#

SQLBindCol
SQLBindFileToCol
SQLExecute
SQLExecDirect
SQLDescribeParam

예 제#

테이블은 다음 DDL에 의해 생성되었다고 가정한다.
CREATE TABLE T1 (i1 INTEGER PRIMARY KEY, i2 BLOB);
한 개의 LOB을 테이블에 입력#
SQLCHAR fileName[16];
SQLLEN fileNameLength = 15;
SQLUINTEGER fileOptions = SQL_FILE_READ;
SQLLEN ind = 0;
.
strcpy(query, "INSERT INTO T1 VALUES (1, ?)");

/* Statement를 준비하고 파일을 바인드한다. */
if (SQLPrepare(stmt, query, SQL_NTS) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, “SQLPrepare : ”);
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

strcpy(fileName, "Terminator2.avi");
if (SQLBindFileToParam(stmt, 1, SQL_BLOB, fileName, &fileNameLength, &fileOptions, 16, &ind) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, “SQLBindFileToParam : “);
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

if (SQLExecute(stmt) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLExecute : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}
세 개의 LOB을 테이블에 입력#
SQLINTEGER i1[3];
SQLCHAR fileName[3][10];
SQLLEN fileNameLength[3];
SQLUINTEGER fileOptions[3];
SQLLEN ind[3];
.
if (SQLSetStmtAttr(stmt, SQL_ATTR_PARAMSET_SIZE, (SQLPOINTER) 3, 0) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLSetStmtAttr : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

if (SQLSetStmtAttr(stmt, SQL_ATTR_PARAM_BIND_TYPE, SQL_PARAM_BIND_BY_COLUMN, 0) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLSetStmtAttr : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

strcpy(query, "INSERT INTO T1 VALUES (?, ?)");

/* Statement를 준비하고 파일을 바인드한다. */
if (SQLPrepare(stmt, query, SQL_NTS) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, “SQLPrepare : ”);
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

if (SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_INTEGER, SQL_INTEGER, 0, 0, (SQLPOINTER) i1, 0, NULL) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, “SQLBindParameter : “);
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

if (SQLBindFileToParam(stmt, 2, SQL_BLOB, (SQLCHAR *) fileName, fileNameLength, fileOptions, 10, ind) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, “SQLBindFileToParam : “);
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

/* Insert할 데이터를 가져올 파일 지정 */
strcpy(fileName[0], "Cube.avi");
strcpy(fileName[1], "Movie.avi");
strcpy(fileName[2], "Term.avi");

for (i = 0; i < 3; i++)
{
    i1[i] = i + 1;
    fileNameLength[i] = strlen(fileName[i]);
    fileOptions[i] = SQL_FILE_READ;
    ind[i] = 0;
}

if (SQLExecute(stmt) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLExecute : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}
테이블의 한 개의 LOB을 업데이트#
SQLCHAR fileName[16];
SQLLEN fileNameLength = 15;
SQLUINTEGER fileOptions = SQL_FILE_READ;
SQLLEN ind = 0;
.
strcpy(query, "UPDATE T1 SET i2=? WHERE i1=1");

/* Statement를 준비하고 파일을 바인드한다. */
if (SQLPrepare(stmt, query, SQL_NTS) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, “SQLPrepare : ”);
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

strcpy(fileName, "Terminator2_fix.avi");
if (SQLBindFileToParam(stmt, 1, SQL_BLOB, fileName, &fileNameLength, &fileOptions, 16, &ind) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, “SQLBindFileToParam : “);
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

if (SQLExecute(stmt) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLExecute : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

SQLGetLobLength#

현재의 트랜잭션 도중에 얻어진 LOB Locator가 가리키는 LOB 의 길이를 얻어온다.

구 문#

SQLRETURN SQLGetLobLength(
    SQLHSTMT         stmt,
    SQLUBIGINT       locator,
    SQLSMALLINT      locatorCType,
    SQLUINTEGER *    valueLength);

인 자#

자료유형 인자 사용 설명
SQLHSTMT stmt 입력 검색된 결과들에 대한 명령문 핸들
SQLUBIGINT locator 입력 LOB Locator
SQLSMALLINT locatorCType 입력 LOB Locator 의 C 데이터타입 식별자로 다음의 값을 가질 수 있다. SQL_C_BLOB_LOCATOR SQL_C_CLOB_LOCATOR
SQLUINTEGER * valueLength 출력 LOB 의 길이를 저장하기 위해 사용한다.
포인터가 가리키는 버퍼는 데이터 길이를 반환한다.

결과값#

SQL_SUCCESS
SQL_SUCCESS_WITH_INFO
SQL_INVALID_HANDLE
SQL_ERROR

설 명#

LOB locator가 가리키는 LOB의 길이를 얻기 위해 사용되는 함수이다.

LOB locator는 데이터베이스 내의 LOB을 직접 가리키는(LOB 내에서의 오프셋 아님) 값이다. LOB locator를 얻는 방법은 두 가지가 존재한다 :

SQLBindCol()이나 SQLGetData() 함수를 통해 SELECT SQL 문의 결과 집합의 LOB 열로부터 얻을 수 있다.

이 경우, 사용자가 바인드하는 application buffer type 은 SQL_C_CLOB_LOCATOR, 혹은, SQL_C_BLOB_LOCATOR 여야 한다.

SQLBindParameter() 의 output parameter 를 통해 얻을 수 있다.

이 경우, 사용자가 바인드하는 application buffer type 은 SQL_C_CLOB_LOCATOR, 혹은, SQL_C_BLOB_LOCATOR 여야 한다.

현재의 트랜잭션 도중 얻어진 LOB locator가 아닌 경우 본 함수의 인자로 사용할 수 없다. 트랜잭션이 종료하면 LOB locator가 무효하게 되기 때문이다. 만약 유효하지 않은 LOB locator를 인자로 사용할 경우, 본 함수는 SQL_ERROR 를 리턴하며, valueLength 인자가 가리키는 버퍼는 변경되지 않는다.

valueLength 인자를 통해 LOB의 길이가 리턴된다.

진 단#

SQLSTATE 설명 부연설명
08S01 통신 회선 장애 (데이터 송수신 실패) Altibase CLI 드라이버와 DB간에 함수 처리가 완료되기 전에 통신 회선 실패
HY000 일반 오류

관련함수#

SQLBindCol
SQLBindParameter
SQLFetch
SQLExecute
SQLGetLob
SQLPutLob

예 제#

테이블은 다음 DDL에 의해 생성되었다고 가정한다.

CREATE TABLE T1 (i1 INTEGER PRIMARY KEY, i2 BLOB);
LOB 데이터를 검색하여 길이 조회#
SQLINTEGER valueLength;
SQLUBIGINT lobLoc;
.
.
.
strcpy(query, "SELECT i2 FROM T1 WHERE i1=1");
if (SQLExecDirect(stmt, query, SQL_NTS) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, “SQLExecDirect : ”);
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

if (SQLBindCol(stmt, 1, SQL_C_BLOB_LOCATOR, &lobLoc, 0, NULL) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, “SQLBindCol : ”);
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

if (SQLFetch(stmt) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, “SQLFetch : ”);
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

if (SQLGetLobLength(stmt, lobLoc, SQL_C_BLOB_LOCATOR, &valueLength) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, “SQLGetLobLength : ”);
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

printf("SQLGetLobLength success!!!\n");

if (SQLFreeLob(stmt, lobLoc) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, “SQLFreeLob : ”);
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

SQLGetLob#

트랜잭션이 진행 중에 얻어진 LOB Locator가 가리키는 LOB에서 데이터의 일부분을 애플리케이션 데이터 버퍼(application data buffer)로 가져온다.

구 문#

SQLRETURN SQLGetLob(
    SQLHSTMT        stmt,
    SQLSMALLINT     locatorCType,
    SQLUBIGINT      sourceLocator,
    SQLUINTEGER     fromPosition,
    SQLUINTEGER     forLength,
    SQLSMALLINT     targetCType,
    SQLPOINTER      value,
    SQLUINTEGER     bufferSize,
    SQLUINTEGER *   valueLength);

인 자#

자료유형 인자 사용 설명
SQLHSTMT stmt 입력 검색된 결과들에 대한 명령문 핸들
SQLSMALLINT locatorCType 입력 LOB Locator 의 C 데이터타입 식별자. 다음과 같은 값을 가질 수 있다. SQL_C_BLOB_LOCATOR SQL_C_CLOB_LOCATOR
SQLUBIGINT sourceLocator 입력 Source LOB Locator
SQLUINTEGER fromPosition 입력 LOB 데이터에서 가져올 데이터의 시작 위치 (바이트 단위). 0부터 시작된다.
SQLUINTEGER forLength 입력 LOB에서 가져올 데이터의 길이 (바이트 단위).
SQLSMALLINT targetCType 입력 Value 버퍼의 C 데이터타입 식별자. 다음과 같은 값을 설정할 수 있다. SQL_C_BINARY SQL_C_CHAR 사용자가 BLOB 데이터를 SQL_C_CHAR 버퍼에 읽어들였을 경우 BINARY CHAR 컨버젼이 일어나며, 그 결과값이 애플리케이션 버퍼에 저장된다.
SQLPOINTER value 출력 데이터가 저장될 버퍼의 포인터
SQLUINTEGER bufferSize 입력 value 버퍼의 크기 (바이트 단위)
SQLUINTEGER* valueLength 출력 value 버퍼에 저장된 데이터의 길이를 돌려받기 위한 버퍼를 가리키는 포인터. 본 인자는 NULL 일 수 없다.

결과값#

SQL_SUCCESS
SQL_SUCCESS_WITH_INFO
SQL_INVALID_HANDLE
SQL_ERROR

설 명#

sourceLocator가 가리키는 LOB 데이터의 일부분을 서버에서 애플리케이션(application data buffer)으로 가져온다. LOB 데이터를 나누어 가져오기 위해 사용된다. LOB의 전체 길이는 SQLGetLobLength()를 호출하여 얻을 수 있다.

sourceLocator가 현재의 트랜잭션 내에서 열린 LOB locator가 아닌 경우 본 함수의 인자로 사용할 수 없다. 트랜잭션을 종료하면 LOB locator가 무효화되기 때문이다. 소스 LOB locator가 유효하지 않은 경우, SQLGetLob() 함수는 SQL_ERROR 를 리턴하며, value 및 valueLength 인자가 가리키는 버퍼는 변경되지 않는다.

sourceLocator가 NULL인 LOB을 가리킬 경우, SQLGetLob() 함수는 LOB locator의 길이가 0인 LOB을 가리키고 있는 경우와 동일하게 동작한다.

SQLGetLob() 호출 결과 반환될 데이터의 크기가 bufferSize의 버퍼 크기보다 클 경우, SQLGetLob() 함수는 SQL_SUCCESS_WITH_INFO (SQLSTATE=01004)를 리턴하며, 버퍼에 반환되는 데이터는 버퍼의 크기에 맞춰 끝부분이 잘린다.

진 단#

SQLSTATE 설명 부연설명
08S01 통신 회선 장애 (데이터 송수신 실패) Altibase CLI 드라이버와 DB간에 함수 처리가 완료되기 전에 통신 회선 실패
HY000 일반 오류

관련함수#

SQLGetLobLength
SQLPutLob

예 제#

테이블은 다음 DDL에 의해 생성되었다고 가정한다.

CREATE TABLE T1 (i1 INTEGER PRIMARY KEY, i2 CLOB);
SQLGetLob() 함수를 이용하여, LOB 데이터를 애플리케이션 버퍼로 가져온다.#
SQLCHAR buf[1024];
SQLINTEGER valueLength, accumLength, forLength, procLength;
SQLUBIGINT lobLoc;
.
.
strcpy(query, "SELECT i2 FROM T1 WHERE i1=1");
if (SQLExecDirect(stmt, query, SQL_NTS) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, “SQLExecDirect : ”);
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

if (SQLBindCol(stmt, 1, SQL_C_CLOB_LOCATOR, &lobLoc, 0, NULL) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, “SQLBindCol : ”);
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

if (SQLFetch(stmt) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, “SQLFetch : ”);
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

if (SQLGetLobLength(stmt, lobLoc, SQL_C_CLOB_LOCATOR, &valueLength) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, “SQLGetLobLength : ”);
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

for (accumLength = 0; accumLength < valueLength; accumLength += procLength)
{
    if (valueLength - accumLength > 256)
    {
        forLength = 256;
    }
    else
    {
        forLength = valueLength - accumLength;
    }

    if (SQLGetLob(stmt, SQL_C_CLOB_LOCATOR, lobLoc, accumLength, forLength, SQL_C_CHAR, buf, 256, &procLength) != SQL_SUCCESS)
    {
        execute_err(dbc, stmt, “SQLGetLob : ”);
        SQLFreeStmt(stmt, SQL_DROP);
        return SQL_ERROR;
    }

    printf("%s", buf);
}

if (SQLFreeLob(stmt, lobLoc) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, “SQLFreeLob : ”);
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

SQLPutLob#

SQLPutLob은 LOB 데이터를 삽입하거나 갱신할 때 사용한다. 이 함수의 모든 동작은 내부적으로 갱신 작업에 해당한다. LOB 데이터를 삽입하는 것은 길이가 0인 LOB 데이터를 다른 값으로 갱신하는 것을 의미하며 LOB 데이터를 갱신하는 것은 기존 LOB 데이터에서 특정 위치의 값을 다른 값으로 변경하거나 LOB 데이터 뒤에 데이터를 추가하는 것을 의미한다. 이 함수를 실행하는 세션은 반드시 자동 커밋 모드를 해제해야 하며, LOB 위치 입력기를 얻는 함수를 먼저 실행해야 한다. 관련 내용은 LOB 데이터 처리 방식에서 확인할 수 있다.

SQLPutLob 함수는 Altibase CLI에서 LOB 데이터를 다루기 위해 제공하는 특수한 함수로, ODBC 표준에는 없다.

구 문#

SQLRETURN SQLPutLob(
    SQLHSTMT        stmt,
    SQLSMALLINT     locatorCType,
    SQLUBIGINT      targetLocator,
    SQLUINTEGER     fromPosition,
    SQLUINTEGER     forLength,
    SQLSMALLINT     sourceCType,
    SQLPOINTER      value,
    SQLUINTEGER     valueLength);

인 자#

자료유형 인자 사용 설명
SQLHSTMT stmt 입력 검색된 결과들에 대한 명령문 핸들
SQLSMALLINT locatorCType 입력 삽입 또는 갱신할 LOB 위치 입력기의 C 데이터 타입 식별자.
SQL_C_BLOB_LOCATOR 또는 SQL_C_CLOB_LOCATOR가 올 수 있다.
SQLUBIGINT targetLocator 입력 LOB 위치 입력기.
LOB 데이터를 삽입 또는 갱신할 LOB 데이터를 가리킨다.
SQLUINTEGER fromPosition 입력 LOB 데이터를 삽입 또는 갱신할 시작 위치로, 0부터 시작하며 LOB 데이터를 삽입할 때는 0이어야 한다. 단위는 바이트이다.
SQLUINTEGER forLength 입력 사용되지 않음
SQLSMALLINT sourceCType 입력 CLI 애플리케이션 버퍼를 나타내는 C 데이터 타입 식별자. 이 버퍼는 삽입 또는 갱신할 LOB 데이터를 담고 있다.
BLOB 데이터는 SQL_C_BINARY, CLOB 데이터는 SQL_C_CHAR가 올 수 있다.
SQLPOINTER value 입력 CLI 애플리케이션 버퍼를 가리키는 포인터
SQLUINTEGER valueLength 입력 CLI 애플리케이션 버퍼에 저장된 LOB 데이터의 길이로, 1부터 시작한다. 단위는 바이트이다. SQL_NULL_DATA는 설정할 수 없다.

결과값#

SQL_SUCCESS
SQL_SUCCESS_WITH_INFO
SQL_INVALID_HANDLE
SQL_ERROR

설 명#

이 함수는 CLI 애플리케이션 버퍼 value에 담긴 LOB 데이터를 LOB 위치 입력기 targetLocator가 가리키고 있는 LOB 데이터에 갱신한다. 이때, 갱신되는 위치는 fromPosition 부터 valueLength 까지이다.

LOB 데이터 삽입#

INSERT 문으로 LOB 데이터를 삽입할 때 이 함수를 사용할 수 있다. 이때, fromPosition은 0이어야 한다. 이것은 targetLocator가 길이가 0인 LOB 데이터를 가리키는 것을 의미한다.

LOB 데이터 전체 갱신#

UPDATE 문으로 LOB 타입 칼럼 전체를 갱신할 때 이 함수를 사용할 수 있다. 이 함수의 동작은 LOB 데이터 삽입 방식과 같으며 fromPosition도 0이어야 한다.

LOB 데이터 부분 갱신#

SQLPutLob 함수를 사용하여 기존 LOB 데이터에서 특정 위치의 값을 갱신할 수 있다. 이때, LOB 위치 입력기를 얻기 위해 SELECT lob_column_name FROM table_name WHERE … FOR UPDATE 문장을 먼저 수행해야 한다. 이 함수의 동작 역시 LOB 데이터 삽입 방식과 같으나 fromPosition은 기존 LOB 데이터에서 갱신할 시작 위치를 지정해야 한다. fromPosition에 기존 LOB 데이터의 끝 위치를 지정하면, CLI 애플리케이션 버퍼(value)에 담긴 LOB 데이터가 기존 데이터 뒤에 추가된다.

SQL_ERROR 반환#

targetLocator 인자가 유효하지 않을 때 SQL_ERROR를 반환한다.

fromPosition 인자가 함수 실행 시점의 targetLocator가 가리키는 LOB 타입 칼럼의 길이보다 크면 SQL_ERROR를 반환한다.

진 단#

SQLSTATE 설명 부연설명
08S01 통신 회선 장애 (데이터 송수신 실패) Altibase CLI 드라이버와 DB간에 함수 처리가 완료되기 전에 통신 회선 실패
HY000 일반 오류

관련함수#

SQLGetLobLength
SQLGetLob

예 제#

아래는 SQLBindCol 함수 예제에서 사용한 테이블 생성 구문이다.

CREATE TABLE T1 (i1 INTEGER PRIMARY KEY, i2 CLOB);
CLOB 데이터 삽입 후 부분 갱신#

CLOB 칼럼 값이 'Hybrid dbms Altibase'인 레코드를 삽입 후 'dbms'를 'DBMS'로 변경한다.

SQLCHAR buf[20];
SQLINTEGER lobInd;
SQLUBIGINT lobLoc;

strcpy(query, "INSERT INTO T1 VALUES (5, ?)");
if (SQLPrepare(stmt, query, SQL_NTS) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLPrepare : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

/* 
SQLExecute 함수에서 LOB 위치 입력기를 얻을 수 있도록 SQLBindParameter 함수에서 LOB 위치 입력기 인자를 바인딩한다. 
*/
if (SQLBindParameter(stmt, 1, SQL_PARAM_OUTPUT, SQL_C_CLOB_LOCATOR, SQL_CLOB_LOCATOR, 0, 0, &lobLoc, 0, &lobInd) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLBindParameter : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

/* 
SQLExecute 함수를 호출한다.
*/ 
if (SQLExecute(stmt) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLExecute : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

/* SQLPutLob 함수로 CLOB 데이터를 삽입한다. */
memcpy(buf, "Hybrid dbms Altibase", 20);
if (SQLPutLob(stmt, SQL_C_CLOB_LOCATOR, lobLoc, 0, 0, SQL_C_CHAR, buf, 20) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLPutLob : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

/* SQLPutLob 함수로 CLOB 데이터를 부분 갱신한다. */
/* 'Hybrid dbms Altibase'에서 8번째 위치(fromPosition+1)부터 12번째 위치까지 'DBMS'로 치환 */
memcpy(buf, "DBMS", 4);
if (SQLPutLob(stmt, SQL_C_CLOB_LOCATOR, lobLoc, 7, 0, SQL_C_CHAR, buf, 4) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLPutLob : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

if (SQLFreeLob(stmt, lobLoc) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLFreeLob : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}
CLOB 데이터 전체 갱신#

여러 레코드의 CLOB 칼럼을 일괄적으로 'Retail'로 변경한다.

SQLCHAR buf[6];
SQLINTEGER lobInd;
SQLUBIGINT lobLoc;

strcpy(query, "UPDATE T1 SET i2=? WHERE i1>=1 AND i1<=100");
if (SQLPrepare(stmt, query, SQL_NTS) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, SQLPrepare : );
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

/* 
SQLExecute 함수에서 LOB 위치 입력기를 얻을 수 있도록 SQLBindParameter 함수에서 LOB 위치 입력기 인자를 바인딩한다. 
*/
if (SQLBindParameter(stmt, 1, SQL_PARAM_OUTPUT, SQL_C_CLOB_LOCATOR, SQL_CLOB_LOCATOR, 0, 0, &lobLoc, 0, &lobInd) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLBindParameter : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

/* 
SQLExecute 함수를 호출한다.
*/
if (SQLExecute(stmt) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLExecute : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

/* SQLPutLob 함수로 CLOB 데이터를 전체 갱신한다. */
memcpy(buf, Retail, 6);
if (SQLPutLob(stmt, SQL_C_CLOB_LOCATOR, lobLoc, 0, 0, SQL_C_CHAR, buf, 6) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLPutLob : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

if (SQLFreeLob(stmt, lobLoc) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLFreeLob : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}
CLOB 데이터 부분 갱신#

CLOB 칼럼 값이 'Ver.Beta'인 레코드 삽입 후 'Beta' 부분을 'Gamma'로 치환

SQLCHAR buf[5];
SQLUBIGINT lobLoc;
.
/* CLOB 타입 칼럼에 "Ver.Beta"를 삽입 */
strcpy(query, "INSERT INTO T1 VALUES (1, 'Ver.Beta')");
if (SQLExecDirect(stmt, query, SQL_NTS) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLExecDirect : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

/* 아래부터는 SQLPutLob 함수로 CLOB 데이터를 부분 갱신하는 예제이다. */

/* LOB 위치 입력기를 얻기 위해 SELECT FOR UPDATE 문을 먼저 수행한다. */
strcpy(query, "SELECT i2 FROM T1 WHERE i1=1 FOR UPDATE");
if (SQLExecDirect(stmt, query, SQL_NTS) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLExecDirect : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}
/* SQLFetch 함수에서 LOB 위치 입력기를 얻을 수 있도록 SQLBindCol 함수에서 LOB 위치 입력기 인자를 바인딩한다. */ 
if (SQLBindCol(stmt, 1, SQL_C_CLOB_LOCATOR, &lobLoc, 0, NULL) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLBindCol : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

if (SQLFetch(stmt) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLFetch : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

/* SQLPutLob 함수로 기존 LOB 데이터의 마지막 부분을 다른 데이터로 변경한다. */
/* 'Ver.Beta'에서 Beta 부분을 Gamma로 변경 */
memcpy(buf, "Gamma", 5);
if (SQLPutLob(stmt, SQL_C_CLOB_LOCATOR, lobLoc, 4, 0, SQL_C_CHAR, buf, 5) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLPutLob : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

if (SQLFreeLob(stmt, lobLoc) != SQL_SUCCESS)
{
    execute_err(dbc, stmt, "SQLFreeLob : ");
    SQLFreeStmt(stmt, SQL_DROP);
    return SQL_ERROR;
}

SQLTrimLob#

LOB Locator가 가리키는 LOB 값의 지정한 위치 뒤쪽 부분을 삭제한다.

구 문#

SQLRETURN SQLTrimLob(
    SQLHSTMT         stmt,
    SQLSMALLINT      locatorCType,
    SQLUBIGINT       targetLocator,
    SQLLEN           fromPosition);

인 자#

자료유형 인자 사용 설명
SQLHSTMT stmt 입력 검색된 결과들에 대한 명령문 핸들
SQLSMALLINT locatorCType 입력 Target LOB Locator의 C 데이터 타입 식별자. SQL_C_BLOB_LOCATOR SQL_C_CLOB_LOCATOR
SQLUBIGINT targetLocator 입력 Target LOB Locator
SQLLEN fromPosition 입력 삭제할 LOB 데이터의 시작 위치 (단위: 바이트). 0부터 시작된다.

결과값#

SQL_SUCCESS
SQL_INVALID_HANDLE
SQL_ERROR

설 명#

이 함수는 타겟 LOB locator가 가리키는 LOB 값에서 지정한 위치 뒤쪽의 데이터를 삭제하며, 삭제 후에는 타겟 LOB의 길이가 줄어든다.

타겟 LOB locator가 현재의 트랜잭션에서 열린 LOB locator가 아닌 경우 본 함수의 인자로 사용할 수 없다. 트랜잭션이 종료하면 LOB locator가 무효가 되기 때문이다. 타겟 LOB locator가 유효하지 않은 경우, SQLTrimLob() 함수는 SQL_ERROR을 리턴한다.

진 단#

SQLSTATE 설명 부연설명
08S01 통신 회선 장애 (데이터 송수신 실패) Altibase CLI 드라이버와 DB 서버간에 함수 처리가 완료되기 전에 통신 회선 실패
HY000 일반 오류

관련함수#

SQLGetLobLength
SQLGetLob

예 제#

테이블은 다음 DDL에 의해 생성되었다고 가정한다.

CREATE TABLE T1 (i1 INTEGER PRIMARY KEY, i2 CLOB);
CLOB 칼럼 값이 ‘Ver.Beta’인 레코드 삽입 후 ‘Beta’ 부분 삭제#
SQLCHAR buf[5];
SQLUBIGINT lobLoc;

strcpy(query, "INSERT INTO T1 VALUES (1, 'Ver.Beta')");
if (SQLExecDirect(stmt, query, SQL_NTS) != SQL_SUCCESS)
{
     execute_err(dbc, stmt, “SQLExecDirect : ”);
     SQLFreeStmt(stmt, SQL_DROP);
     return SQL_ERROR;
}

strcpy(query, "SELECT i2 FROM T1 WHERE i1=1 FOR UPDATE");
if (SQLExecDirect(stmt, query, SQL_NTS) != SQL_SUCCESS)
{
     execute_err(dbc, stmt, “SQLExecDirect : ”);
     SQLFreeStmt(stmt, SQL_DROP);
     return SQL_ERROR;
}
if (SQLBindCol(stmt, 1, SQL_C_CLOB_LOCATOR, &lobLoc, 0, NULL) != SQL_SUCCESS)
{
     execute_err(dbc, stmt, “SQLBindCol : ”);
     SQLFreeStmt(stmt, SQL_DROP);

     return SQL_ERROR;
}
if (SQLFetch(stmt) != SQL_SUCCESS)
{
     execute_err(dbc, stmt, “SQLFetch : ”);
     SQLFreeStmt(stmt, SQL_DROP);
     return SQL_ERROR;
}

if (SQLTrimLob(stmt, SQL_C_CLOB_LOCATOR, lobLoc, 4) != SQL_SUCCESS)
{
     execute_err(dbc, stmt, “SQLTrimLob : ”);
     SQLFreeStmt(stmt, SQL_DROP);
     return SQL_ERROR;
}
if (SQLFreeLob(stmt, lobLoc) != SQL_SUCCESS)
{
     execute_err(dbc, stmt, “SQLFreeLob : ”);
     SQLFreeStmt(stmt, SQL_DROP);
     return SQL_ERROR;
}

SQLFreeLob#

현재의 트랜잭션에서 열린 LOB Locator와 관련된 자원들을 해제한다.

구 문#

SQLRETURN SQLFreeLob (
    SQLHSTMT        stmt,
    SQLUBIGINT      locator);

인 자#

자료유형 인자 사용 설명
SQLHSTMT stmt 입력 검색된 결과들에 대한 명령문 핸들
SQLUBIGINT locator 입력 LOB Locator

결과값#

SQL_SUCCESS
SQL_INVALID_HANDLE
SQL_ERROR

설 명#

LOB locator로 대표되는 LOB에 대한 조작이 종료되었음을 서버에게 알려준다. 이로 인해 서버에서 할당된 LOB locator는 해제되며, 그와 관련된 서버의 자원들도 해제된다.

본 함수는 LOB locator가 가리키는 LOB에 대한 변경 사항을 commit 또는 rollback하지 않는다.

SQLEndTran()으로 트랜잭션을 종료한 경우, LOB locator는 자동으로 해제되므로 본 함수를 호출할 필요가 없다.

진 단#

SQLSTATE 설명 부연설명
08S01 통신 회선 장애 (데이터 송수신 실패) Altibase CLI 드라이버와 DB간에 함수 처리가 완료되기 전에 통신 회선 실패
HY000 일반 오류

관련함수#

SQLGetLobLength
SQLGetLob
SQLPutLob

예 제#

SQLGetLobLength(), SQLGetLob(), SQLPutLob() 의 예제를 참고한다.