com.alibaba.druid.sql.parser.ParserException: syntax error, error in :‘ TOP 3 * FROM 。。。

先说一下现象,此处我使用是国产达梦6数据库,该处SQL在数据库客户端中能正常执行,且该错误对系统运行,目前没发现有何异常,但,看着该接口每次被调用后,都打出一堆Exception,也是很不爽的事。

此处报错日志异常如下(仅供参考):

11:11:47.031 [main] DEBUG c.r.p.t.s.m.S.searchSql - [debug,143] - ==>  Preparing: SELECT TOP 3 * FROM XXXXXX WHERE XXXX ORDER BY XXX ASC 
11:11:47.078 [main] ERROR c.a.d.f.s.StatFilter - [mergeSql,149] - merge sql error, dbType null, druid-1.1.14, sql : SELECT TOP 3 * FROM XXXX WHERE XXX ORDER BY XXX ASC
com.alibaba.druid.sql.parser.ParserException: syntax error, error in :' TOP 3 * FROM XXX', expect LITERAL_INT, actual LITERAL_INT pos 12, line 1, column 12, token LITERAL_INT
	at com.alibaba.druid.sql.parser.SQLParser.printError(SQLParser.java:287)
	at com.alibaba.druid.sql.parser.SQLStatementParser.parseStatementList(SQLStatementParser.java:532)
	at com.alibaba.druid.sql.parser.SQLStatementParser.parseStatementList(SQLStatementParser.java:171)
	at com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils.parameterize(ParameterizedOutputVisitorUtils.java:98)
	at com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils.parameterize(ParameterizedOutputVisitorUtils.java:81)
	at com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils.parameterize(ParameterizedOutputVisitorUtils.java:54)
	at com.alibaba.druid.filter.stat.StatFilter.mergeSql(StatFilter.java:147)
	at com.alibaba.druid.filter.stat.StatFilter.createSqlStat(StatFilter.java:648)
	at com.alibaba.druid.filter.stat.StatFilter.statementPrepareAfter(StatFilter.java:311)
	at com.alibaba.druid.filter.FilterEventAdapter.connection_prepareStatement(FilterEventAdapter.java:124)
	at com.alibaba.druid.filter.FilterChainImpl.connection_prepareStatement(FilterChainImpl.java:568)
	at com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl.prepareStatement(ConnectionProxyImpl.java:341)
	at com.alibaba.druid.pool.DruidPooledConnection.prepareStatement(DruidPooledConnection.java:348)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.apache.ibatis.logging.jdbc.ConnectionLogger.invoke(ConnectionLogger.java:55)

经常使用druid,还是觉得挺好用的,但是源代码没仔细跟过,乘着此次异常,研究了研究。

于是在 com.alibaba.druid.sql.parser.Token中发现了TOP作为了关键字

package com.alibaba.druid.sql.parser;

