【问题标题】:REGEXP Bases Replace not working in MySQL ProcedureREGEXP Bases Replace 在 MySQL 过程中不起作用
【发布时间】:2017-08-28 04:57:09
【问题描述】:

我有一组关键字,我想在表格的列中更改它们出现的位置。所以有一个主表和关键字表,它有 2 列:要查找的关键字和将其更改为的内容。因此,例如,有一行

findtxt repltxt LTD$有限公司

然后我有一个程序,其中引用的重要部分如下:

DECLARE cur1 CURSOR FOR SELECT findtxt,repltxt FROM keywords ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=1;
SET done = 0;
OPEN cur1;

myLoop: LOOP
    FETCH cur1 INTO ftxt,rtxt;      
    IF done = 1 THEN 
        LEAVE igmLoop; 
    END IF;
    SET @t1 = CONCAT('UPDATE ',tbl,' SET ',sanecol,' = REPLACE(',sanecol,',?,','?) WHERE ',sanecol,' REGEXP ?'); 

    PREPARE stmt FROM @t1;

    SET @ftxt = ftxt;
    SET @rtxt = rtxt;
    EXECUTE stmt USING @ftxt,@rtxt,@ftxt; 
    DEALLOCATE PREPARE stmt;
END LOOP myLoop;
CLOSE cur1;

sanecol 和 tbl 作为参数传递到表示要更改的列和具有该列的表的过程中。

此过程循环运行所有记录(我知道是因为它需要一段时间),但没有错误结束。然而关键字并没有改变(例如 LTD 不会变成 LIMITED。)

我做错了什么?

我已经测试通过

来隔离问题
SET @t2 = CONCAT('UPDATE ',tbl,' SET idd = 1 WHERE ',sanecol,' REGEXP ?'); 

其中 idd 只是为确保 REGEXP 正常工作而创建的测试标志。它确实是通过将 LIM 或 LTD 的每条记录的 idd 列设置为 1。

所以问题出在这部分代码上:

