使用表对列执行多个REPLACE调用

时间:2014-03-17 00:32:16

标签: mysql replace

我需要创建一个SQL解决方案来对字符串列执行多个搜索和替换操作。搜索/替换术语的数量是动态的,以及搜索和替换术语本身。

出于这个原因,我计划使用包含所有搜索和替换所需术语的表。因此基础设置涉及两个表,一个包含具有以下模式的字符串列的通用表:

CREATE TABLE GENERAL_TABLE (
    ID           INTEGER NOT NULL
  , SOURCE_TEXT  VARCHAR(1024) NOT NULL
  , CONSTRAINT PRIMARY KEY (ID)
);

以及使用以下架构搜索和替换术语表:

CREATE TABLE SEARCH_REPLACE (
    SEARCH_TERM   VARCHAR(256) NOT NULL
  , REPLACE_TERM  VARCHAR(256) NOT NULL
);

是否有办法将每个SEARCH_TERM值中的所有SOURCE_TEXT值替换为相应的REPLACE_TERM值?

例如,如果GENERAL_TABLE填充了以下记录:

ID  SOURCE_TEXT
--  -------------------------------------------------------
 1  honesty is the best policy.
 2  honesty is the best policy - when there is money in it.
 3  we are all worms. but i believe that i am a glow-worm.
 4  believe you can and you're halfway there.
 5  ambition must be made to counteract ambition.
 6  run, run as fast as you can.

SEARCH_REPLACE填充了以下记录:

SEARCH_TERM  REPLACE_TERM
-----------  ------------
honesty      taco tuesday
policy       sale
money        cheese
worm         robot
believe      know
ambition     loans
run          swim

然后在所有搜索和替换之后GENERAL_TABLE中的所需结果是:

ID  SOURCE_TEXT
--  -----------------------------------------------------------
 1  taco tuesday is the best sale.
 2  taco tuesday is the best sale - when there is cheese in it.
 3  we are all robots. but i know that i am a glow-robot.
 4  know you can and you're halfway there.
 5  loans must be made to counteract loans.
 6  swim, swim as fast as you can.

整个过程将由具有DBA特权的用户执行。因此,任何解决方案都可以根据需要使用DDL命令。

3 个答案:

答案 0 :(得分:0)

  • 将SEARCH_Replace中的所有行值获取为字符串变量+包含替换函数

    声明@str nvarchar(2000)
    设置@str ='替换(SOURCE_TEXT,'
    从@SEARCH_REPLACE中选择前1个@str = @str +''''+ SEARCH_TERM +''','''+ REPLACE_TERM +''')' - 第一行 从@SEARCH_REPLACE选择@str ='替换('+ @str +','''+ SEARCH_TERM +''','''+ REPLACE_TERM +'''),其中SEARCH_TERM不喜欢'诚实' - 其他行

  • 为@str

    构建查询

    声明@sql nvarchar(4000)
    设置@sql ='从GENERAL_TABLE'选择Source_Text,'+ @str +'

  • 执行@sql

    EXEC(@sql)

  • 表格结果

    NEW_TEXT
    -------------------------------------------------- -------
    塔科周二是最好的销售 taco周二是最好的销售 - 当它有奶酪时。
    我们都是机器人。但我知道我是一个发光机器人 知道你可以而且你已经到了一半。
    必须提供贷款以抵消贷款 游泳,尽可能快地游泳。

答案 1 :(得分:0)

您可以尝试使用选择

进行更新
UPDATE GENERAL_TABLE dest,
    (SELECT 
        SEARCH_TERM, REPLACE_TERM
    FROM
        SEARCH_REPLACE) src 
SET 
    dest.SOURCE_TEXT = REPLACE(dest.SOURCE_TEXT,
        src.SEARCH_TERM,
        src.REPLACE_TERM)

干杯

答案 2 :(得分:0)

这是一个利用工作表存储连续搜索/替换结果的解决方案。该解决方案涉及三个SQL步骤。首先创建一个表来执行所有中间工作,其中SOURCE_TEXT是原始GENERAL_TABLE值,TARGET_TEXT是搜索/替换结果:

-- workspace table
-- all search/replace work is done in this table
DROP TABLE IF EXISTS GENERAL_TABLE_WORK;
CREATE TABLE GENERAL_TABLE_WORK (
    ID           INTEGER NOT NULL
  , SOURCE_TEXT  VARCHAR(1024) NOT NULL
  , TARGET_TEXT  VARCHAR(1024) NULL
  , LAST_ID      INTEGER NULL
  , REC_NUM      INTEGER
  , CONSTRAINT PRIMARY KEY (ID, REC_NUM)
);

接下来,将GENERAL_TABLESEARCH_REPLACE表一起使用,并将其用作表格,将所有搜索/替换结果选择到工作区表中。连接中还使用控制表来维持连续搜索/替换结果之间的状态:

-- perform search/replace on source text
-- creating one record for each search/replace value
-- using the last replace results as the next input string
-- R is used solely to intialize variables
-- the ordering in A is crucial to maintain the correct variable state
INSERT INTO GENERAL_TABLE_WORK (
  SELECT
      A.ID AS ID
    , A.SOURCE_TEXT AS SOURCE_TEXT
    , CAST(IF(@lastid = A.ID,
       @text := REPLACE(@text, A.SEARCH_TERM, A.REPLACE_TERM),
       @text := REPLACE(A.SOURCE_TEXT, A.SEARCH_TERM, A.REPLACE_TERM)) AS CHAR)
       AS TARGET_TEXT
    , @lastid := A.ID AS LAST_ID
    , @record := @record + 1 AS REC_NUM
  FROM
    (SELECT G.ID AS ID, G.SOURCE_TEXT AS SOURCE_TEXT,
       S.SEARCH_TERM AS SEARCH_TERM, S.REPLACE_TERM AS REPLACE_TERM
       FROM GENERAL_TABLE G JOIN SEARCH_REPLACE S
       ORDER BY G.ID, S.SEARCH_TERM) A
    JOIN (SELECT @lastid := NULL, @text := NULL, @record := 0) R
);

最后,GENERAL_TABLE值将替换为GENERAL_TABLE_WORK中为每条原始记录找到的最后一次搜索/替换结果:

-- copy target text back to original table
-- only taking the highest rec_num record for each id.
UPDATE GENERAL_TABLE G
  JOIN
    (SELECT W1.* FROM GENERAL_TABLE_WORK W1
     LEFT OUTER JOIN GENERAL_TABLE_WORK W2 ON (W1.ID = W2.ID AND W2.REC_NUM > W1.REC_NUM)
     WHERE W2.ID IS NULL
    ) A ON (G.ID = A.ID)
SET G.SOURCE_TEXT = A.TARGET_TEXT
WHERE NOT A.TARGET_TEXT = A.SOURCE_TEXT
;