Share via


ntext, text 및 image 데이터 관리

중요 정보중요

Microsoft SQL Server의 이후 버전에서는 이 기능이 제거됩니다. 새 개발 작업에서는 이 기능을 사용하지 않도록 하고, 현재 이 기능을 사용하는 응용 프로그램은 수정하십시오. 대신 varchar(max), nvarchar(max) 및 varbinary(max) 데이터 형식을 사용하십시오. 자세한 내용은 큰 값 데이터 형식 사용을 참조하십시오.

SQL Serverntext, text 및 image 데이터 형식은 하나의 값에 많은 양(최대 2GB)의 데이터를 저장할 수 있습니다. 데이터 값 하나가 일반적으로 응용 프로그램에서 한 번에 검색할 수 있는 용량보다 크거나 클라이언트에서 사용할 수 있는 가상 메모리 용량보다 큰 경우도 있습니다. 따라서 이러한 값을 검색하려면 특별한 단계가 필요합니다.

ntext, text 및 image 데이터 값이 4,000자보다 짧은 유니코드, 8,000자보다 짧은 문자 또는 8,000바이트보다 짧은 이진 문자열인 경우 크기가 적은 데이터 형식과 마찬가지로 SELECT, UPDATE, INSERT 문에서 이러한 값을 참조할 수 있습니다. 예를 들어 짧은 값이 포함된 ntext 열은 nvarchar 열과 마찬가지로 SELECT 문의 선택 목록에서 참조할 수 있습니다. 하지만 WHERE 절에서 ntext, text 또는 image 열을 직접 참조할 수 없는 등의 일부 제한 사항이 있습니다. 이러한 열은 다른 데이터 형식을 반환하는 함수(예: ISNULL, SUBSTRING, PATINDEX)의 매개 변수로 WHERE 절에 포함되거나 IS NULL, IS NOT NULL, LIKE 식에 포함될 수 있습니다.

큰 데이터 값 처리

ntext, text 및 image 데이터 값이 커지면 블록 단위로 처리해야만 합니다. Transact-SQL과 데이터베이스 API에는 응용 프로그램이 ntext, text 및 image 데이터를 블록 단위로 사용할 수 있게 하는 함수가 포함되어 있습니다.

데이터베이스 API는 긴 ntext, text 및 image 열을 처리하는 것과 같은 패턴을 따릅니다.

  • 긴 열을 읽기 위해 응용 프로그램은 선택 목록에 ntext, text 또는 image 열을 포함한 다음 적절한 데이터 블록을 저장할 만큼 큰 프로그램 변수에 해당 열을 바인딩합니다. 이렇게 하면 응용 프로그램에서 해당 문을 실행하고 API 함수나 메서드를 사용하여 한 번에 한 블록씩 데이터를 바인딩된 변수로 가져옵니다.

  • 긴 열을 쓰기 위해 응용 프로그램은 ntext, text 또는 image 열에 값 대신 매개 변수 표식(?)이 있는 INSERT 또는 UPDATE 문을 실행합니다. 매개 변수 표식(또는 ADO의 경우 매개 변수)은 데이터 블록을 저장할 만큼 큰 프로그램 변수에 바인딩됩니다. 응용 프로그램은 다음 데이터 집합을 바인딩된 변수로 이동한 다음 API 함수나 메서드를 호출하여 데이터 블록을 쓰는 루프를 돕니다. 이 과정은 전체 데이터 값이 전송될 때까지 반복됩니다.

text in row 사용

SQL Server에서는 테이블에 text in row 옵션을 사용하여 해당 데이터 행에 text, ntext 또는 image 데이터를 저장할 수 있습니다.

이 옵션을 사용하려면 옵션 이름으로 text in row를 지정하고 옵션 값으로 on을 지정하여 sp_tableoption 저장 프로시저를 실행합니다. text, ntext 또는 image 데이터와 같은 BLOB(Binary Large Object) 행에 저장할 수 있는 최대 크기의 기본값은 256바이트이지만 24에서 7000바이트 사이의 값을 사용할 수 있습니다. 기본값이 아닌 최대 크기를 지정하려면 옵션 값으로 해당 범위 내의 정수를 지정합니다.

다음과 같은 경우 text, ntext 또는 image 문자열은 데이터 행에 저장됩니다.

  • text in row가 설정된 경우

  • 문자열의 길이가 @OptionValue에 지정된 제한보다 짧은 경우

  • 데이터 행에 사용할 수 있는 충분한 공간이 있을 경우

BLOB 문자열이 데이터 행에 저장된 경우 문자와 이진 문자열과 마찬가지로 text, ntext 또는 image 문자열을 빠르게 읽고 쓸 수 있습니다. SQL Server에서는 BLOB 문자열을 읽거나 쓰기 위해 별도의 페이지에 액세스할 필요가 없습니다.

