一道面试题,求解题思路

qq_38277664 2017-11-23 08:54:09
已知带有特殊标记的sql语句和前端传过来的参数集合,用参数替换sql的特殊标记,如果标记对应的参数存在,则直接替换,如果不存在,要把对应的一段条件去掉,最后得出一个能用于查询的sql语句。要求给出完整代码,代码加上必要的注释。

例如:已知 1)带有特殊标记的sql语句 select * from T1 where 1=1 and a = :aa and (b =:bb or b =:cc) and e like :ee

          2)前端传过来的参数有 aa= "111" , bb= "222", cc= "333",dd = "444"

     得到 select * from T1 where 1=1 and a = 111 and (b = 222 or b = 333)

 /**

  * 用参数替换sql的特殊标记,如果标记对应的参数存在,则直接替换,如果不存在,要把对应的一段条件去掉,最后得出一个能用于查询的sql语句,返回能用于查询的sql语句。

  * @param labelSql 带有标记的sql语句, 如select * from T1 where 1=1 and a = :aa and (b =:bb or b =:cc) and e like :ee

  * @param param 参数集合,如aa= "111" , bb= "222", cc= "333",dd = "444"

  * @return 能用于查询的sql,如select * from T1 where 1=1 and a = 111 and (b = 222 or b = 333)

  */

 public static String getRunnableSql(String labelSql,Map<String,Object> param){

  //write your code here;

 }

完成了,请用如下情况去测试
1) sql: select * from T1 where 1=1 and (((a = :AA or B like :BB or c in :CC) and d in :DD ) or e = :EE) and f like :FF
2)参数:GG = "1223" , aa = "first"

最终得到 select * from T1 where 1=1
也测一下:有些标记有参数,有些标记没有参数,看最终结果是否正确

我在解这个字符串的时候,"select * from T1 where 1=1 and (((a=:AA or B like :BB or c in :CC) and d in :DD) or e=:EE) and f like :FF"
得到结果select * from T1 where 1=1 and d in 1234 or e=1234 and f like 1234,语意错误。

求大神们的解题思路,谢谢。
...全文
973 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
艺哥来了 2017-11-27
  • 打赏
  • 举报
回复
引用 7 楼 qq_38277664 的回复:
[quote=引用 6 楼 weixin_40114694 的回复:] 使用动态sql select * from T1 <where> <if test="aa!= null> and a= #{aa} </if> <if test="bb!= null or cc != null > and b= #{bb} or c = #{cc} </if> <if test="dd!= null > and d= #{dd} </if> and 1=1 </where>
这是mybatis里的吧,我说的是最近的面试题啦[/quote] 这个方法也可以在java中这样逻辑判断使用的撒
qq_38277664 2017-11-26
  • 打赏
  • 举报
回复
引用 12 楼 u014038116 的回复:
[quote=引用 11 楼 qq_38277664 的回复:] [quote=引用 10 楼 u014038116 的回复:] 还有一个思路就是,你判断没有那个参数的话,比如没有找到:ee的值,就找到他他前面的and或者or的位置,然后把and或者or到:ee这段语句去掉,等整个处理完后。最后你还要判断()之前有没有内容,如果没有,就把()删掉
是的,我也是这样的思路,但是像这条语句:select * from T1 where 1=1 and (((a=:AA or B like :BB or c in :CC) and d in :DD) or e=:EE) and f like :FF 存在参数bb:1234 DD:1234 EE:1234 FF:1234 这是我的结果:select * from T1 where 1=1 and d in 1234 or e=1234 and f like 1234 就出现了语意不明的情况 [/quote] 那是你判断的有问题吧,按思路select * from T1 where 1=1 and (((a=:AA or B like :BB or c in :CC) and d in :DD) or e=:EE) and f like :FF这个第一步处理完应该是这样的select * from T1 where 1=1 and ((() and d in 1234 ) or e=1234 ) and f like 1234[/quote] 确实是这样,我做了些更改,因为这样也是语意不明了吧?
xiaovhao 2017-11-26
  • 打赏
  • 举报
回复
引用 11 楼 qq_38277664 的回复:
[quote=引用 10 楼 u014038116 的回复:] 还有一个思路就是,你判断没有那个参数的话,比如没有找到:ee的值,就找到他他前面的and或者or的位置,然后把and或者or到:ee这段语句去掉,等整个处理完后。最后你还要判断()之前有没有内容,如果没有,就把()删掉
是的,我也是这样的思路,但是像这条语句:select * from T1 where 1=1 and (((a=:AA or B like :BB or c in :CC) and d in :DD) or e=:EE) and f like :FF 存在参数bb:1234 DD:1234 EE:1234 FF:1234 这是我的结果:select * from T1 where 1=1 and d in 1234 or e=1234 and f like 1234 就出现了语意不明的情况 [/quote] 那是你判断的有问题吧,按思路select * from T1 where 1=1 and (((a=:AA or B like :BB or c in :CC) and d in :DD) or e=:EE) and f like :FF这个第一步处理完应该是这样的select * from T1 where 1=1 and ((() and d in 1234 ) or e=1234 ) and f like 1234
qq_38277664 2017-11-26
  • 打赏
  • 举报
