java - 将 SQL-INSERT 拆分为 Map 列名称 > 值

标签 java

你知道一个java函数来分割INSERT语句

INSERT INTO mytable (col1, col2, col3) VALUES ('val1', 'val2,andmore', 123)

进入 map :

col1 => "val1"
col2 => "val2,andmore"
col3 => 123

(暂时不需要Oracle的ESCAPE子句)

最佳答案

我没有找到解决方案,但构建了自己的函数

/**
 * The Unicode Char for "object replacement character"
 */
private final static char REPLACEMENT_CHAR = '\uFFFC';

/**
 * Split an SQL INSERT or UPDATE Statement to return the map of (column_name, values)
 * @param sql  the statement
 * @return the map with the column names as key and the sql values as values
 */
public static final SortedMap<String, String> getValuesFromSqlStatement (String sql)
{
    // check the argument
    if (sql==null || sql.trim().length() == 0)
        throw new IllegalArgumentException("The sql string cannot be empty");
    sql = sql.trim();

    final String ucSql = sql.toUpperCase();
    if (!ucSql.startsWith("INSERT") && !ucSql.startsWith("UPDATE"))
        throw new IllegalArgumentException("The sql string is neither an insert nor an update");

    // extract the column names
    Pattern pattern;
    pattern = Pattern.compile("[^(]*\\(([^)]*)\\).*");
    final Matcher m = pattern.matcher(sql);
    m.matches();
    final String columList = m.group(1);
    final String[] columns = columList.trim().split("\\s*,\\s*");

    // replace the , chars inside of strings by the REPLACEMENT_CHAR
    final char[] rest = sql.substring(sql.indexOf("VALUES")).toCharArray();
    boolean inString = false;
    int start = -1;
    int end   = -1;
    for (int i = 0; i<rest.length; i++)
    {
        final char c = rest[i];
        if ( inString && c == ',')
        {
            rest[i] = REPLACEMENT_CHAR;
        }
        else if ( c=='\'')
        {
            inString = !inString;
        }
        else if (!inString && c == '(')
        {
            if (start != -1)
                throw new AssertionError("Start brace found twice!");

            start = i+1;
        }
        else if (!inString && c == ')')
        {
            end = i-1;
            break;
        }
    }

    if (start == -1 || end == -1)
        throw new AssertionError("Start or end of the values part not found!");


    // split the result for having the values
    final String[] values = new String(rest, start, end-start+1).split("\\s*,\\s*");
    if (values.length != columns.length)
        throw new AssertionError("The number of values differs of the number of columns");

    // reset the , char in the values containing REPLACEMENT_CHAR and collect the results
    final TreeMap<String, String> map = new TreeMap<String, String>();
    for (int i=0; i<values.length; i++)
    {
        if (values[i].indexOf(REPLACEMENT_CHAR) != -1)
        {
            values[i] = values[i].replace(REPLACEMENT_CHAR, ',');
        }

        map.put(columns[i], values[i]);
    }

    return map;
}

关于java - 将 SQL-INSERT 拆分为 Map 列名称 > 值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11878469/

相关文章:

java - .class 和 .dex 文件有什么区别?

java - 如何在 Android 平台上的 SQLite 中创建准备好的 SELECT 语句

java - JSR-303 与 Spring 和 Hibernate 混合错误消息

java - ModelAndView 和 ModelMap 有什么区别?

java - Firestore - 嵌套集合的自定义对象

java - 无法获取 JAXBContext?

java - 可以在 JOptionPane 的 showConfirmDialog 中使用 JLabel 作为背景吗?

java - ArrayList 和 List 的区别

java - Eclipse SWT GUI - StyledText 控件 - 每个字符等宽

java - 在使用自签名证书签名的服务器上调用 API