【问题标题】:MYSQL use of CONCAT and SUBSTRING with http and https URLS in databaseMYSQL 在数据库中使用带有 http 和 https URLS 的 CONCAT 和 SUBSTRING
【发布时间】:2018-10-11 23:59:32
【问题描述】:

这个问题围绕着使用 CONCAT 和 SUBSTRINGS 来更新 mysql TABLE 中的内容

如果我有一个存储在 mysql 数据库中的链接,该链接由

https://this.example.com/work-a-link.php?https://that.example.com/thisisworthkeeping.php

以下代码将删除第一个实例,并为该 url 的第二个实例保留前缀 http:// url(理论上在这种情况下它应该是 https:// - 因为第二个 URL 以https://

DROP TABLE IF EXISTS content_temp;
CREATE TABLE content_temp AS SELECT * FROM content GROUP BY Title ORDER BY ID ASC;
UPDATE content_temp SET link = CONCAT('http://', SUBSTRING_INDEX(link, 'https://', -1));
UPDATE content_temp SET link = CONCAT('http://', SUBSTRING_INDEX(link, 'http://', -1));
UPDATE content_temp SET link=replace(link,'http://https://','http://');
UPDATE content_temp SET link=replace(link,'http://http://','http://');

这就是我正在寻求可以帮助我或为我指明正确方向的人的问题 - 我希望在第二种情况下将任何 https:// 保留为 https:// - 而我的双胞胎代码将其更改为http://

我想要完成的是尊重并保留第二个实例 - 无论是 http 还是 https。

所有这一切中唯一的其他随机因素...是第一个实例可能是 http 或 https

因此,重新调整此代码的最终结果将是:

(一)

http://this.example.com/work-a-link.php?http://that.example.com/thisisworthkeeping.php 

会给http://that.example.com/thisisworthkeeping.php

(B)

http://this.example.com/work-a-link.php?https://that.example.com/thisisworthkeeping.php 

会给https://that.example.com/thisisworthkeeping.php

(C)

https://this.example.com/work-a-link.php?http://that.example.com/thisisworthkeeping.php 

会给http://that.example.com/thisisworthkeeping.php

(D)

https://this.example.com/work-a-link.php?https://that.example.com/thisisworthkeeping.php 

会给https://that.example.com/thisisworthkeeping.php

【问题讨论】:

  • 所有要更改的link 值是否包含字符串.php?http?你可以在? 上拆分吗?
  • 用反引号或缩进四个空格包围的代码块是你的朋友:它们中的 URL 不会被制成链接,因此它们不会被反垃圾邮件捕获。此外,还有一个保留域example.com 用于这种解释。

标签: mysql sql-update substring concat


【解决方案1】:

看起来您总共有四种可能的组合我们正在研究。 第一个可以是“http”或“https”,第二个可以是“http”或“https”。四种可能的组合:

http:/  http:/
http:/  https:/
https:/ http:/
https:/ https:/

几个建议:

首先,在我们执行 UPDATE 语句之前,我们不确定它是否会按照我们的意图执行,我们应该编写一个 SELECT 语句来测试表达式.让我们看看表达式的结果,这样我们就可以在各种测试条件下验证它是否按照我们的意图进行。

其次,应该可以分离出组合(四种可能性)。如果我们正在应用的更改是“删除”第一个 http/https 只留下一次出现......那么我们应用于其中一个子集的修改不会产生一行然后移动到不同的子集中。 (我明白我的意思,它可能是乱码。)

如果我有这样的行

http 1   https 2 

我通过更新将其更改为

https 2 

然后对行进行后续运行,这不会匹配对

的检查
https  https 

因为字符串中只出现了一次 http。


假设我们只对link 字符串包含两次http:// / https:// 的行感兴趣

我们可以使用正则表达式做一些匹配,或者我们可以用一些LIKE比较来伪造它

