quinta-feira, 4 de julho de 2013

ATUALIZAÇÃO OPÇÕES com LIKE e REGEXP SUBSTRING LOCALIZAR

Original post: http://anothermysqldba.blogspot.com/2013/07/update-options-with-like-regexp.html

Um post no fórum recente me fez parar e pensar por um momento .. 
http://forums.mysql.com/read.php?10, 589573,589573 # msg-589573 

O problema era que o usuário queria atualizar apenas a palavra audi e não a palavra auditor.
Foi resolvido, aproveitando o período de facilidade, uma vez eu parei de tentar usar SUBSTRING e localizar. Eles queriam uma solução rápida e fácil depois de tudo. 


root@localhost [test]> CREATE TABLE `forumpost` (
-> `name` varchar(255) DEFAULT NULL
-> ) ENGINE=InnoDB;

root@localhost [test]> insert into forumpost value ('An auditor drives an audi.'),('An auditor drives a volvo.');

root@localhost [test]> select * from forumpost;
+----------------------------+
| name |
+----------------------------+
| An auditor drives an audi. |
| An auditor drives a volvo. |
+----------------------------+ 


Então agora vamos atualizá-lo a maneira rápida e fácil, aproveitando o período 

root@localhost [test]>UPDATE forumpost SET name = REPLACE(name, 'audi.', 'toyota.') WHERE name LIKE '%audi.';
Query OK, 1 row affected (0.20 sec)
Rows matched: 1 Changed: 1 Warnings: 0

root@localhost [test]> select * from forumpost;
+------------------------------+
| name |
+------------------------------+
| An auditor drives an toyota. |
| An auditor drives a volvo. |
+------------------------------+ 


Mas ... o que acontece com as opções válidas de SUBSTRING e localizar ..... 


root@localhost [test]> insert into forumpost value ('An auditor drives an audi.');
root@localhost [test]> insert into forumpost value ('An auditor drives an audi car');
root@localhost [test]> select * from forumpost;
+-------------------------------+
| name |
+-------------------------------+
| An auditor drives an toyota. |
| An auditor drives a volvo. |
| An auditor drives an audi. |
| An auditor drives an audi car |
+-------------------------------+ 


Primeiro testar suas opções para que você se certificar de que você pode encontrar o que você está depois .. 


root@localhost [test]> SELECT * FROM forumpost WHERE name REGEXP 'audi car$';
+-------------------------------+
| name |
+-------------------------------+
| An auditor drives an audi car |
+-------------------------------+ 

root@localhost [test]> SELECT * FROM forumpost WHERE name LIKE '%audi car%';
+-------------------------------+
| name |
+-------------------------------+
| An auditor drives an audi car |
+-------------------------------+


Isso realmente não faz muito, uma vez que apenas mudou o prazo para a palavra carro.Então continue indo .... 

Precisamos retirar apenas a palavra audi a partir da linha com o carro audi. 

root@localhost [test]> SELECT SUBSTRING(name,-8,4), name FROM forumpost WHERE SUBSTRING(name,-8,4) = 'audi';
+----------------------+-------------------------------+
| SUBSTRING(name,-8,4) | name |
+----------------------+-------------------------------+
| audi | An auditor drives an audi car |
+----------------------+-------------------------------+ 


O SUBSTRING me permitiu puxar os 4 primeiros caracteres depois contei para trás oito caracteres a partir do final. 

Assim que se você não souber a localização dos personagens? 
Para começar, você deve rever seus dados para se certificar de que você sabe o que você está depois. Mas os personagens podem se mover em torno de sua seqüência, então vamos trabalhar com localizar. 

Eu vou adicionar outra linha apenas para testes. 

root@localhost [test]> insert into forumpost value ('An auditor drives an red audi car');
Query OK, 1 row affected (0.04 sec)

root@localhost [test]> select * from forumpost;
+------------------------------------+
| name |
+------------------------------------+
| An auditor drives an toyota. |
| An auditor drives a volvo. |
| An auditor drives an audi. |
| An auditor drives an audi car |
| An auditor drives an audi blue car |
| An auditor drives an red audi car |
+------------------------------------+ 


Portanto, independentemente do fim, podemos ver que a Audi sempre depois de auditor por isso só precisa pular sobre essa palavra. A palavra auditor é o primeiro caractere 8 para pular aqueles. 

root@localhost [test]> SELECT LOCATE('audi', name,8), name FROM forumpost WHERE LOCATE('audi', name,8) > 0 ;
+------------------------+------------------------------------+
| LOCATE('audi', name,8) | name |
+------------------------+------------------------------------+
| 22 | An auditor drives an audi. |
| 22 | An auditor drives an audi car |
| 22 | An auditor drives an audi blue car |
| 26 | An auditor drives an red audi car |
+------------------------+------------------------------------+ 


OK assim que nós encontramos os que são depois. Agora precisamos escrever a instrução de atualização. 

Nós não podemos usar o substituir neste momento. 

UPDATE forumpost SET name = REPLACE(name, LOCATE('audi', name,8), 'mercedes') WHERE LOCATE('audi', name,8) > 0 ;
Query OK, 0 rows affected (0.02 sec)
Rows matched: 4 Changed: 0 Warnings: 0 

Observe que encontrou as linhas, mas não muda nada. 

Então, tente de novo e eu não quero assumir a posição 8. Eu quero que o segundo valor da audi. 
Assim, um teste mostra que com SUBSTRING_INDEX posso pular o primeiro um e usá-CONCAT

SELECT name , CONCAT ( SUBSTRING_INDEX(name, 'audi', 2) , ' mercedes ' , SUBSTRING_INDEX(name, 'audi', -1) ) as newvalue
FROM forumpost
WHERE LOCATE('audi', name,10) > 0 ;
+-----------------------------------+-----------------------------------------+
| name | newvalue |
+-----------------------------------+-----------------------------------------+
| An auditor drives an audi. | An auditor drives an mercedes . |
| An auditor drives an audi. | An auditor drives an mercedes . |
| An auditor drives an audi car | An auditor drives an mercedes car |
| An auditor drives an red audi car | An auditor drives an red mercedes car |
+-----------------------------------+-----------------------------------------+

root@localhost [test]> UPDATE forumpost SET name = CONCAT(SUBSTRING_INDEX(name, 'audi', 2) , ' mercedes ' , SUBSTRING_INDEX(name, 'audi', -1) )
WHERE LOCATE('audi', name,10) > 0 ;
Query OK, 4 rows affected (0.03 sec)
Rows matched: 4 Changed: 4 Warnings: 0

root@localhost [test]> select * from forumpost;
+-----------------------------------------+
| name |
+-----------------------------------------+
| An auditor drives an mercedes . |
| An auditor drives a volvo. |
| An auditor drives an mercedes . |
| An auditor drives an mercedes car |
| An auditor drives an red mercedes car |
+-----------------------------------------+
5 rows in set (0.00 sec) 


Agora, concedido a gramática com o uso de "um" é inválido, mas isso é outra história. 

Mais informações sobre estes podem ser encontrados aqui: