一个mysql解决的问题:游标、字符串操作 类似另一篇 sql
2014-03-18 01:20
555 查看
问题:已知username表,得到userhobby表
username表:(用户ID,用户名,用户所有爱好) userhobby表:(用户id,用户名,用户单个爱好)
解决思路:实现创建空的single_hobby表,用于存储所有的单一爱好,eg:string ;逐行读取username表,并处理UserHobby字段:按照','分割字符串,将提取出的单一爱好,eg:string ,判断此单一爱好是否已存在single_hobby表中,若是不存在,则将此单一爱好插入到single_hobby表中,并将username表所有的含有此爱好的用户添加到userhobby表中。
single_hobby表:(单一的爱好)
1.mysql中空格问题:字段值若是空''或一个空格' '或一个以上空格' ' mysql用于=号的时候不区分它们,同等对待 。而用于like的时候不一致,因为'%%'表示:所有的字符串;若%之间是1个空格表示:至少有1个空格的字符串;若%之间是2个空格表示:至少有2个空格的字符串;以此类推。
2.mysql中字符大小写问题:mysql对大小写不敏感,从=或like运算符可以看出一致看待。
3.mysql中游标问题:语句需要放在存储过程中。
语法参考:http://www.jbxue.com/db/13451.html
实现:
注意:以上代码其实结果有问题。
若是username表中Userhobby中有单个爱好为java和javascript的,但添加含有java爱好的用户到userhobby表时,会把含有javascript的也插入进去,而等到添加含有javascript爱好的用户时,用添加了一次,所以like语句中必须用分隔符来作为边界。
修改后的代码参考如下:
username表:(用户ID,用户名,用户所有爱好) userhobby表:(用户id,用户名,用户单个爱好)
解决思路:实现创建空的single_hobby表,用于存储所有的单一爱好,eg:string ;逐行读取username表,并处理UserHobby字段:按照','分割字符串,将提取出的单一爱好,eg:string ,判断此单一爱好是否已存在single_hobby表中,若是不存在,则将此单一爱好插入到single_hobby表中,并将username表所有的含有此爱好的用户添加到userhobby表中。
single_hobby表:(单一的爱好)
1.mysql中空格问题:字段值若是空''或一个空格' '或一个以上空格' ' mysql用于=号的时候不区分它们,同等对待 。而用于like的时候不一致,因为'%%'表示:所有的字符串;若%之间是1个空格表示:至少有1个空格的字符串;若%之间是2个空格表示:至少有2个空格的字符串;以此类推。
2.mysql中字符大小写问题:mysql对大小写不敏感,从=或like运算符可以看出一致看待。
3.mysql中游标问题:语句需要放在存储过程中。
语法参考:http://www.jbxue.com/db/13451.html
实现:
DROP PROCEDURE IF EXISTS PK; CREATE PROCEDURE PK() BEGIN DECLARE DONE INT DEFAULT 0; /*用于游标循环终止的变量*/ DECLARE n INT DEFAULT 0; /*用于在single_hobby表中统计单一爱好行数的变量*/ DECLARE semi_hobby VARCHAR(60) DEFAULT ''; /*用于存取待处理的爱好字符串*/ DECLARE h VARCHAR(60) DEFAULT ''; /*用于从semi_hobby中提取出的首个单一爱好*/ DECLARE mycursor CURSOR FOR select UserHobby from username; /*游标定义*/ DECLARE CONTINUE HANDLER FOR NOT FOUND SET DONE = 1; /*游标循环终止条件设置*/ open mycursor; /*打开游标*/ REPEAT FETCH mycursor INTO semi_hobby; /*游标取出待处理的字段*/ set semi_hobby = REPLACE(semi_hobby,' ',''); /*为了用于有空格但意义相同的单一爱好处理*/ IF NOT DONE THEN /*判断是否终止游标循环*/ WHILE(LOCATE(',',semi_hobby)<> 0) DO /*用于分割字符串的循环*/ SET h = SUBSTRING(semi_hobby,1,LOCATE(',',semi_hobby)-1); /*取出首个单一爱好字符串*/ SELECT COUNT(*) INTO n from single_hobby WHERE Hobby = h; /*获取single_hobby表中已有的此单一爱好个数*/ IF NOT n THEN /*n为0即尚不存在*/ INSERT INTO single_hobby(Hobby) VALUES(h); /*插入到single_hobby表*/ /*向userhobby表中插入username表中含有此爱好的所有用户*/ INSERT INTO userhobby (id,name,semi_hobby) SELECT UserID,UserName,h from username WHERE UserHobby LIKE CONCAT('%',h,'%'); END IF; /*删除已处理的部分,将剩余的赋值给semi_hobby*/ SET semi_hobby = SUBSTR(semi_hobby,LOCATE(',',semi_hobby)+1,LENGTH(semi_hobby)-LOCATE(',',semi_hobby)); END WHILE; /*对最后一个单一的爱好处理,类似以上h的操作,不同的是对于空或空格的处理*/ SELECT COUNT(*) INTO n from single_hobby WHERE Hobby =semi_hobby; IF NOT n THEN INSERT INTO single_hobby(Hobby) VALUES(semi_hobby); IF semi_hobby = '' THEN /*若字段的值原来为空或是若干个空格,都将插入userhobby表中*/ INSERT INTO userhobby (id,name,semi_hobby) SELECT UserID,UserName,semi_hobby from username WHERE UserHobby = ''; ELSE INSERT INTO userhobby (id,name,semi_hobby) SELECT UserID,UserName,semi_hobby from username WHERE UserHobby LIKE CONCAT('%',semi_hobby,'%'); END IF; END IF; END IF; UNTIL DONE END REPEAT; /*结束游标循环*/ close mycursor; /*关闭游标*/ END; CALL PK(); /*执行存储过程*/
注意:以上代码其实结果有问题。
若是username表中Userhobby中有单个爱好为java和javascript的,但添加含有java爱好的用户到userhobby表时,会把含有javascript的也插入进去,而等到添加含有javascript爱好的用户时,用添加了一次,所以like语句中必须用分隔符来作为边界。
SELECT COUNT(*) INTO n from single_hobby WHERE Hobby = h /*这样假如一个前后没有空格的字符串h,但表中已有一个前面或是后面有空格的字段,但其实是没有前后没有空格的字符串h的,但是n的值不是0,这是应为=运算符忽略字符串前后的空格,所以改为like运算符比较好*/
SELECT COUNT(*) INTO n from single_hobby WHERE Hobby like h
修改后的代码参考如下:
DROP PROCEDURE IF EXISTS PK; CREATE PROCEDURE PK() BEGIN DECLARE DONE INT DEFAULT 0; /*用于游标循环终止的变量*/ DECLARE n INT DEFAULT 0; /*用于在single_hobby表中统计单一爱好行数的变量*/ DECLARE semi_hobby VARCHAR(60) DEFAULT ''; /*用于存取待处理的爱好字符串*/ DECLARE s_hobby VARCHAR(60) DEFAULT ''; DECLARE h VARCHAR(60) DEFAULT ''; /*用于从semi_hobby中提取出的首个单一爱好*/ DECLARE mycursor CURSOR FOR select UserHobby from username; /*游标定义*/ DECLARE CONTINUE HANDLER FOR NOT FOUND SET DONE = 1; /*游标循环终止条件设置*/ open mycursor; /*打开游标*/ REPEAT FETCH mycursor INTO semi_hobby; /*游标取出待处理的字段*/ IF NOT DONE THEN /*判断是否终止游标循环*/ set s_hobby = REPLACE(semi_hobby,' ',''); /*只在为空或是若干空格时使用,若在其他情况下,很难取到,如:%sql%,或包括含有sql-server单个爱好,而不是纯粹的sql*/ IF s_hobby = '' THEN /*单独处理空或是若干个空格*/ SELECT COUNT(*) INTO n from single_hobby WHERE Hobby =s_hobby; IF NOT n THEN INSERT INTO single_hobby(Hobby) VALUES(s_hobby); INSERT INTO userhobby (id,name,semi_hobby) SELECT UserID,UserName,semi_hobby from username WHERE UserHobby = ''; END IF; ELSE WHILE(LOCATE(',',semi_hobby)<> 0) DO /*用于分割字符串的循环*/ SET h = SUBSTRING(semi_hobby,1,LOCATE(',',semi_hobby)-1); /*取出首个单一爱好字符串*/ SELECT COUNT(*) INTO n from single_hobby WHERE Hobby like h; /*获取single_hobby表中已有的此单一爱好个数*/ IF NOT n THEN /*n为0即尚不存在*/ INSERT INTO single_hobby(Hobby) VALUES(h); /*插入到single_hobby表*/ /*向userhobby表中插入username表中含有此爱好的所有用户,注意分四种情况:在开头后面有新的,在开头后面无新的,不在开头后面有新的,不在开头后面无新的*/ INSERT INTO userhobby (id,name,semi_hobby) SELECT UserID,UserName,h from username WHERE UserHobby LIKE CONCAT('%,',h,',%'); INSERT INTO userhobby (id,name,semi_hobby) SELECT UserID,UserName,h from username WHERE UserHobby LIKE CONCAT('%,',h); INSERT INTO userhobby (id,name,semi_hobby) SELECT UserID,UserName,h from username WHERE UserHobby LIKE CONCAT(h,',%'); INSERT INTO userhobby (id,name,semi_hobby) SELECT UserID,UserName,h from username WHERE UserHobby LIKE h; END IF; /*删除已处理的部分,将剩余的赋值给semi_hobby*/ SET semi_hobby = SUBSTR(semi_hobby,LOCATE(',',semi_hobby)+1,LENGTH(semi_hobby)-LOCATE(',',semi_hobby)); END WHILE; /*对最后一个单一的爱好处理,类似以上h的操作*/ SELECT COUNT(*) INTO n from single_hobby WHERE Hobby like semi_hobby; IF NOT n THEN /*若是select 语句中semi_hobby改为replace(semi_hobby,' ',''),则userhobby表中semi_hobby字段会不含有空格如:' c'和'c'而一致*/ INSERT INTO single_hobby(Hobby) VALUES(semi_hobby); INSERT INTO userhobby (id,name,semi_hobby) SELECT UserID,UserName,semi_hobby from username WHERE UserHobby LIKE CONCAT('%,',semi_hobby,',%'); INSERT INTO userhobby (id,name,semi_hobby) SELECT UserID,UserName,semi_hobby from username WHERE UserHobby LIKE CONCAT(semi_hobby,',%'); INSERT INTO userhobby (id,name,semi_hobby) SELECT UserID,UserName,semi_hobby from username WHERE UserHobby LIKE CONCAT('%,',semi_hobby); INSERT INTO userhobby (id,name,semi_hobby) SELECT UserID,UserName,semi_hobby from username WHERE UserHobby LIKE semi_hobby; END IF; END IF; END IF; UNTIL DONE END REPEAT; /*结束游标循环*/ close mycursor; /*关闭游标*/ END; CALL PK(); /*执行存储过程*/
相关文章推荐
- 一个关于sql语句的问题解决,包括:字符串拆分,游标
- 一次ORA-4030问题诊断及解决【解决思路不错,说明了对象的统计信息与优化器的优化操作(即选择执行一个SQL语句在该优化参数环境下最佳的执行计划)间的关系】
- 一个SQL字符串问题的解决
- 执行SQL语句时出现问题操作必须使用一个可更新的查询错误的解决方法
- laravel+Mysql 中DB原生SQL操作报1292 Truncated incorrect DOUBLE value问题解决
- mysql5.7中的一个update order by排名问题解决办法(一条sql搞定排名)
- "执行SQL语句时出现问题操作必须使用一个可更新的查询"错误的解决方法
- 6.(Mysql数据管理相关)连接MYSQL,修改密码,增加新用户,数据库相关命令,表操作相关命令,数据相关命令,数据库sql导入和导出,备份数据库,查看不到mysql数据库的解决办法
- Mysql根据id查询上下条数据(解决上一篇下一篇问题)
- vs2010下MFC解决自动配置数据源函数SQLConfigDataSource第四个参数字符串问题
- 2014.06.26 MySQL 用索引解决的一个性能问题
- Android自带播放器字符串显示乱码问题的一个解决方法
- JDBC操作MySQL出现:This result set must come from a statement that was created with a result set type of ResultSet.CONCUR_UPDATABLE, ...的问题解决
- mysql 通道,解决mysql不在同一个局域网访问问题
- MySQL(Navicat)运行.sql文件时报错:[Err] 2006 - MySQL server has gone away 的解决方法 背景: 今天导入一个数据量很大的.sql文件时,
- 解决mybatis继承SqlSessionDaoSupport方式操作数据库不打印sql日志的问题。
- PowerDesigner导入MySql步骤和解决问题Non SQL Error : Could not load class com.mysql.jdbc.Driver
- 在使用Hibernate时,因为一个查询需要更多的表连接而要使用SQL来解决性能问题。然而返回的结果集中包含了没有映射的Entity类中的表字段,在这个SQL中还有使用如何将层次关系的父子结点显示为横行
- 【软件系肖潇】解决使用DButils进行jdbc多表联合操作时抛出sql异常的问题