分隔符上的 MySQL 字符串拆分

时间:2021-03-06 08:18:55

标签: mysql enums

基于 https://stackoverflow.com/a/59666211/4250302,我创建了存储函数 get_enum_item,以便将来处理 ENUM() 类型字段中的可能值列表。

它工作得很好,但是......但是如果分隔符本身是被拆分的字符串的一部分,我无法确定该怎么做。例如: (方括号是为了便于阅读)

mysql> set @q=",v1,',v2'" --empty string, "v1", "comma-v2";
mysql> select concat('[',get_enum_item(@q,',',0),']') as item;
+------+
| item |
+------+
| []   |
+------+

没问题

mysql> select concat('[',get_enum_item(@q,',',1),']') as item;
+------+
| item |
+------+
| [v1] |
+------+

还可以

mysql> select concat('[',get_enum_item(@q,',',2),']') as item;
+------+
| item |
+------+
| [']  |
+------+

不正常

@q 包含 3 个逗号,其中前两个是真正的分隔符,而最后一个是第三个可能值的部分:"comma-v-two"。而且我不知道如何避免拆分功能的混淆。 “表单编辑器”模式下的 MySQL WorkBench 以某种方式解决了这个问题,但我如何用 MySQL 的代码解决这个问题?

嗯,我可以依赖这样一个事实,即 show_columns 之类的查询以“硬编码”方式显示枚举:

select column_name,column_type
  from information_schema.columns
  where data_type='enum' and table_name='assemblies';
+--------------+------------------------------------------------------------------+
| COLUMN_NAME  | COLUMN_TYPE                                                      |
+--------------+------------------------------------------------------------------+
| AssetTagType | enum('','И/Н','Н/Н',',fgg')                                      |
| PCTagType    | enum('','И/Н','Н/Н')                                             |
| MonTagType   | enum('','И/Н','Н/Н')                                             |
| UPSTagType   | enum('','И/Н','Н/Н')                                             |
| OtherTagType | enum('','И/Н','Н/Н')                                             |
| state        | enum('в работе','на списание','списано')                         |
+--------------+------------------------------------------------------------------+

因此我可以尝试使用 ',' 作为分隔符,但是如果“逗号-撇号”组合是可能值的一部分,这不会使我免于这种情况...... :-( 我唯一能想象的是计算撇号,如果分隔逗号在偶数个 ' 之后,那么它是分隔符,而如果它跟在奇数个 ' 之后,它是值的一部分。 除了愚蠢地扫描循环内的输入字符串之外,我无法发明任何东西。但也许还有其他一些建议可以正确拆分值?

请不要建议使用 PHP、Python、AWK 等。查询将从 Pascal(Lazarus,CodeTyphoon)应用程序执行,调用外部处理器是非常不安全的。 作为最后的手段,我可​​以使用 Pascal 的代码处理 column_type,但首先,我必须确保自己无法通过 MySQL 的功能解决该任务。

编辑:

select column_type from information_schema.columns
where column_name='assettagtype' and table_name='assemblies';

+------------------------------------------+
| COLUMN_TYPE                              |
+------------------------------------------+
| enum('','И/Н','Н/Н',''''',fgg','''')     |
+------------------------------------------+
1 row in set (0.00 sec)

第四个字段:'',fgg,第五个字段:'

1 个答案:

答案 0 :(得分:1)

set @q="'в работе','на списание','списано'";
WITH RECURSIVE cte as (
   select 1 as a union all
   select a+1 from cte where a<35
   )
select distinct  regexp_substr(@q,'''[^,]*''',a) as E from cte;
  • 35 的值过高会引发错误 ERROR 3686 (HY000): Index out of bounds in regular expression search.。 (我为此创建了一个 bug
  • 应该过滤掉 null 值...?

输出:

<头>
E
'в работе'
'на списание'
'списано'

编辑:通过一些努力,这也适用于更复杂的示例(不适用于每个“分阶段”示例!)

set @q="'в работе','на списание','списано',''',fgg'";
select @q;

WITH RECURSIVE cte as (
   select 1 as a union all
   select a+1 from cte where a<35
   )
select distinct regexp_substr(@q,'(''([^,]|[^''][^''])*'')',a) E  from cte;

输出:

<头>
E
'вработе'
'на списание'
'списано'
''',fgg'