데이터 분류

ODBC 드라이버 다운로드

개요

중요한 데이터를 관리하기 위해 SQL Server 및 Azure SQL Server는 클라이언트 응용 프로그램에서 데이터 보호 정책에 따라 다양한 유형의 중요한 데이터(예: 건강, 재무 등)를 처리할 수 있도록 하는 민감도 메타데이터를 데이터베이스 열에 제공하는 기능을 도입했습니다.

열에 분류를 할당하는 방법에 대한 자세한 내용은 SQL 데이터 검색 및 분류를 참조하세요.

Microsoft ODBC Driver 17.2 이상 버전에서는 SQL_CA_SS_DATA_CLASSIFICATION 필드 식별자를 사용하는 SQLGetDescField를 통해 이 메타데이터를 검색할 수 있도록 합니다.

형식

SQLGetDescField의 구문은 다음과 같습니다.

SQLRETURN SQLGetDescField(  
     SQLHDESC        DescriptorHandle,  
     SQLSMALLINT     RecNumber,  
     SQLSMALLINT     FieldIdentifier,  
     SQLPOINTER      ValuePtr,  
     SQLINTEGER      BufferLength,  
     SQLINTEGER *    StringLengthPtr);  

DescriptorHandle
[Input] IRD(구현 행 설명자) 핸들입니다. SQL_ATTR_IMP_ROW_DESC 문 특성의 SQLGetStmtAttr를 호출하여 검색할 수 있습니다.

RecNumber
[Input] 0

FieldIdentifier
[Input] SQL_CA_SS_DATA_CLASSIFICATION

ValuePtr
[Output] 출력 버퍼

BufferLength
[Input] 출력 버퍼의 길이(바이트)

StringLengthPtr [Output] ValuePtr에 반환할 수 있는 총 바이트 수를 반환할 버퍼에 대한 포인터입니다.

참고 항목

버퍼의 크기를 알 수 없는 경우 ValuePtr을 NULL로 사용하여 SQLGetDescField를 호출하고 StringLengthPtr 값을 검사하여 확인할 수 있습니다.

데이터 분류 정보를 사용할 수 없는 경우 잘못된 설명자 필드 오류가 반환됩니다.

SQLGetDescField를 성공적으로 호출하면 ValuePtr에서 가리키는 버퍼에 다음 데이터가 포함됩니다.

nn nn [n sensitivitylabels] tt tt [t informationtypes] cc cc [c columnsensitivitys]

참고 항목

nn nn, tt tt, cc cc는 멀티바이트 정수로 가장 아래 주소에서 최하위 바이트를 사용하여 저장됩니다.

sensitivitylabelinformationtype은 모두 다음 형식을 취합니다.

nn [n bytes name] ii [i bytes id]

columnsensitivity의 형식은

nn nn [n sensitivityprops]

각 열 (c)에 대해 n 4바이트 sensitivityprops가 있습니다.

ss ss tt tt

s - sensitivitylabels 배열에 대한 인덱스, 레이블이 지정되지 않은 경우 FF FF

t - informationtypes 배열에 대한 인덱스, 레이블이 지정되지 않은 경우 FF FF



데이터 형식은 다음과 같은 의사 구조체로 표현될 수 있습니다.

struct IDnamePair {
 BYTE nameLen;
 USHORT name[nameLen];
 BYTE idLen;
 USHORT id[idLen];
};

struct SensitivityProp {
 USHORT labelIdx;
 USHORT infoTypeIdx;
};

USHORT nLabels;
struct IDnamePair labels[nLabels];
USHORT nInfoTypes;
struct IDnamePair infotypes[nInfoTypes];
USHORT nColumns;
struct {
 USHORT nProps;
 struct SensitivityProp[nProps];
} columnClassification[nColumns];

코드 샘플

데이터 분류 메타데이터를 읽는 방법을 보여 주는 응용 프로그램을 테스트합니다. Windows에서는 cl /MD dataclassification.c /I (directory of msodbcsql.h) /link odbc32.lib를 사용해 컴파일하고 연결 문자열과 분류된 열을 반환하는 매개 변수로서 SQL 쿼리를 사용하여 실행할 수 있습니다.

