SQL Server-NTEXT 열 및 문자열 조작


11

NTEXT라는 열 이있는 테이블이 comments있습니다. 두 번째 문자열이 있는데 단어 뒤에 주어진 문자열 안에 배치 해야하는 anothercomment(a varchar) 라고 부릅니다 .commentsUPDATEHERE

에 캐스팅 nvarchar(max)자릅니다 comments내가의 좋아하는을 사용할 수 있도록 문자열을 CHARINDEX()( Msg 8152, Level 16, State 10, Line 2 String or binary data would be truncated.). 내가 사용하고 datalength()있는 몇 천 컬럼> 8000 개 문자가 있는지 확인 할 수 있습니다.

달성하려는 것의 예 (더 긴 문자열이더라도) :

코멘트 - This is a test UPDATEHERE This is the end of the test

다른 의견- . This is inserted.

결과 문자열- This is a test UPDATEHERE. This is inserted. This is the end of the test

나는 이것이 정상적인 varchar()/ 사소한 것임을 알고 nvarchar()있지만, 작업하기에는 ntext완전하고 완전한 악몽입니다. 더 이상 사용되지 않는 데이터 유형이라는 것을 알고 있지만 문제의 응용 프로그램을 작성하지 않았습니다.

답변:


8

nvarchar(max)당신이 뭔가 잘못하고 있지 않는 한 변환 은 작동해야합니다CHARINDEX()

이 코드 스 니펫을 사용해보십시오. 원하는 것을 출력해야합니다.

-- Create the table
CREATE TABLE [dbo].[PhilsTable](
    [comment] [ntext] NULL,
    [anothercomment] [nvarchar](50) NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY];

GO

-- insert very long string
INSERT INTO [dbo].[PhilsTable] (comment, anothercomment) VALUES (N'This is a test UPDATEHERE This is the end of the test' + REPLICATE (CAST(N'x' AS nvarchar(max)), 1000000), 'this goes in here');

-- verify data
SELECT DATALENGTH(comment), *  FROM [dbo].[PhilsTable];

-- perform replace
SELECT CAST(REPLACE(CAST(comment AS NVARCHAR(MAX)),'UPDATEHERE','UPDATEHERE' + anothercomment) AS NTEXT) FROM [dbo].[PhilsTable];

DROP TABLE [dbo].[PhilsTable];

성명서 에 도움을 주신 Andriy M 에게 감사드립니다 REPLICATE.


10

로 변환 nvarchar(max)하고 다시에 ntext보기의 코드 포인트에서 메이크업 수명 간단 않지만, 의미 모든 CPU 및 로깅 오버 헤드, 변환 및 전체 (아마도 매우 큰) 값을 재 작성 의미한다.

대안은을 사용하는 것 UPDATETEXT입니다. 이처럼 더 이상 사용되지 ntext않지만 로깅 오버 헤드를 크게 줄일 수 있습니다. 단점은 텍스트 포인터를 사용한다는 것을 의미하며 한 번에 한 행에서만 작동합니다.

다음 예제 코드는 커서를 사용하여 해당 제한을 해결하고 PATINDEX대신 CHARINDEX전자가 직접 작동 하는 몇 가지 기능 중 하나이므로 대신 사용 합니다 ntext.

샘플 데이터

CREATE TABLE dbo.PhilsTable
(
    comment ntext NULL,
    anothercomment nvarchar(50) NULL
);

INSERT dbo.PhilsTable
    (comment, anothercomment)
VALUES 
(
    CONVERT(ntext, 
        N'This is a test UPDATEHERE This is the end of the test ' + 
            REPLICATE (CONVERT(nvarchar(max), N'x'), 1000000)), 
    CONVERT(nvarchar(50), N'. This is inserted.')
),
(
    CONVERT(ntext, 
        N'This is a test UPDATEHERE This is the end of the test ' + 
            REPLICATE (CONVERT(nvarchar(max), N'x'), 1000000)), 
    CONVERT(nvarchar(50), N'. This is inserted.')
),
(
    CONVERT(ntext, 
        N'This is a test UPDATEHERE This is the end of the test ' + 
            REPLICATE (CONVERT(nvarchar(max), N'x'), 1000000)), 
    CONVERT(nvarchar(50), N'. This is inserted.')
);

커서 선언

DECLARE c 
    CURSOR GLOBAL 
    FORWARD_ONLY 
    DYNAMIC 
    SCROLL_LOCKS 
    TYPE_WARNING
FOR
SELECT
    TxtPtr = TEXTPTR(PT.comment),
    Src = PT.anothercomment,
    Offset = PATINDEX(N'%UPDATEHERE%', PT.comment) + LEN(N'UPDATEHERE') - 1
FROM dbo.PhilsTable AS PT
WHERE
    PT.comment LIKE N'%UPDATEHERE%'; -- LIKE works with ntext

OPEN c;

처리 루프

DECLARE 
    @Ptr binary(16),
    @Src nvarchar(50),
    @Offset integer;

SET STATISTICS XML OFF; -- No cursor fetch plans

BEGIN TRANSACTION;

    WHILE 1 = 1
    BEGIN
        FETCH c INTO @Ptr, @Src, @Offset;

        IF @@FETCH_STATUS = -2 CONTINUE; -- row missing
        IF @@FETCH_STATUS = -1 BREAK; -- no more rows

        IF 1 = TEXTVALID('dbo.PhilsTable.comment', @Ptr)
        BEGIN
            -- Modify ntext value
            UPDATETEXT dbo.PhilsTable.comment @Ptr @Offset 0 @Src;
        END;
    END;

COMMIT TRANSACTION;

CLOSE c; DEALLOCATE c;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.