text, ntext 또는 image 문자열이 지정된 제한보다 크거나 행에서 사용 가능한 공간보다 큰 경우에는 대신 포인터가 행에 저장됩니다. 하지만 이 경우에도 행에 BLOB 문자열을 저장하기 위한 조건이 적용됩니다. 데이터 행에는 포인터를 유지할 수 있는 충분한 공간도 있어야 합니다.

자세한 내용은 sp_tableoption(Transact-SQL)을 참조하십시오.

텍스트 포인터 사용

text in row 옵션을 지정하지 않으면 text, ntext 또는 image 문자열은 데이터 행 외부에 저장되고 해당 문자열의 텍스트 포인터만 데이터 행에 저장됩니다. 텍스트 포인터는 text, ntext 및 image 데이터의 문자열 조각이 실제로 저장된 페이지에 대응되는 내부 포인터로 만들어진 트리의 루트 노드를 가리킵니다.

SQL Server 2000의 행 내부 텍스트 포인터는 이전 버전의 SQL Server 텍스트 포인터와는 다릅니다. 행 내부 텍스트 포인터는 BLOB 데이터의 파일 핸들처럼 작동하지만 이전의 텍스트 포인터는 BLOB 데이터의 주소처럼 작동합니다. 따라서 행 내부 텍스트 포인터를 사용할 때는 다음과 같은 특징을 유의해야 합니다.

중요 정보중요

커서에 행 내부 텍스트는 허용되지만 행 내부 텍스트 포인터는 허용되지 않습니다. SQL Server에서 행 내부 텍스트 포인터가 포함된 커서를 선언하려고 하면 오류 328이 반환됩니다.

  1. 숫자

    데이터베이스의 트랜잭션 당 최대 1024개의 활성 행 내부 텍스트 포인터가 허용됩니다.

  2. 잠금

    사용자가 활성 텍스트 포인터를 얻으면 SQL Server 2000은 첫 번째 사용자가 텍스트 포인터를 보유한 동안 다른 사용자가 행을 수정하거나 삭제할 수 없도록 데이터 행을 잠급니다. 텍스트 포인터가 무효화되면 잠금이 해제됩니다. 텍스트 포인터를 무효화하려면 sp_invalidate_textptr(Transact-SQL)을 사용합니다.

    트랜잭션 격리 수준이 커밋되지 않은 읽기거나 데이터베이스가 읽기 전용 모드일 경우 BLOB 값을 업데이트할 때 텍스트 포인터를 사용할 수 없습니다.

    SQL Server 2000은 데이터베이스가 단일 사용자 모드일 경우 데이터 행을 잠그지 않습니다.

    예를 들어 다음 테이블의 경우를 생각해 봅시다.

    CREATE TABLE t1 (c1 int, c2 text)
    EXEC sp_tableoption 't1', 'text in row', 'on'
    INSERT t1 VALUES ('1', 'a')
    

    다음 트랜잭션은 성공합니다.

    INSERT t1 VALUES ('1','This is text.')
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
    GO
    BEGIN TRAN
    DECLARE @ptr varbinary(16)
    SELECT @ptr = textptr(c2)
    FROM t1
    WHERE c1 = 1;
    READTEXT t1.c2 @ptr 0 5
    COMMIT TRAN
    GO
    

    다음 트랜잭션은 실패합니다.

    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
    GO
    BEGIN TRAN
    DECLARE @ptr varbinary(16)
    SELECT @ptr = textptr(c2)
    FROM t1
    WHERE c1 = 1
    WRITETEXT t1.c2 @ptr 'xx'
    COMMIT TRAN
    GO
    
  3. 기간

    행 내부 텍스트 포인터는 트랜잭션 내에서만 유효합니다. 트랜잭션이 커밋되면 텍스트 포인터가 무효화됩니다.

    다음과 같은 경우 트랜잭션 내에서 행 내부 텍스트 포인터가 무효화됩니다.

    • 세션이 끝난 경우

    • 동일한 트랜잭션에서 데이터 행이 삭제된 경우. 잠금 설정 때문에 다른 트랜잭션은 데이터 행을 삭제할 수 없습니다.

    • 텍스트 포인터가 있는 테이블의 스키마가 변경된 경우. 텍스트 포인터를 무효로 만드는 스키마 변경 작업에는 클러스터형 인덱스 만들기나 삭제, 테이블 변경이나 삭제, 테이블 잘라내기, sp_tableoption을 통한 text in row 옵션 변경, sp_indexoption 실행 등이 있습니다.

    위의 예에서 다음 스크립트는 이전 버전의 SQL Server에서는 작동되지만 SQL Server 2000에서는 오류를 발생시킵니다.

    DECLARE @ptrval varbinary(16)
    PRINT 'get error here'
    SELECT @ptrval = TEXTPTR(c2)
    FROM t1
    WHERE c1 = 1
    READTEXT t1.c2 @ptrval 0 1
    

    SQL Server 2000에서 행 내부 텍스트 포인터는 트랜잭션 내에서 사용해야 합니다.

    BEGIN TRAN
    DECLARE @ptrval varbinary(16)
    SELECT @ptrval = TEXTPTR(c2)
    FROM t1
    WHERE c1 = 1
    READTEXT t1.c2 @ptrval 0 1
    COMMIT
    
  4. NULL 텍스트

    INSERT에 의해 생성된 NULL 텍스트에 대해 행 내부 텍스트 포인터를 얻을 수 있습니다. 이전에는 BLOB을 NULL로 업데이트한 후에만 텍스트 포인터를 얻을 수 있었습니다.

    예를 들어 다음 코드는 SQL Server 7.0에서는 작동하지 않지만 SQL Server 2000에서는 작동합니다.

    SET TRANSACTION ISOLATION LEVEL READ COMMITTED
    GO
    INSERT INTO t1 VALUES (4, NULL)
    BEGIN TRAN
    DECLARE @ptrval VARBINARY(16)
    SELECT @ptrval = TEXTPTR(c2)
    FROM t1
    WHERE c1 = 4
    WRITETEXT t1.c2 @ptrval 'x4'
    COMMIT
    

    SQL Server 7.0에서는 다음을 사용해야 합니다.

    INSERT INTO t1 VALUES (4, NULL)
    UPDATE t1 
       SET c2 = NULL 
       WHERE c1 = 4
    DECLARE @ptrval VARBINARY(16)
    SELECT @ptrval = TEXTPTR(c2)
    FROM t1
    WHERE c1 = 4
    WRITETEXT t1.c2 @ptrval 'x4'
    

