2012-06-19 88 views
0

我有我的表去归一化的记录:MySQL的:分裂VARCHAR值和插入件

ID, CODES 
1 |1|2|3|4 
2 |5|6|7|8 

在第二列有int类型,保存在由分离varchar字段|符号。 我想使用链接表将它们转换为正常的Many2Many关系表。 所以我想创建一个表像这样

ID CODE 
1 1 
1 2 
1 3 
1 4 
.... 
2 8 

我明白,我可以通过在MySQL存储功能,分割字符串,并插入值记录迭代。但我很感兴趣:是否有可能以这种方式转换数据没有存储过程/函数,但只使用查询(创建表...选择...)? 谢谢。

UPD:在不同行中有可变数量的代码。每行有1到15个代码。

+0

一个单元中的最大代码数是多少? – biziclop

+0

代码字段中只有四个“列”还是可变的?你的例子只显示4“|”分隔的领域。 –

+0

@biziclop在不同的行中有可变数量的代码。每行有1到15个代码。 – dbf

回答

1

以下是它的工作原理,包含的测试数据等。

认为,这仅仅是一个乐趣答案。要走的路线显然是存储过程或功能或其他。

drop table testvar; 
create table testvar (id int, codes varchar(20)); 
insert into testvar values (1, '|1|2|3|4'), (2, '|5|6|7|8'); 



drop table if exists inserttest; 
create table inserttest (id int, code int); 

select @sql:=left(concat('insert into inserttest values ', group_concat('(', id, ',', replace(right(codes, length(codes) - 1), '|', concat('),(', id, ',')), '),' separator '')), length(concat('insert into inserttest values ', group_concat('(', id, ',', replace(right(codes, length(codes) - 1), '|', concat('),(', id, ',')), '),' separator ''))) -1) 
from testvar; 

prepare stmt1 from @sql; 
execute stmt1; 

select * from inserttest; 
1

Oracle的方式是:

insert into newtestvar 
select t.id, to_number(substr(t.codes, p1 + 1, p2)) 
from (
    select testvar.id, testvar.codes, s.num, 
    instr(testvar.codes, '|',1,s.num) p1, 
    instr(testvar.codes||'|', '|',1,s.num + 1)- instr(testvar.codes, '|',1,s.num) - 1 p2 
    from testvar, (select level num from dual connect by level <= 15) s 
    where s.num <= (length(testvar.codes)-length(replace(testvar.codes, '|'))) 
) t; 

我希望你能适应它为MySQL。