SQL Server - NTEXT sütunları ve dize işleme


11

Adlı bir NTEXTsütun ile bir tablo var comments. İkinci bir dize var, diyelim ki anothercomment(a varchar) commentskelimeden sonra belirli bir dize içine yerleştirilmesi gerekir UPDATEHERE.

Dizeyi nvarchar(max)kısaltmak için döküm comments, bu yüzden beğenilerini kullanamıyorum CHARINDEX()( Msg 8152, Level 16, State 10, Line 2 String or binary data would be truncated.). datalength()> 8000 karakter olan birkaç bin sütun olup olmadığını kontrol etmek için kullandım .

Ne elde etmek istediğime bir örnek (çok daha uzun dizelerle de olsa):

yorumlar - This is a test UPDATEHERE This is the end of the test

başka bir yorum - . This is inserted.

Sonuç dizesi - This is a test UPDATEHERE. This is inserted. This is the end of the test

Bunun normal varchar()/ ile önemsiz olduğunu anlıyorum nvarchar(), ancak ntextçalışmak için tam ve mutlak bir kabus. Kullanımdan kaldırılmış bir veri türü olduğunun farkındayım, ancak söz konusu uygulamayı yazmadım.

Yanıtlar:


8

İle nvarchar(max)yanlış bir şey yapmadıkça işe dönüşmeliCHARINDEX()

Bu kod snippet'ini deneyin, istediğiniz çıktıyı almalıdır.

-- 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];

Açıklamaya yardımcı olduğu için Andriy M'ye teşekkürler REPLICATE.


10

Buna dönüş nvarchar(max)ve geri dönüş ntext, hayatı kod açısından daha basit hale getirir, ancak tüm CPU ve kayıt yükü anlamına gelen tüm (belki de çok büyük) değerin dönüştürülmesi ve yeniden yazılması anlamına gelir.

Bir alternatif kullanmaktır UPDATETEXT. Bu, tıpkı olduğu gibi kullanımdan kaldırılmıştır, ntextancak günlük tutma yükünü önemli ölçüde azaltabilir. Aşağı yönde, metin işaretçileri kullanmak anlamına gelir ve her seferinde yalnızca bir satırda çalışır.

Aşağıdaki örnek kod, bu sınırlamaya geçici bir çözüm bulmak için bir imleç kullanır ve PATINDEXbunun yerine ilkiyle doğrudan çalışan birkaç işlevdenCHARINDEX biri olduğu için kullanır :ntext

Örnek veri

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.')
);

İmleç bildirimi

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;

İşleme döngüsü

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;
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.