收集,整理常用的MySQL,MSSQL,Javascript,php技术资料.

MySQL字符串处理系统-一个字段包含多个ID的解决办法

上一篇 / 下一篇  2008-01-12 12:02:55 / 个人分类:Mysql开发

查看( 2215 ) / 评论( 0 )

    今天在朋友家整理一个旧项目的时候,发现在一个表中存着一个字段包含多个Id的问题。觉得这个问题很多朋友都会碰到,就把它写出来跟大家分享一下。或许已经有更好的解决办法,欢迎大家讨论.
转载请注明来自[phpchina.com]


以下是完整的例子。

1、新建表

#title: 自定义字符
#auther: 小强(占卜师) 
#date: 
2008-01-08

drop table if exists Category;
create table Category
(
   cateId                         
int(5)                         not null AUTO_INCREMENT,
   chiName                        
varchar(80),
   
primary key (cateId)
);

drop table if exists OpenRecord;
create table OpenRecord
(
   opreId                         
int(5)                         not null AUTO_INCREMENT,
   cateIds                        
varchar(80),
   
primary key (opreId)                    
);

2、初始化数据

insert Category(chiName) values ('fish'),('shrimp'),('crab'),('tiger');

insert OpenRecord(cateIds) values('1,2');
insert OpenRecord(cateIds) values('2,3');

3、查询OpenRecord中Id为1包括的Category。

#错误的方法
select * 
    
from Category
    
where (select INSTR(cateIds,cateId) from OpenRecord where opreId=1)

#正确的方法
select * 
    
from Category
    
where (select FIND_IN_SET(cateId,cateIds) from OpenRecord where opreId=1)

用INSTR会出现当ID大于10的时候,查ID为1的数据,会把1,10,11,12......的都拿出来。

4、扩展会出现的问题。
用FIND_IN_SET可以解决ID是用","号隔开的问题。然而会有另外的两种情况。

A、当ID不包含",",但是用别的符号分开时,如用"|"。我们有如下的解决办法

select * 
    
from Category
    
where (select FIND_IN_SET(cateId,REPLACE(cateIds,'|',',')) from OpenRecord where opreId=1)

  如果你的数据库中这种情况的表很多。我们也可以把它写成函数。(MYSQL 5 下通过)

#title: 自定义字符串拆分函数
#auther: 小强(占卜师) 
#date: 
2007-01-08

DELIMITER $$

DROP FUNCTION IF EXISTS fun_instr$$

CREATE FUNCTION fun_instr(ns VARCHAR(100),s TEXT,isplit CHAR(1))
    
RETURNS INT(8)
    
BEGIN

        
DECLARE strPosition INT(8);

        
SET strPosition = FIND_IN_SET(ins,REPLACE(s,split,','));
        
RETURN strPosition;
    
END$$

DELIMITER ;

#使用方法
select * 
    
from Category
    
where (select fun_instr(cateId,cateIds,','from OpenRecord where opreId=1)


B、当ID包含",",但是用别的符号分开时,如用"|"。用上面的方法是行不通的。我们有如下的解决办法

#title: 自定义字符串拆分函数
#auther: 小强(占卜师) 
#date: 
2008-01-08

DELIMITER $$

DROP FUNCTION IF EXISTS fun_custom_instr$$

CREATE FUNCTION fun_custom_instr(ins VARCHAR(255),s TEXT,split VARCHAR(10))
    
RETURNS INT(8)
    
BEGIN
        
DECLARE splitlen INT(2);
        
DECLARE strPosition INT(8);
        
SET splitLen = LENGTH(split);
        
SET strPosition = 0;
        #第一段的字符相等
        
IF s=ins THEN
                
RETURN 1;
        
END IF;
        #中间段的字符相等
        
WHILE INSTR(s,split)>0 DO
            
SET strPosition = strPosition + 1;
            
IF LEFT(s,INSTR(s,split)-1)=ins THEN
                
RETURN strPosition;
            
END IF;            
            
SET s = SUBSTRING(s,INSTR(s,split) + splitLen);
        
END WHILE;
        #最一段的字符相等
        
IF s=ins THEN
                
RETURN strPosition+1;
        
END IF;

        
RETURN 0;
    
END$$

DELIMITER ;

#使用方法
select * 
    
from Category
    
where (select fun_custom_instr(cateId,cateIds,','from OpenRecord where opreId=1)


5、总结
以上方法虽然能解决我们的问题,但数据量大的时候速度较慢。彻底的解决办法是设计数据库的时候按照数据库的范式来做。
现在的空间基本已经不是问题,硬件已经很便宜了。

 


TAG: Mysql开发 MySQL字符串拆分函数 MySQL自定义函数 MySQL字符串分解函数 MySQL字符串分割函数

我来说两句

(可选)

Open Toolbar