mysql 替换所有字符,如何替换MySQL字符串中特定字符的所有其他实例?

本文详细介绍了如何使用MySQL查询将存储在varchar(255)列中的选项数据,从非规范化形式如'A|10|B|20|C|30'转换为更灵活的规范化表格形式,包括创建辅助表和利用substring_index()函数进行数据提取。此外,还讨论了规范化数据的好处,以及如何将规范化数据转换回原始格式。
摘要由CSDN通过智能技术生成

How to replace value in mysql column by query like, Column is options and its of type varchar(255)

From

id options

1 A|10|B|20|C|30

2 A|Positive|B|Negative

To

id options

1 A|10,B|20,C|30

2 A|Positive,B|Negative

I am doing it by php like this.

$str = "A|10|B|20|C|30";

$arr = explode("|",$str);

$newArr = array();

for($i=0;$i

if($arr[$i] && $arr[$i+1]){

$newArr[] = $arr[$i]."|".$arr[$i+1];

}

}

echo "Before:".$str."\n";

echo "After :".implode(",",$newArr);

?>

So instead of PHP, I want to do this in MySQL.

解决方案

You should consider to store your data in a normalized schema. In your case the table should look like:

| id | k | v |

|----|---|----------|

| 1 | A | 10 |

| 1 | B | 20 |

| 1 | C | 30 |

| 2 | A | Positive |

| 2 | B | Negative |

This schema is more flexible and you will see why.

So how to convert the given data into the new schema? You will need a helper table containing sequence numbers. Since your column is varchar(255) you can only store 128 values (+ 127 delimiters) in it. But let's just create 1000 numbers. You can use any table with enough rows. But since any MySQL server has the information_schema.columns table, I will use it.

drop table if exists helper_sequence;

create table helper_sequence (i int auto_increment primary key)

select null as i

from information_schema.columns c1

join information_schema.columns c2

limit 1000;

We will use this numbers as position of the values in your string by joining the two tables.

To extract a value from a delimited string you can use the substring_index() function. The value at position i will be

substring_index(substring_index(t.options, '|', i ), '|', -1)

In your string you have a sequence of keys followed by its values. The position of a key is an odd number. So if the position of the key is i, the position of the corresponding value will be i+1

To get the number of the delimiters in the string and limit our join we can use

char_length(t.options) - char_length(replace(t.options, '|', ''))

The query to store the data in a normalized form would be:

create table normalized_table

select t.id

, substring_index(substring_index(t.options, '|', i ), '|', -1) as k

, substring_index(substring_index(t.options, '|', i+1), '|', -1) as v

from old_table t

join helper_sequence s

on s.i <= char_length(t.options) - char_length(replace(t.options, '|', ''))

where s.i % 2 = 1

Now run select * from normalized_table and you will get this:

| id | k | v |

|----|---|----------|

| 1 | A | 10 |

| 1 | B | 20 |

| 1 | C | 30 |

| 2 | A | Positive |

| 2 | B | Negative |

So why is this format a better choice? Besides many other reasons, one is that you can easily convert it to your old schema with

select id, group_concat(concat(k, '|', v) order by k separator '|') as options

from normalized_table

group by id;

| id | options |

|----|-----------------------|

| 1 | A|10|B|20|C|30 |

| 2 | A|Positive|B|Negative |

or to your desired format

select id, group_concat(concat(k, '|', v) order by k separator ',') as options

from normalized_table

group by id;

| id | options |

|----|-----------------------|

| 1 | A|10,B|20,C|30 |

| 2 | A|Positive,B|Negative |

If you don't care about normalization and just want this task to be done, you can update your table with

update old_table o

join (

select id, group_concat(concat(k, '|', v) order by k separator ',') as options

from normalized_table

group by id

) n using (id)

set o.options = n.options;

And drop the normalized_table.

But then you won't be able to use simple queries like

select *

from normalized_table

where k = 'A'

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值