回复
引用 10 楼 u014038116 的回复:
还有一个思路就是,你判断没有那个参数的话,比如没有找到:ee的值,就找到他他前面的and或者or的位置,然后把and或者or到:ee这段语句去掉,等整个处理完后。最后你还要判断()之前有没有内容,如果没有,就把()删掉
是的,我也是这样的思路,但是像这条语句:select * from T1 where 1=1 and (((a=:AA or B like :BB or c in :CC) and d in :DD) or e=:EE) and f like :FF 存在参数bb:1234 DD:1234 EE:1234 FF:1234 这是我的结果:select * from T1 where 1=1 and d in 1234 or e=1234 and f like 1234 就出现了语意不明的情况
xiaovhao 2017-11-25
  • 打赏
  • 举报
回复
还有一个思路就是,你判断没有那个参数的话,比如没有找到:ee的值,就找到他他前面的and或者or的位置,然后把and或者or到:ee这段语句去掉,等整个处理完后。最后你还要判断()之前有没有内容,如果没有,就把()删掉
xiaovhao 2017-11-25
  • 打赏
  • 举报
回复
如果只是针对这道题的话,可以把where后面的字符串截取出来,然后根据and分割一下,判断有参数就把值替换,然后拼接上去,至于括号里面的,就根据or来分割,一样的处理,要是要适应多种情况的话,得在好好想想
qq_38277664 2017-11-25
  • 打赏
  • 举报
回复
顶个贴。。。
titvax 2017-11-24
  • 打赏
  • 举报
回复
后面漏了这个,吃饭去了,我也是随便写的
		// 去年and () or()这种
		labelSql = labelSql.replaceAll("(and|or)\\s?\\(\\s*+\\)\\s", "");
titvax 2017-11-24
  • 打赏
  • 举报
回复
package test;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TTeeest {
	public static void main(String[] args) {

		Map<String, Object> map = new HashMap<String, Object>();
		map.put("aa", "123");

		getRunnableSql("select * from T1 where 1=1 and a = :aa and (b=:bb or b =:cc) and e like :ee", map);
	}

	/**
	 * 
	 * 用参数替换sql的特殊标记,如果标记对应的参数存在,则直接替换,如果不存在,要把对应的一段条件去掉,最后得出一个能用于查询的sql语句,返回能用于查询的sql语句。
	 * 
	 * @param labelSql
	 *            带有标记的sql语句, 如select * from T1 where 1=1 and a = :aa and (b
	 *            =:bb or b =:cc) and e like :ee
	 * 
	 * @param param
	 *            参数集合,如aa= "111" , bb= "222", cc= "333",dd = "444"
	 * 
	 * @return 能用于查询的sql,如select * from T1 where 1=1 and a = 111 and (b = 222 or
	 *         b = 333)
	 * 
	 */

	public static String getRunnableSql(String labelSql, Map<String, Object> param) {

		String regex1 = "(or|and)?\\s?[\\(?\\w?\\s?]\\s?(=|like)?\\s?:\\w+";

		String regex2 = "(?<=:)\\w+";

		Pattern pattern1 = Pattern.compile(regex1);

		Pattern pattern2 = Pattern.compile(regex2);

		Matcher matcher = pattern1.matcher(labelSql);

		// 匹配找出以下
		// and a = :aa
		// b=:bb
		// or b =:cc
		// and e like :ee
		while (matcher.find()) {
			// 用于aa bb这些
			String paramXX = null;
			// 提取到要替换的字符串
			String paramReplace = matcher.group();

			Matcher matcher2 = pattern2.matcher(paramReplace);
			// 再找出:aa中的aa
			if (matcher2.find()) {
				paramXX = matcher2.group();

			}
			// 找出map中的参数
			Object mapParam = param.get(paramXX);

			// 判断是否为null,为null则删除
			if (mapParam == null) {

				labelSql = labelSql.replaceAll(paramReplace, " ");
			} else {
				// 替换
				labelSql = labelSql.replaceAll(":" + paramXX, mapParam.toString());
			}

		}
		System.out.println(labelSql);

		return null;

	}
}
titvax 2017-11-24
  • 打赏
  • 举报
回复
正则表达式也许可以
qq_38277664 2017-11-24
  • 打赏
  • 举报
回复
顶个帖。。。
qq_38277664 2017-11-24
  • 打赏
  • 举报
回复
引用 6 楼 weixin_40114694 的回复:
使用动态sql select * from T1 <where> <if test="aa!= null> and a= #{aa} </if> <if test="bb!= null or cc != null > and b= #{bb} or c = #{cc} </if> <if test="dd!= null > and d= #{dd} </if> and 1=1 </where>
这是mybatis里的吧,我说的是最近的面试题啦
  • 打赏
  • 举报
回复
使用动态sql select * from T1 <where> <if test="aa!= null> and a= #{aa} </if> <if test="bb!= null or cc != null > and b= #{bb} or c = #{cc} </if> <if test="dd!= null > and d= #{dd} </if> and 1=1 </where>
qq_38277664 2017-11-24
  • 打赏
  • 举报
回复
引用 4 楼 z924139546 的回复:
后面漏了这个,吃饭去了,我也是随便写的
		// 去年and () or()这种
		labelSql = labelSql.replaceAll("(and|or)\\s?\\(\\s*+\\)\\s", "");
这个思路很好,但是还是要求语意正确 select * from T1 where 1=1 and (((a=:AA or B like :BB or c in :CC) and d in :DD) or e=:EE) and f like :FF map.put("bb", "1234"); map.put("DD", "1234"); map.put("EE", "1234"); map.put("FF", "1234");

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