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

一个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、总结

以上方法虽然能解决我们的问题,但数据量大的时候速度较慢。彻底的解决办法是设计数据库的时候按照数据库的范式来做。

现在的空间基本已经不是问题,硬件已经很便宜了。

e7ce419cf2d6ad34d01da2ceb8829eed.png

微信 赏一包辣条吧~

023a57327877fb4402bcc76911ec18ea.png

支付宝 赏一听可乐吧~


版权声明:本文为weixin_30909873原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。