SELECT t.link
     , t.link LIKE '%http://%http://%'   AS c1 
     , t.link LIKE '%http://%https://%'  AS c2 
     , t.link LIKE '%https://%http://%'  AS c3 
     , t.link LIKE '%https://%https://%' AS c4
  FROM (

SELECT 'http://somedomain.com/work-a-link.php?http://someotherdomain.com/thisisworthkeeping.php' AS link
UNION ALL
SELECT 'http://somedomain.com/work-a-link.php?https://someotherdomain.com/thisisworthkeeping.php'
UNION ALL
SELECT 'https://somedomain.com/work-a-link.php?http://someotherdomain.com/thisisworthkeeping.php'
UNION ALL 
SELECT 'https://somedomain.com/work-a-link.php?https://someotherdomain.com/thisisworthkeeping.php'

       ) t
 WHERE t.link LIKE '%http%://%http%://%'
   AND t.link NOT LIKE '%http%://%http%://%http%://%'  

返回类似这样的内容(在链接值中进行一些字符串替换以缩短它们)...

link                                                           c1  c2  c3  c4
-------------------------------------------------------------- --  --  --  --
http://somedomain.com/walp?http://someotherdomain.com/tiwkp     1   0   0   0
http://somedomain.com/walp?https://someotherdomain.com/tiwkp    0   1   0   0
https://somedomain.com/walp?http://someotherdomain.com/tiwkp    0   0   1   0
https://somedomain.com/walp?https://someotherdomain.com/tiwkp   0   0   0   1

我们在WHERE 子句中添加了一个条件,以“过滤掉”出现两次以上“http[s]://”的任何 URL。 (这里有一点点捏造,% 通配符可以匹配任意数量的字符,所以我们不完全检查 https:// 和 http:// ...(再次,我们可以实现一个常规表达式(REGEXP 或 RLIKE)比较更准确。

但请注意我们是如何设法将值链接“分类”为 c1、c2、c3 和 c4。

确认每个链接都属于一个类别, 我们可以在 SELECT 列表中包含一个额外的表达式

     , CASE 
       WHEN t.link LIKE '%http://%http://%'   THEN 'c1'
       WHEN t.link LIKE '%http://%https://%'  THEN 'c2'
       WHEN t.link LIKE '%https://%http://%'  THEN 'c3' 
       WHEN t.link LIKE '%https://%https://%' THEN 'c4'
       ELSE NULL
       END

如果我们找到匹配的 WHEN 条件,我们会返回 THEN,然后我们就完成了。 (如果存在重叠,即属于多个类别的链接,我们将不会在此表达式中看到它。)

link                                                            c   c1  c2  c3  c4
-------------------------------------------------------------- --  --  --  --  --
http://somedomain.com/walp?http://someotherdomain.com/tiwkp    c1   1   0   0   0
http://somedomain.com/walp?https://someotherdomain.com/tiwkp   c2   0   1   0   0
https://somedomain.com/walp?http://someotherdomain.com/tiwkp   c3   0   0   1   0
https://somedomain.com/walp?https://someotherdomain.com/tiwkp  c4   0   0   0   1

我们可以使用各种link 值、各种模式进行测试,并验证我们匹配的“分类”是否按我们预期的方式工作。

(这种使用 SELECT 语句来测试表达式的技术,尤其是我们不熟悉的函数......使用 SUBSTRING_INDEX,当找不到搜索字符串时返回什么?REPLACE 函数是否区分大小写?和等等。)

我们可以调整和调整、试验并找到正确的组合,让它按照我们想要的方式工作。一旦我们明白了,

我们可以在 SELECT 列表中包含另一个表达式。我们将复制我们刚刚添加的那个,但是这一次,我们将包含一个不同的表达式,而不是返回一个字面量,一个执行 SUBSTRING_INDEXREPLACE 函数的表达式。