public enum Token
{
  SELECT("SELECT"),  DELETE("DELETE"),  INSERT("INSERT"),  UPDATE("UPDATE"),  FROM("FROM"),  HAVING("HAVING"),  WHERE("WHERE"),  ORDER("ORDER"),  BY("BY"),  GROUP("GROUP"),  INTO("INTO"),  AS("AS"),  CREATE("CREATE"),  ALTER("ALTER"),  DROP("DROP"),  SET("SET"),  NULL("NULL"),  NOT("NOT"),  DISTINCT("DISTINCT"),  TABLE("TABLE"),  TABLESPACE("TABLESPACE"),  VIEW("VIEW"),  SEQUENCE("SEQUENCE"),  TRIGGER("TRIGGER"),  USER("USER"),  INDEX("INDEX"),  SESSION("SESSION"),  PROCEDURE("PROCEDURE"),  FUNCTION("FUNCTION"),  PRIMARY("PRIMARY"),  KEY("KEY"),  DEFAULT("DEFAULT"),  CONSTRAINT("CONSTRAINT"),  CHECK("CHECK"),  UNIQUE("UNIQUE"),  FOREIGN("FOREIGN"),  REFERENCES("REFERENCES"),  EXPLAIN("EXPLAIN"),  FOR("FOR"),  IF("IF"),  SORT("SORT"),  ALL("ALL"),  UNION("UNION"),  EXCEPT("EXCEPT"),  INTERSECT("INTERSECT"),  MINUS("MINUS"),  INNER("INNER"),  LEFT("LEFT"),  RIGHT("RIGHT"),  FULL("FULL"),  OUTER("OUTER"),  JOIN("JOIN"),  ON("ON"),  SCHEMA("SCHEMA"),  CAST("CAST"),  COLUMN("COLUMN"),  USE("USE"),  DATABASE("DATABASE"),  TO("TO"),  AND("AND"),  OR("OR"),  XOR("XOR"),  CASE("CASE"),  WHEN("WHEN"),  THEN("THEN"),  ELSE("ELSE"),  ELSIF("ELSIF"),  END("END"),  EXISTS("EXISTS"),  IN("IN"),  CONTAINS("CONTAINS"),  RLIKE("RLIKE"),  FULLTEXT("FULLTEXT"),  NEW("NEW"),  ASC("ASC"),  DESC("DESC"),  IS("IS"),  LIKE("LIKE"),  ESCAPE("ESCAPE"),  BETWEEN("BETWEEN"),  VALUES("VALUES"),  INTERVAL("INTERVAL"),  LOCK("LOCK"),  SOME("SOME"),  ANY("ANY"),  TRUNCATE("TRUNCATE"),  RETURN("RETURN"),  TRUE("TRUE"),  FALSE("FALSE"),  LIMIT("LIMIT"),  KILL("KILL"),  IDENTIFIED("IDENTIFIED"),  PASSWORD("PASSWORD"),  ALGORITHM("ALGORITHM"),  DUAL("DUAL"),  BINARY("BINARY"),  SHOW("SHOW"),  REPLACE("REPLACE"),  BITS,  WHILE("WHILE"),  DO("DO"),  LEAVE("LEAVE"),  ITERATE("ITERATE"),  REPEAT("REPEAT"),  UNTIL("UNTIL"),  OPEN("OPEN"),  CLOSE("CLOSE"),  OUT("OUT"),  INOUT("INOUT"),  EXIT("EXIT"),  UNDO("UNDO"),  SQLSTATE("SQLSTATE"),  CONDITION("CONDITION"),  DIV("DIV"),  WINDOW("WINDOW"),  OFFSET("OFFSET"),  ROW("ROW"),  ROWS("ROWS"),  ONLY("ONLY"),  FIRST("FIRST"),  NEXT("NEXT"),  FETCH("FETCH"),  OF("OF"),  SHARE("SHARE"),  NOWAIT("NOWAIT"),  RECURSIVE("RECURSIVE"),  TEMPORARY("TEMPORARY"),  TEMP("TEMP"),  UNLOGGED("UNLOGGED"),  RESTART("RESTART"),  IDENTITY("IDENTITY"),  CONTINUE("CONTINUE"),  CASCADE("CASCADE"),  RESTRICT("RESTRICT"),  USING("USING"),  CURRENT("CURRENT"),  RETURNING("RETURNING"),  COMMENT("COMMENT"),  OVER("OVER"),  TYPE("TYPE"),  ILIKE("ILIKE"),  START("START"),  PRIOR("PRIOR"),  CONNECT("CONNECT"),  WITH("WITH"),  EXTRACT("EXTRACT"),  CURSOR("CURSOR"),  MODEL("MODEL"),  MERGE("MERGE"),  MATCHED("MATCHED"),  ERRORS("ERRORS"),  REJECT("REJECT"),  UNLIMITED("UNLIMITED"),  BEGIN("BEGIN"),  EXCLUSIVE("EXCLUSIVE"),  MODE("MODE"),  WAIT("WAIT"),  ADVISE("ADVISE"),  SYSDATE("SYSDATE"),  DECLARE("DECLARE"),  EXCEPTION("EXCEPTION"),  GRANT("GRANT"),  REVOKE("REVOKE"),  LOOP("LOOP"),  GOTO("GOTO"),  COMMIT("COMMIT"),  SAVEPOINT("SAVEPOINT"),  CROSS("CROSS"),  PCTFREE("PCTFREE"),  INITRANS("INITRANS"),  MAXTRANS("MAXTRANS"),  INITIALLY("INITIALLY"),  ENABLE("ENABLE"),  DISABLE("DISABLE"),  SEGMENT("SEGMENT"),  CREATION("CREATION"),  IMMEDIATE("IMMEDIATE"),  DEFERRED("DEFERRED"),  STORAGE("STORAGE"),  MINEXTENTS("MINEXTENTS"),  MAXEXTENTS("MAXEXTENTS"),  MAXSIZE("MAXSIZE"),  PCTINCREASE("PCTINCREASE"),  FLASH_CACHE("FLASH_CACHE"),  CELL_FLASH_CACHE("CELL_FLASH_CACHE"),  NONE("NONE"),  LOB("LOB"),  STORE("STORE"),  CHUNK("CHUNK"),  CACHE("CACHE"),  NOCACHE("NOCACHE"),  LOGGING("LOGGING"),  NOCOMPRESS("NOCOMPRESS"),  KEEP_DUPLICATES("KEEP_DUPLICATES"),  EXCEPTIONS("EXCEPTIONS"),  PURGE("PURGE"),  COMPUTE("COMPUTE"),  ANALYZE("ANALYZE"),  OPTIMIZE("OPTIMIZE"),  TOP("TOP"),  ARRAY("ARRAY"),  DISTRIBUTE("DISTRIBUTE"),  EOF,  ERROR,  IDENTIFIER,  HINT,  VARIANT,  LITERAL_INT,  LITERAL_FLOAT,  LITERAL_HEX,  LITERAL_CHARS,  LITERAL_NCHARS,  LITERAL_ALIAS,  LINE_COMMENT,  MULTI_LINE_COMMENT,  BINARY_FLOAT,  BINARY_DOUBLE,  PARTITION,  PARTITIONED,  OVERWRITE,  SEL("SEL"),  LOCKING("LOCKING"),  ACCESS("ACCESS"),  VOLATILE("VOLATILE"),  MULTISET("MULTISET"),  POSITION("POSITION"),  RANGE_N("RANGE_N"),  FORMAT("FORMAT"),  QUALIFY("QUALIFY"),  MOD("MOD"),  CONCAT("CONCAT"),  UPSERT("UPSERT"),  LPAREN("("),  RPAREN(")"),  LBRACE("{"),  RBRACE("}"),  LBRACKET("["),  RBRACKET("]"),  SEMI(";"),  COMMA(","),  DOT("."),  DOTDOT(".."),  DOTDOTDOT("..,"),  EQ("="),  GT(">"),  LT("<"),  LT_SUB_GT("<->"),  BANG("!"),  BANGBANG("!!"),  BANG_TILDE("!~"),  BANG_TILDE_STAR("!~*"),  TILDE("~"),  TILDE_STAR("~*"),  TILDE_EQ("~="),  QUES("?"),  QUESQUES("??"),  QUESBAR("?|"),  QUESAMP("?&"),  COLON(":"),  COLONCOLON("::"),  COLONEQ(":="),  EQEQ("=="),  EQGT("=>"),  LTEQ("<="),  LTEQGT("<=>"),  LTGT("<>"),  GTEQ(">="),  BANGEQ("!="),  BANGGT("!>"),  BANGLT("!<"),  AMPAMP("&&"),  BARBAR("||"),  BARBARSLASH("||/"),  BARSLASH("|/"),  PLUS("+"),  SUB("-"),  SUBGT("->"),  SUBGTGT("->>"),  STAR("*"),  SLASH("/"),  AMP("&"),  BAR("|"),  CARET("^"),  CARETEQ("^="),  PERCENT("%"),  LTLT("<<"),  GTGT(">>"),  MONKEYS_AT("@"),  MONKEYS_AT_AT("@@"),  POUND("#"),  POUNDGT("#>"),  POUNDGTGT("#>>"),  MONKEYS_AT_GT("@>"),  LT_MONKEYS_AT("<@");
  
  public final String name;
  
  private Token()
  {
    this(null);
  }
  
  private Token(String name)
  {
    this.name = name;
  }
}

而在方言处理中并没有关于达梦数据库的写法:
com.alibaba.druid.sql.parser.ParserException: syntax error, error in :‘ TOP 3 * FROM 。。。
这就不难解释了,估计是druid自己也不知道怎么处理,然后就直接放行了,然后又怕会有不可预料的结果,于是也抛出了该异常!!

当然,如果是常规保留字冲突,在mapper中文件或者SQL 引起来就能解决(达梦是""、MySql是使用 ``)
可是此处却是使用TOP功能,使用引号视乎解决不了问题,还好我的诉求是取前3条数据,于是我试下使用另一个关键字 LIMIT,然后问题解决了

源SQL : SELECT TOP 3 * FROM XXXXXX WHERE XXXX ORDER BY XXX ASC
改成  : SELECT  * FROM XXXXXX WHERE XXXX ORDER BY XXX ASC LIMIT 3
上一篇:Spark——Spark SQL逻辑计划(Logical Plan)、物理计划(Physical Plan)和Catalyst优化器(Catalyst Optimizer)


下一篇:vue 组件之间的通信