首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > Mysql >

一个MySQL字段包含多个ID的解决方法

2012-11-03 
一个MySQL字段包含多个ID的解决办法转自:http://database.51cto.com/art/201011/235339.htm如果一个MySQL

一个MySQL字段包含多个ID的解决办法
转自:http://database.51cto.com/art/201011/235339.htm


如果一个MySQL字段包含多个ID,应该如何解决呢?下面就为您介绍一个处理单个MySQL字段包含多个ID的处理方法,希望对您能有所启迪。

以下是一个MySQL字段包含多个ID的解决办法完整的例子。

1、新建表

    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 下通过)

    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包含",",但是用别的符号分开时,如用"|"。用上面的方法是行不通的。我们有如下的解决办法

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

热点排行