由于我们正在运行SELECT,因此我们知道我们不会破坏/修改表格的内容。我们只是在测试一些表达式,看看它们会返回什么。

     , CASE 
       WHEN t.link LIKE '%http://%http://%'    -- 'c1'
       THEN CONCAT('http://', SUBSTRING_INDEX(t.link, 'http://', -1))

       WHEN t.link LIKE '%http://%https://%'   -- 'c2'
       THEN CONCAT('https://', SUBSTRING_INDEX(t.link, 'https://', -1))

       WHEN t.link LIKE '%https://%http://%'   -- 'c3' 
       THEN CONCAT('http://', SUBSTRING_INDEX(t.link, 'http://', -1))

       WHEN t.link LIKE '%https://%https://%'  -- 'c4'
       THEN CONCAT('https://', SUBSTRING_INDEX(t.link, 'https://', -1))

       ELSE NULL
       END AS new_link

很快我们就会得到这样的结果...

link                                                           new_link 
-------------------------------------------------------------  ---------------------------------
http://somedomain.com/walp?http://someotherdomain.com/tiwkp    http://someotherdomain.com/tiwkp
http://somedomain.com/walp?https://someotherdomain.com/tiwkp   https://someotherdomain.com/tiwkp
https://somedomain.com/walp?http://someotherdomain.com/tiwkp   http://someotherdomain.com/tiwkp
https://somedomain.com/walp?https://someotherdomain.com/tiwkp  https://someotherdomain.com/tiwkp

一旦我们有一个表达式工作,它返回一个我们想要分配给列的new_link 值,代替link 值,

(我们首先针对表的测试副本运行它)

我们可以将 SELECT 语句转换为 UPDATE

SELECT ... FROM 替换为UPDATE

并添加一个SET 子句以将 new_link 表达式分配给链接

(将 ELSE 中的 NULL 替换为对该列的引用,因此,如果我们遇到了在 CASE 中检查的所有条件,我们将不会更改该行...)

UPDATE mytesttable t
   SET t.link
     = CASE 
       WHEN t.link LIKE '%http://%http://%'    -- 'c1'
       THEN CONCAT('http://', SUBSTRING_INDEX(t.link, 'http://', -1))

       WHEN t.link LIKE '%http://%https://%'   -- 'c2'
       THEN CONCAT('https://', SUBSTRING_INDEX(t.link, 'https://', -1))

       WHEN t.link LIKE '%https://%http://%'   -- 'c3' 
       THEN CONCAT('http://', SUBSTRING_INDEX(t.link, 'http://', -1))

       WHEN t.link LIKE '%https://%https://%'  -- 'c4'
       THEN CONCAT('https://', SUBSTRING_INDEX(t.link, 'https://', -1))

       ELSE t.link
       END
 WHERE t.link LIKE '%http%://%http%://%'  
   AND t.link NOT LIKE '%http%://%http%://%http%://%'  

但是在我们运行 UPDATE 之前,我们应该使用各种链接值测试我们的表达式,包括边缘和角落情况。

再次注意,我写的那些LIKE 比较有可能匹配我们可能不想匹配的不稳定行,例如http://BLAH http DERP :// flurb http://.

看起来也许我们还应该在第二次出现 http 之前检查问号。

我们将使用正则表达式、REGEXP (RLIKE) 比较获得更准确的模式匹配。


主题保持不变...首先使用 SELECT 测试表达式,然后运行 ​​UPDATE。

【讨论】:

    【解决方案2】:

    如果您要更改的所有链接都包含子字符串.php?,您可以这样做:

    UPDATE content_temp SET link = SUBSTRING_INDEX(link, '.php?', -1)
          WHERE link LIKE '%.php?%'
    

    专业提示:WHERE 子句放在UPDATE 操作上总是一个好主意:没有它,SQL 会更新表中的所有行。这可能会破坏表,并且会淹没事务日志。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-25
      • 2014-10-22
      • 2015-05-24
      • 1970-01-01
      • 2013-01-07
      • 1970-01-01
      • 2017-02-10
      相关资源
      最近更新 更多