다음은 위 두 방식의 차이점을 요약한 표입니다.

차이

행 내부 텍스트 포인터가 있을 경우

행 내부 텍스트 포인터가 없을 경우

숫자

데이터베이스의 트랜잭션 당 최대 1024개의 활성 행 내부 텍스트 포인터가 허용됩니다.

제한이 없습니다.

잠금

포인터가 무효화될 때까지 데이터 행에 S 잠금이 설정됩니다.

트랜잭션이 '커밋되지 않은 읽기'이거나 데이터베이스가 '단일 사용자'나 '읽기 전용' 모드이면 잠금이 설정되지 않습니다.

데이터 행이 잠기지 않습니다.

기간

행이 삭제되거나 테이블의 스키마가 변경되면 트랜잭션이나 세션 종료 시 무효화됩니다.

행이 삭제되면 무효화됩니다.

NULL 텍스트

NULL 텍스트를 삽입한 후 바로 설정할 수 있습니다.

업데이트 후에만 설정할 수 있습니다.

ntext, text, image 데이터에 데이터베이스 API 사용

다음은 데이터베이스 API가 ntext, text 및 image 데이터를 처리하는 방식을 요약한 것입니다.

  • ADO

    ADO는 ntext, text 또는 image 열이나 매개 변수를 Field 또는 Parameter 개체에 매핑할 수 있습니다. GetChunk 메서드를 사용하여 데이터를 한 번에 한 블록씩 검색하고 AppendChunk 메서드를 사용하여 데이터를 한 번에 한 블록씩 씁니다.

  • OLE DB

    OLE DB는 ISequentialStream 인터페이스를 사용하여 ntext, text 및 image 데이터 형식을 지원합니다. ISequentialStream::Read 메서드는 긴 데이터를 한 번에 한 블록씩 읽고 ISequentialStream::Write는 긴 데이터를 한 번에 한 블록씩 데이터베이스에 씁니다. 자세한 내용은 BLOB 및 OLE 개체를 참조하십시오.

  • ODBC

    ODBC에는 긴 데이터의 ODBC 데이터 형식을 처리하기 위한 "실행 시 데이터"라는 기능이 있습니다. 긴 데이터의 ODBC 데이터 형식은 SQL_WLONGVARCHAR(ntext), SQL_LONGVARCHAR(text) 및 SQL_LONGVARBINARY(image)입니다. 이러한 데이터 형식은 프로그램 변수에 바인딩됩니다. 그런 다음 SQLGetData가 호출되어 긴 데이터를 한 번에 한 블록씩 가져오고 SQLPutData가 호출되어 긴 데이터를 한 번에 한 블록씩 전송합니다. 자세한 내용은 text 및 image 열 관리를 참조하십시오.

  • DB-Library

    DB-Library 응용 프로그램도 ntext, text 및 image 열을 프로그램 변수에 바인딩합니다. DB-Library 함수인 dbtxtptr을 사용하여 데이터베이스에서 긴 열이 발생한 위치에 대한 포인터를 가져오고 dbreadtext를 사용하여 긴 데이터를 한 번에 한 블록씩 읽습니다. dbwritetext, dbupdatetextdbmoretext 등의 함수는 긴 데이터를 한 번에 한 블록씩 쓰는 데 사용됩니다.

    [!참고]

    DB-Library에서 행 내부 텍스트 액세스는 지원되지 않습니다.

자세한 내용은 텍스트 및 이미지 함수(Transact-SQL)를 참조하십시오.