데이터 분류
개요
중요한 데이터를 관리하기 위해 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
는 멀티바이트 정수로 가장 아래 주소에서 최하위 바이트를 사용하여 저장됩니다.
sensitivitylabel
및 informationtype
은 모두 다음 형식을 취합니다.
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에서는 FieldIdentifier
가 SQL_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);