SQL Server - Thao tác chuỗi và cột NTEXT


11

Tôi có một bảng với một NTEXTcột được gọi comments. Tôi có một chuỗi thứ hai, hãy gọi nó là anothercomment(a varchar) cần đặt bên trong một commentschuỗi nhất định sau từ đó UPDATEHERE.

Đúc để nvarchar(max)cắt ngắn commentschuỗi, vì vậy tôi không thể sử dụng các lượt thích CHARINDEX()( Msg 8152, Level 16, State 10, Line 2 String or binary data would be truncated.). Tôi đã sử dụng datalength()để kiểm tra xem có vài nghìn cột có> 8000 ký tự.

Một ví dụ về những gì tôi muốn đạt được (mặc dù với chuỗi dài hơn nhiều):

bình luận - This is a test UPDATEHERE This is the end of the test

một vấn đề khác - . This is inserted.

Chuỗi kết quả - This is a test UPDATEHERE. This is inserted. This is the end of the test

Tôi nhận ra rằng điều này là tầm thường với một bình thường varchar()/ nvarchar(), nhưng ntextlà một cơn ác mộng hoàn toàn và hoàn toàn để làm việc với. Tôi nhận ra đó là loại dữ liệu không dùng nữa, nhưng tôi đã không viết ứng dụng này.

Câu trả lời:


8

Chuyển đổi thành nvarchar(max)nên hoạt động trừ khi bạn đang làm gì đó sai vớiCHARINDEX()

Hãy thử đoạn mã này, nó sẽ xuất ra những gì bạn muốn.

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

Cảm ơn đi ra ngoài với Andriy M vì đã giúp đỡ với REPLICATEtuyên bố.


10

Chuyển đổi sang nvarchar(max)và quay lại để ntextlàm cho cuộc sống đơn giản hơn từ quan điểm mã, nhưng điều đó có nghĩa là chuyển đổi và viết lại toàn bộ giá trị (có lẽ rất lớn), với tất cả chi phí CPU và ghi nhật ký.

Một cách khác là sử dụng UPDATETEXT. Điều này không được chấp nhận, giống như ntext, nhưng nó có thể làm giảm đáng kể chi phí đăng nhập. Mặt khác, nó có nghĩa là sử dụng các con trỏ văn bản và nó chỉ hoạt động trên một hàng tại một thời điểm.

Mã ví dụ sau sử dụng một con trỏ để khắc phục giới hạn đó và sử dụng PATINDEXthay vì vì CHARINDEXtrước đây là một trong số ít các hàm hoạt động trực tiếp với ntext:

Dữ liệu mẫu

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

Khai báo con trỏ

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;

Vòng lặp xử lý

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;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.