SQL: заменить часть столбца в нескольких строках на основе второй таблицы - PullRequest
4 голосов
/ 26 августа 2011

У меня есть таблица (pages), которая содержит свойства для веб-страниц, включая столбец для самого содержимого страницы, столбец NVARCHAR(MAX).

В этом столбце мне нужно найти и заменить кучу текстовых строк и заменить их другими текстовыми строками; эти корреляции находятся во второй таблице (moving) со столбцами oldValue и newValue.

Так, например, если я начинаю с двух таблиц, подобных этой:

таблица страниц:

ID Content
1  Words words Ancient words
2  Blah blah OutWithTheOld blah
3  Etc etc Useless etc

подвижный стол:

OldValue          NewValue
Ancient           Better
OutWithTheOld     InWithTheNew
Useless           Useful

... Мне нужен способ сделать Replace, который оставляет таблицу страниц следующим образом:

ID Content
1  Words words Better words
2  Blah blah InWithTheNew blah
3  Etc etc Useful etc

Возможно, что данная запись в таблице страниц потребует многократных замен, и нет способа предсказать, будет ли запись страниц не иметь ни одной, ни одной, или много необходимых замен, или какие значения из moving.oldvalue будут найдены и должны быть заменены.

Я использую SQL Server 2008, и я довольно новичок в этом. Большое спасибо заранее за любую помощь, которую вы можете оказать!

Ответы [ 2 ]

3 голосов
/ 26 августа 2011

Вот метод с одним оператором без курсора, который использует CTE:

WITH CTE(iteration, page_id, content) AS (
    SELECT
        0,
        P.page_id,
        REPLACE(P.content, M1.old_value, M1.new_value)
    FROM
        Pages P
    INNER JOIN Moving M1 ON
        P.content LIKE '%' + M1.old_value + '%'
    WHERE
        NOT EXISTS (SELECT * FROM Moving M2 WHERE P.content LIKE '%' + M2.old_value + '%' AND M2.moving_id < M1.moving_id)
    UNION ALL
    SELECT
        CTE.iteration + 1,
        CTE.page_id,
        REPLACE(CTE.content, M3.old_value, M3.new_value)
    FROM
        CTE
    INNER JOIN Moving M3 ON
        CTE.content LIKE '%' + M3.old_value + '%'
    WHERE
        NOT EXISTS (SELECT * FROM Moving M4 WHERE CTE.content LIKE '%' + M4.old_value + '%' AND M4.moving_id < M3.moving_id)
)
UPDATE P2
SET
    content = CTE1.content
FROM
    Pages P2
INNER JOIN CTE CTE1 ON
    CTE1.page_id = P2.page_id AND
    NOT EXISTS (SELECT * FROM CTE CTE2 WHERE page_id = P2.page_id AND CTE2.iteration > CTE1.iteration)
2 голосов
/ 26 августа 2011

Попробуйте это

DECLARE @OldV NVARCHAR(32)    -- Adjust for your field sizes in MOVING
DECLARE @NEWV NVARCHAR(32)

DECLARE db_cursor CURSOR FOR  
SELECT *
FROM Moving

OPEN db_cursor   
FETCH NEXT FROM db_cursor INTO @OldV,@newV

WHILE @@FETCH_STATUS = 0   
BEGIN   
    UPDATE Pages SET content=REPLACE(content,@oldV,@NewV)
      WHERE content LIKE '%'+@OldV+'%'
       FETCH NEXT FROM db_cursor INTO @oldV,@NewV
END   

CLOSE db_cursor   
DEALLOCATE db_cursor

Хотя я обычно не люблю курсоры, это должно помочь вам

...