MYSQL在数据库

时间:2018-05-01 23:17:17

标签: mysql mysqli sql-update substring concat

这个问题围绕使用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

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

(A)

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

2 个答案:

答案 0 :(得分:0)

如果要更改的所有链接都包含子字符串.php?,则可以执行以下操作:

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

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

答案 1 :(得分:0)

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

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

一些建议:

首先,在我们执行UPDATE语句之前,我们不确定它是否会按照我们的意图去做,我们应该在 test SELECT语句em>表达式。这让我们看到了表达式的结果,因此我们可以在各种测试条件下验证它是否正在按照我们的意图行事。

其次,应该可以将组合分开(四种可能性)。如果我们正在应用的更改是“删除”第一个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。