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