【YashanDB知识库】共享超过32000字节字符串插入CLOB类型方案
本文内容来自YashanDB官网,原文内容请见 https://www.yashandb.com/newsinfo/7508311.html?templateId=1718516
概述
超过32000字节字符串通过insert into values的方式插入崖山数据库CLOB类型字段(无论是DBeaver还是yasql),会报YAS-04107 string exceeding limit 32000错误。本文通过jdbc动态变量绑定的方案支持超过32000字节字符串插入到CLOB类型字段的表。
方案
通过jdbc变量绑定的方式可以支持超过32000字节字符串插入到CLOB类型字段的表,但是不通用,不同的表需要编写不同的插入代码,本方案使用yashandb jdbc和druid组件,动态解析插入sql的字段和字段类型,进行动态变量绑定,可以支持不同的表进行超过32000字节字符串插入到CLOB类型字段的表。
关键代码
pom主要依赖
主要代码
public static void insertSql(DataSource dataSource, String sql) { log.info("insertSql sql = {}", sql);
// 获取数据库连接 Connection connection = getConnection(dataSource);
PreparedStatement ps = null;
// 通过sql获取SQLStatement SQLStatement stmt = InsertSqlParserUtil.getInsertStmt(sql);
// 通过SQLStatement动态获取insert into xxx values(?,?,?......)插入语句 String insertSQL = InsertSqlParserUtil.getInsertSQL(stmt);
try { // 通过insertSQL获取PreparedStatement对象 ps = connection.prepareStatement(insertSQL); // 动态绑定插入变量 InsertSqlParserUtil.bindPreparedStatement(stmt, ps); // 执行插入 ps.execute(); } catch (SQLException e) { log.error("insert异常", e); } finally { closePreparedStatement(ps); closeConnection(connection); } }
public static SQLStatement getInsertStmt(String sql) { SQLStatement stmt = null;
DbType druidDbType = DbType.oracle;
String formatSQL = SQLUtils.format(sql, druidDbType); List<SQLStatement> stmtList = new ArrayList<>(); try { stmtList = SQLUtils.parseStatements(formatSQL, druidDbType); } catch (Exception exp) { log.error("parseStatements sql is :{}", formatSQL); log.error("parseStatements exception : {}", exp.getMessage()); }
log.info("getInsertValues param stmtList size is {}", stmtList.size());
stmt = stmtList.get(0); SchemaStatVisitor statVisitor = SQLUtils.createSchemaStatVisitor(druidDbType); stmt.accept(statVisitor); log.info(SQLUtils.toSQLString(stmt));
if (stmt instanceof OracleInsertStatement) { return stmt; } return stmt; }
public static String getInsertSQL(SQLStatement stmt) { StringBuilder sb = new StringBuilder(); String schemaName = null; String tableName = null; if (stmt instanceof OracleInsertStatement) { schemaName = ((OracleInsertStatement) stmt).getTableSource().getSchema(); tableName = ((OracleInsertStatement) stmt).getTableSource().getTableName(); if (StringUtils.isEmpty(tableName)) { return sb.toString(); } else if (!StringUtils.isEmpty(schemaName)) { tableName = schemaName + "." + tableName; }
if (!StringUtils.isEmpty(tableName)) { sb.append("INSERT INTO ").append(tableName.toUpperCase()).append(" VALUES("); }
List<SQLExpr> values = ((OracleInsertStatement) stmt).getValuesList().get(0).getValues();
for (int i = 0; i < values.size(); i++) { if (i == values.size() - 1) { sb.append("?"); } else { sb.append("?,"); } } sb.append(")"); }
return sb.toString(); }
public static void bindPreparedStatement(SQLStatement stmt, PreparedStatement pst) { List<SQLExpr> values = ((OracleInsertStatement) stmt).getValuesList().get(0).getValues(); for (int i = 0; i < values.size(); i++) { SQLExpr value = values.get(i); try { if (value instanceof SQLIntegerExpr) { pst.setInt(i + 1, ((SQLIntegerExpr) value).getNumber().intValue()); } else if (value instanceof SQLBigIntExpr) { pst.setLong(i + 1, ((SQLBigIntExpr) value).getNumber().intValue()); } else if (value instanceof SQLNumberExpr) { Number number = ((SQLNumberExpr) value).getNumber(); if (number instanceof BigDecimal) { pst.setBigDecimal(i + 1, (BigDecimal) number); } } else if (value instanceof SQLCharExpr) { pst.setString(i + 1, ((SQLCharExpr) value).getText()); } else if (value instanceof SQLTimestampExpr) { pst.setTimestamp(i + 1, Timestamp.valueOf(((SQLTimestampExpr) value).getValue())); } else if (value instanceof SQLDateExpr) { pst.setDate(i + 1, Date.valueOf(((SQLDateExpr) value).getValue())); } else if (value instanceof SQLDateTimeExpr) { pst.setDate(i + 1, Date.valueOf(((SQLDateTimeExpr) value).getValue())); } else if (value instanceof SQLNullExpr) { pst.setNull(i + 1, Types.NULL); } else { pst.setString(i + 1, ((SQLCharExpr) value).getText()); } } catch (SQLException e) { log.error("绑定插入变量异常", e); } } } |
程序使用说明
注:需要安装jdk1.8
1、解压yashandb-sql-imp-1.0-bin.zip,然后设置yashandb-sql-imp/conf/jdbc.properties中需要导入的崖山用户连接
2、导入命令:
win:
cd yashandb-sql-imp/bin
.\yashandb-sql-imp.bat D:\clob_test
linux:
cd yashandb-sql-imp/bin
./yashandb-sql-imp.sh /data/clob_test
注:参数/data/clob_test为sql文件存放目录,支持多sql文件,但只支持执行insert into xxx values这样的插入语句
附件
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比