我正在编写一个可以执行不同SQL语句的应用程序(用户将这些语句指定为一个字符串值)。我正在使用 ”;”作为语句之间的分隔符(用户可以立即执行许多DML语句)。但是在DML语句中,可能存在具有“;”的varchar值。内。
insert into A values(1, 'sda;asdad');
insert into A values(2, 'asdsa');
我的第一个想法是使用String#split(String regex)
。但是我不知道如何制作一个正则表达式,它只能用那些不在varchars里面的分号来分割。你能建议一个或者可能有另一种方法来解决这个问题吗?
答案 0 :(得分:2)
通常你会通过转义来解决这个问题:
insert into A values(1, 'sda\\;asdad');
然后当您String#split()
时,请确保使用negative lookbehind ;
前面没有\
。像这样:
String rawInput = ...;
String[] statements = rawInput.split("(?<!\\\\);");
答案 1 :(得分:1)
String.split
以下更复杂,但它有效:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Regex2 {
static Pattern pattern = Pattern.compile(".*'(.*);(.*)'.*");
public static void main(String[] args) {
String target = "'asdf;asdf';";
String[] split = split(target);
if (split == null)
System.out.println("No match");
else
for (String word : split(target))
System.out.println(word);
}
static String[] split(String target) {
Matcher matcher = pattern.matcher(target);
String[] split = null;
if (matcher.matches()) {
split = new String[matcher.groupCount()];
for (int i = 1; i <= matcher.groupCount(); i++)
split[i - 1] = matcher.group(i);
}
return split;
}
}
答案 2 :(得分:1)
这是一个天真的解析器,可能是你正在寻找的。我想过使用正则表达式。起初我认为你的语言实际上不是常规的。
我相信DML是一种上下文无关语言,但实际上,您的目标语言是常规的,因为您不关心嵌套语句。你关心的只是检测顶级字符串。但是,当您考虑到varchars中可能存在转义引号时,即使这很难使用正则表达式。即'abcd \'efg',如果你有多个;在varchar里面。
此代码并不漂亮,但它应该可以满足您的需求。
public static void main(String[] ar) {
String s = "aaa 'bb;bb;bb' aaa; aaa 'bb;bb\\';bb' aaa";
System.out.println(splitStatments(s, ';'));
}
private static List<String> splitStatments(String s, char statementDelimiter) {
List<String> statements = new ArrayList<String>();
StringBuffer sb = new StringBuffer();
boolean outsideString = true;
char lastChar = 0;
for (char c : s.toCharArray()) {
// in the case of the escaped \', we DON'T want to flip the boolean
if (c == '\'' && lastChar != '\\') {
outsideString = !outsideString;
}
if (c == statementDelimiter && outsideString) {
statements.add(sb.toString());
sb = new StringBuffer();
} else {
sb.append(c);
}
lastChar = c;
}
if (sb.length() > 0) {
statements.add(sb.toString());
}
return statements;
}