#ifdef _WIN32
#include <windows.h>
#endif
#include <sql.h>
#include <sqlext.h>
#include <msodbcsql.h>
#include <stdio.h>
SQLHANDLE env, dbc, stmt;
void checkRC_exit(SQLRETURN rc, SQLHANDLE hand, SQLSMALLINT htype, int retcode, char *action)
{
    if ((rc == SQL_ERROR || rc == SQL_SUCCESS_WITH_INFO) && hand)
    {
        char msg[1024], state[6];
        int i = 0;
        SQLRETURN rc2;
        SQLINTEGER err;
        SQLSMALLINT lenout;
        while ((rc2 = SQLGetDiagRec(htype, hand, ++i, state, &err, msg, sizeof(msg), &lenout)) == SQL_SUCCESS ||
            rc2 == SQL_SUCCESS_WITH_INFO)
            printf("%d (%d)[%s]%s\n", i, err, state, msg);
    }
    if (rc == SQL_ERROR && retcode)
    {
        printf("Error occurred%s%s\n", action ? " upon " : "", action ? action : "");
        exit(retcode);
    }
}
void printLabelInfo(char *type, char **pptr)
{
    char *ptr = *pptr;
    unsigned short nlabels;
    printf("----- %s(%u) -----\n", type, nlabels = *(unsigned short*)ptr);
    ptr += sizeof(unsigned short);
    while (nlabels--)
    {
        int namelen, idlen;
        char *nameptr, *idptr;
        namelen = *ptr++;
        nameptr = ptr;
        ptr += namelen * 2;
        idlen = *ptr++;
        idptr = ptr;
        ptr += idlen * 2;
        wprintf(L"Name: \"%.*s\" Id: \"%.*s\"\n", namelen, nameptr, idlen, idptr);
    }
    *pptr = ptr;
}
int main(int argc, char **argv)
{
    unsigned char *dcbuf;
    unsigned int dclen = 0;
    SQLRETURN rc;
    SQLHANDLE ird;
    if (argc < 3)
    {
        fprintf(stderr, "usage: dataclassification connstr query\n");
        return 1;
    }
    checkRC_exit(SQLAllocHandle(SQL_HANDLE_ENV, 0, &env), 0, 0,
        2, "allocate environment");
    checkRC_exit(SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0), env, SQL_HANDLE_ENV,
        3, "set ODBC version");
    checkRC_exit(SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc), env, SQL_HANDLE_ENV,
        4, "allocate connection");
    checkRC_exit(SQLDriverConnect(dbc, 0, argv[1], SQL_NTS, 0, 0, 0, SQL_DRIVER_NOPROMPT), dbc, SQL_HANDLE_DBC,
        5, "connect to server");
    checkRC_exit(SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt), dbc, SQL_HANDLE_DBC,
        6, "allocate statement");
    checkRC_exit(SQLExecDirect(stmt, argv[2], SQL_NTS), stmt, SQL_HANDLE_STMT,
        7, "execute query");
    checkRC_exit(SQLGetStmtAttr(stmt, SQL_ATTR_IMP_ROW_DESC, (SQLPOINTER)&ird, SQL_IS_POINTER, 0), stmt, SQL_HANDLE_STMT,
        8, "get IRD handle");
    rc = SQLGetDescFieldW(ird, 0, SQL_CA_SS_DATA_CLASSIFICATION, dcbuf, 0, &dclen);

    checkRC_exit(rc, ird, SQL_HANDLE_DESC, 0, 0);
  

    SQLINTEGER dclenout;
    unsigned char *dcptr;
    unsigned short ncols;
    printf("Data Classification information (%u bytes):\n", dclen);
    if (!(dcbuf = malloc(dclen)))
    {
        printf("Memory Allocation Error");
        return 9;
    }
    checkRC_exit(SQLGetDescFieldW(ird, 0, SQL_CA_SS_DATA_CLASSIFICATION, dcbuf, dclen, &dclenout),
            ird, SQL_HANDLE_DESC, 10, "reading SQL_CA_SS_DATA_CLASSIFICATION");
    dcptr = dcbuf;
    printLabelInfo("Labels", &dcptr);
    printLabelInfo("Information Types", &dcptr);
    printf("----- Column Sensitivities(%u) -----\n", ncols = *(unsigned short*)dcptr);
    dcptr += sizeof(unsigned short);
    while (ncols--)
    {
        unsigned short nprops = *(unsigned short*)dcptr;
        dcptr += sizeof(unsigned short);
        while (nprops--)
        {
            unsigned short labelidx, typeidx;
            labelidx = *(unsigned short*)dcptr; dcptr += sizeof(unsigned short);
            typeidx = *(unsigned short*)dcptr; dcptr += sizeof(unsigned short);
            printf(labelidx == 0xFFFF ? "(none) " : "%u ", labelidx);
            printf(typeidx == 0xFFFF ? "(none)\n" : "%u\n", typeidx);
        }
        printf("-----\n");
    }
    if (dcptr != dcbuf + dclen)
    {
        printf("Error: unexpected parse of DATACLASSIFICATION data\n");
        return 11;
    }
    free(dcbuf);
    
    return 0;
}

지원되는 버전

Microsoft ODBC Driver 17.2에서는 FieldIdentifierSQL_CA_SS_DATA_CLASSIFICATION(1237)으로 설정된 경우 SQLGetDescField를 통해 데이터 분류 정보를 검색할 수 있습니다.

Microsoft ODBC Driver 17.4.1.1부터는 SQL_CA_SS_DATA_CLASSIFICATION_VERSION(1238) 필드 식별자를 사용하여 SQLGetDescField를 통해 서버에서 지원하는 데이터 분류 버전을 검색할 수 있습니다. 17.4.1.1에서는 지원되는 데이터 분류 버전이 "2"로 설정됩니다.

17.4.2.1부터 데이터 분류의 기본 버전은 "1"로 설정되며 이는 지원에 따라 드라이버에서 SQL Server에 보고하는 버전입니다. 새 연결 특성 SQL_COPT_SS_DATACLASSIFICATION_VERSION(1400)을 사용하면 응용 프로그램에서 지원 데이터 분류 버전을 "1"에서 최대 지원 버전으로 변경할 수 있습니다.

예시:

버전을 설정하려면 SQLConnect 또는 SQLDriverConnect 호출 바로 전에 이 호출이 실행되어야 합니다.

ret = SQLSetConnectAttr(dbc, SQL_COPT_SS_DATACLASSIFICATION_VERSION, (SQLPOINTER)2, SQL_IS_INTEGER);

현재 지원되는 데이터 분류 버전의 값은 SQLGetConnectAttr 호출을 통해 검색할 수 있습니다.

ret = SQLGetConnectAttr(dbc, SQL_COPT_SS_DATACLASSIFICATION_VERSION, (SQLPOINTER)&dataClassVersion, SQL_IS_INTEGER, 0);