Pouvez-vous analyser une chaîne séparée par des virgules dans une table temporaire dans MySQL en utilisant RegEx?
'1|2|5|6' into temp table with 4 rows.
C’est à peu près la même question que Mysql peut-il fractionner une colonne?
MySQL n'a pas de fonction split string, vous devez donc contourner le problème. Vous pouvez faire n'importe quoi avec les données une fois que vous les avez divisées en utilisant l’une des méthodes énumérées dans la page de réponses ci-dessus.
Vous pouvez faire une boucle sur cette fonction personnalisée et casser quand elle retourne vide, vous devrez jouer et apprendre une syntaxe (ou du moins je le ferais) mais la syntaxe d'une boucle FOR dans mysql est la suivante: http: //www.roseindia.net/sql/mysql-example/for.shtml
Vous pouvez le parcourir en incrémentant la position dans la fonction ci-dessous:
CREATE FUNCTION SPLIT_STR(
x VARCHAR(255),
delim VARCHAR(12),
pos INT
)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
delim, '');
(Crédit: https://blog.fedecarg.com/2009/02/22/mysql-split-string-function/ )
Ce qui devrait retourner '' si aucune correspondance n'est trouvée, alors rompez la boucle si aucune correspondance n'est trouvée. Cela vous permettra d'analyser uniquement avec mysql sur la chaîne divisée et d'exécuter les requêtes d'insertion dans une table temporaire. Mais pourquoi ne pas utiliser un langage de script tel que php pour ce genre de travail? :(
Code pour la syntaxe de la boucle:
DELIMITER $$
CREATE PROCEDURE ABC(fullstr)
BEGIN
DECLARE a INT Default 0 ;
DECLARE str VARCHAR(255);
simple_loop: LOOP
SET a=a+1;
SET str=SPLIT_STR(fullstr,"|",a);
IF str='' THEN
LEAVE simple_loop;
END IF;
#Do Inserts into temp table here with str going into the row
insert into my_temp_table values (str);
END LOOP simple_loop;
END $$
J'ai fait ceci, pour quand vous n'avez pas de valeurs de table et ainsi de suite:
select *
from(
select c, SUBSTRING_INDEX(SUBSTRING_INDEX('1|2|5|6', '|', c+1), '|', -1) as name
from(
SELECT (TWO_1.SeqValue + TWO_2.SeqValue + TWO_4.SeqValue + TWO_8.SeqValue + TWO_16.SeqValue + TWO_32.SeqValue) c
FROM (
SELECT 0 SeqValue UNION ALL SELECT 1 SeqValue) TWO_1
CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 2 SeqValue) TWO_2
CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 4 SeqValue) TWO_4
CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 8 SeqValue) TWO_8
CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 16 SeqValue) TWO_16
CROSS JOIN (SELECT 0 SeqValue UNION ALL SELECT 32 SeqValue) TWO_32
) as b
WHERE c <= (CHAR_LENGTH('1|2|5|6') - CHAR_LENGTH(REPLACE('1|2|5|6', '|', '')))
) as a;
Peut-être pas la meilleure réponse, mais fonctionne sans aide de fonctions et procédures, pas de tables supplémentaires, etc.
Vous pouvez utiliser une expression régulière dans MySQL pour spécifier un modèle pour une recherche complexe. Vous ne pouvez pas analyser les chaînes.
Mais vous pouvez créer une requête INSERT à l'aide de REPLACE et CONCATENATE pour enregistrer des données dans une table temporaire.
DELIMITER $$
CREATE PROCEDURE SPLIT_VALUE_STRING()
BEGIN
SET @String = '1,22,333,444,5555,66666,777777';
SET @Occurrences = LENGTH(@String) - LENGTH(REPLACE(@String, ',', ''));
myloop: WHILE (@Occurrences > 0)
DO
SET @myValue = SUBSTRING_INDEX(@String, ',', 1);
IF (@myValue != '') THEN
/* my code... */
ELSE
LEAVE myloop;
END IF;
SET @Occurrences = LENGTH(@String) - LENGTH(REPLACE(@String, ',', ''));
IF (@occurrences = 0) THEN
LEAVE myloop;
END IF;
SET @String = SUBSTRING(@String,LENGTH(SUBSTRING_INDEX(@String, ',', 1))+2);
END WHILE;
END $$
select distinct
SUBSTRING_INDEX(SUBSTRING_INDEX('1,2,3,4', ',', numbers.n), ',', -1) name
from
(select @rownum := @rownum + 1 as n
from YourTable
cross join (select @rownum := 0) r
) numbers
order by
n
J'ai trouvé une bonne solution pour cela
https://forums.mysql.com/read.php?10,635524,635529
Merci à Peter Brawley
Astuce: convertissez un résultat Group_Concat () sur la chaîne csv en un Insérer ... valeurs ... chaîne:
drop table if exists t;
create table t( txt text );
insert into t values('1,2,3,4,5,6,7,8,9');
drop temporary table if exists temp;
create temporary table temp( val char(255) );
set @sql = concat("insert into temp (val) values ('", replace(( select group_concat(distinct txt) as data from t), ",", "'),('"),"');");
prepare stmt1 from @sql;
execute stmt1;
select distinct(val) from temp;
+------+
| val |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
+------+
Aussi, si vous voulez juste joindre une table à une liste d'identifiant, vous pouvez utiliser l'opérateur LIKE . rejoindre des produits connexes par liste d'identifiant avec l'opérateur LIKE.
SELECT b2.id blog_id, b2.id_list, p.id
FROM (
SELECT b.id,b.text,
CONCAT(
",",
REPLACE(
EXTRACTVALUE(b.text,'//a/@id')
, " ", ","
)
,","
) AS id_list
FROM blog b
) b2
LEFT JOIN production p ON b2.id_list LIKE CONCAT('%,',p.id,',%')
HAVING b2.id_list != ''
Juste parce que j'aime vraiment ressusciter de vieilles questions:
CREATE PROCEDURE `SPLIT_LIST_STR`(IN `INISTR` TEXT CHARSET utf8mb4, IN `ENDSTR` TEXT CHARSET utf8mb4, IN `INPUTSTR` TEXT CHARSET utf8mb4, IN `SEPARATR` TEXT CHARSET utf8mb4)
BEGIN
SET @I = 1;
SET @SEP = SEPARATR;
SET @INI = INISTR;
SET @END = ENDSTR;
SET @VARSTR = REPLACE(REPLACE(INPUTSTR, @INI, ''), @END, '');
SET @N = FORMAT((LENGTH(@VARSTR)-LENGTH(REPLACE(@VARSTR, @SEP, '')))/LENGTH(@SEP), 0)+1;
CREATE TEMPORARY TABLE IF NOT EXISTS temp_table(P1 TEXT NULL);
label1: LOOP
SET @TEMP = SUBSTRING_INDEX(@VARSTR, @SEP, 1);
insert into temp_table (`P1`) SELECT @TEMP;
SET @I = @I + 1;
SET @VARSTR = REPLACE(@VARSTR, CONCAT(@TEMP, @SEP), '');
IF @N >= @I THEN
ITERATE label1;
END IF;
LEAVE label1;
END LOOP label1;
SELECT * FROM temp_table;
END
Qui produit:
P1
1
2
3
4
Lors de l'utilisation de CALL SPLIT_LIST_STR('("', '")', '("1", "2", "3", "4")', '", "');
Je pourrais apparaître plus tard pour mettre le code un peu plus loin! À votre santé!
Si le texte que vous essayez de scinder contient des caractères multi-octets, cette approche échouera à cause du calcul incorrect de LENGTH. Dans ce cas, la version suivante avec CHAR_LENGTH au lieu de LENGTH fonctionne:
CREATE DEFINER=`root`@`localhost` FUNCTION `strSplit`(
`src` MEDIUMTEXT CHARACTER SET utf8,
`delim` VARCHAR(12),
`pos` INTEGER
)
RETURNS mediumtext
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE output MEDIUMTEXT CHARACTER SET utf8;
SET output = REPLACE(SUBSTRING(SUBSTRING_INDEX(src, delim, pos) ,
CHAR_LENGTH(SUBSTRING_INDEX(src, delim, pos - 1)) + 1) , delim , '');
IF output = '' THEN SET output = null; END IF;
RETURN output;
END
Référence: http://www.shakedos.com/2011/Nov/23/mysql-split-string-function-fix-split_str.html