Convertir nvarchar(max)y volver a ntexthace que la vida sea más simple desde el punto de vista del código, pero significa convertir y reescribir todo el valor (quizás muy grande), con toda la CPU y la sobrecarga de registro que eso implica.
Una alternativa es usar UPDATETEXT. Esto está en desuso, al igual que ntext, pero puede reducir significativamente la sobrecarga de registro. En el lado negativo, significa usar punteros de texto, y solo funciona en una fila a la vez.
El siguiente código de ejemplo usa un cursor para evitar esa limitación, y lo usa en PATINDEXlugar de, CHARINDEXdado que el primero es una de las pocas funciones que funcionan directamente con ntext:
Data de muestra
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.')
);
Declaración del cursor
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;
Bucle de procesamiento
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;