CONCAT('UPDATE ',tbl,' SET ',sanecol,' = REPLACE(',sanecol,',?,','?)

替换只是不起作用。

表中要替换的样本数据

id        replacecol
1         FOREVER UNITED LTD
2         APPLE DEVICES LIMITED
3         QUICKFIX DESIGNS LIM
4         FINANCIAL TIMES LTD

这应该改为:

id        replacecol
1         FOREVER UNITED LIMITED
2         APPLE DEVICES LIMITED
3         QUICKFIX DESIGNS LIMITED
4         FINANCIAL TIMES LIMITED

【问题讨论】:

  • 我怀疑您的根本问题是您将关键字存储为分隔列表,而不是存储在每个关键字一行的表中。
  • 它在表格中:我已编辑添加屏幕截图。
  • 你认为像“BEAUTI SLIM”这样的名字会发生什么?也许是“BEAUTI SLIMITED”?
  • 那些将被忽略,因为在关键字表中 LIM$ 和 LTD$ 之前有一个空格。我现在可以接受这种治疗。

标签: mysql regex stored-procedures replace prepared-statement


【解决方案1】:

尝试类似:

mysql> DROP PROCEDURE IF EXISTS `sp_test`;
Query OK, 0 rows affected (0.00 sec)

mysql> DROP TABLE IF EXISTS `keywords`, `to_replace`;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE IF NOT EXISTS `to_replace` (
    ->  `id` BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    ->  `text` VARCHAR(255) NOT NULL
    -> );
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE IF NOT EXISTS `keywords` (
    ->  `id` BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    ->  `regexptxt` VARCHAR(255) NOT NULL,
    ->  `findtxt` VARCHAR(255) NOT NULL,
    ->  `repltxt` VARCHAR(255) NOT NULL
    -> );
Query OK, 0 rows affected (0.01 sec)

mysql> INSERT INTO `to_replace` (`text`)
    ->  VALUES ('LTD$ AAAA'),
    ->         ('BBBB LIM$'),
    ->         ('AAAA LTD$ LIM$ BBBB'),
    ->         ('FOREVER UNITED LTD'),
    ->         ('APPLE DEVICES LIMITED'),
    ->         ('QUICKFIX DESIGNS LIM'),
    ->         ('FINANCIAL TIMES LTD'),
    ->         ('BEAUTI SLIM'),
    ->         ('FINANCIAL TIMES LTD & FOREVER UNITED LTD'),
    ->         ('FOREVER UNITED LTD & QUICKFIX DESIGNS LIM');
Query OK, 10 rows affected (0.00 sec)
Records: 10  Duplicates: 0  Warnings: 0

mysql> INSERT INTO `keywords`
    ->    (`regexptxt`, `findtxt`, repltxt)
    ->  VALUES
    ->    (' LTD$', 'LTD', 'LIMITED'),
    ->    (' LIM$', 'LIM', 'LIMITED');
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> DELIMITER //

mysql> CREATE PROCEDURE `sp_test`(`tbl` VARCHAR(64), `sanecol` VARCHAR(64))
    ->  BEGIN
    ->    DECLARE `done` BOOL DEFAULT FALSE;
    ->    DECLARE `retxt`, `ftxt`, `rtxt` VARCHAR(255) DEFAULT '';
    ->  
    ->    DECLARE `cur1` CURSOR FOR
    ->    SELECT `regexptxt`, `findtxt`, `repltxt`
    ->    FROM `keywords`;
    ->  
    ->    DECLARE CONTINUE HANDLER FOR NOT FOUND SET `done` := TRUE;
    ->  
    ->    OPEN `cur1`;
    ->  
    ->    `myLoop`: LOOP
    ->      FETCH `cur1` INTO `retxt`, `ftxt`, `rtxt`;
    ->      IF `done` THEN
    ->        CLOSE `cur1`;
    ->        LEAVE `myLoop`;
    ->      END IF;
    ->  
    ->      SET @`t1` = CONCAT('UPDATE `', `tbl`,'`
    '>                          SET `', `sanecol`, '` = REPLACE(`', `sanecol`, '`, ?, ?)
    '>                          WHERE `', `sanecol`, '` REGEXP ?');
    ->      PREPARE `stmt` FROM @`t1`;
    ->      SET @`ftxt` = `ftxt`,
    ->          @`rtxt` = `rtxt`,
    ->          @`retxt` = `retxt`;
    ->      EXECUTE `stmt` USING @`ftxt`, @`rtxt`, @`retxt`;
    ->      DEALLOCATE PREPARE `stmt`;
    ->    END LOOP `myLoop`;
    ->  END//
Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER ;

mysql> SELECT `id`, `text`
    ->  FROM `to_replace`;
+----+-------------------------------------------+
| id | text                                      |
+----+-------------------------------------------+
|  1 | LTD$ AAAA                                 |
|  2 | BBBB LIM$                                 |
|  3 | AAAA LTD$ LIM$ BBBB                       |
|  4 | FOREVER UNITED LTD                        |
|  5 | APPLE DEVICES LIMITED                     |
|  6 | QUICKFIX DESIGNS LIM                      |
|  7 | FINANCIAL TIMES LTD                       |
|  8 | BEAUTI SLIM                               |
|  9 | FINANCIAL TIMES LTD & FOREVER UNITED LTD  |
| 10 | FOREVER UNITED LTD & QUICKFIX DESIGNS LIM |
+----+-------------------------------------------+
10 rows in set (0.00 sec)

mysql> CALL `sp_test`('to_replace', 'text');
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT `id`, `text`
    ->  FROM `to_replace`;
+----+--------------------------------------------------+
| id | text                                             |
+----+--------------------------------------------------+
|  1 | LTD$ AAAA                                        |
|  2 | BBBB LIM$                                        |
|  3 | AAAA LTD$ LIM$ BBBB                              |
|  4 | FOREVER UNITED LIMITED                           |
|  5 | APPLE DEVICES LIMITED                            |
|  6 | QUICKFIX DESIGNS LIMITED                         |
|  7 | FINANCIAL TIMES LIMITED                          |
|  8 | BEAUTI SLIM                                      |
|  9 | FINANCIAL TIMES LIMITED & FOREVER UNITED LIMITED |
| 10 | FOREVER UNITED LTD & QUICKFIX DESIGNS LIMITED    |
+----+--------------------------------------------------+
10 rows in set (0.00 sec)

【讨论】:

  • 谢谢,我会试一试,但我发现一个明显的误解。 to_replace 表不会包含这些值。 sanecol 列的公司名称以不一致的方式书写,例如记录可能有 MYCOMPANY LTD、HISCOMPANY LIMITED、THEIRCOMPANY LIM。正则表达式中的 $ 用于在 LIM 和 LTD 出现在字段末尾时进行隔离。因此,该过程应该从keywords 表的findtxt 列中获取通用的正则表达式描述,并替换为从相应的repltxt 列中获取的统一拼写。列中将没有$
  • @user1729972:您能添加一些真实的样本数据吗?您期望最终结果如何?。
  • 嗨,我通过编辑原始帖子添加了示例数据。它在底部。
  • 问题肯定出在REPLACE ...?...?部分。我添加了一些关于刚刚进行的故障排除的信息
  • @user1729972:更新了答案。它可能不是您期望的答案,但它可以帮助您获得最终解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
  • 1970-01-01
  • 1970-01-01
  • 2013-11-03
  • 2018-03-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多