oracle表结构同步到oracle 问题修复

This commit is contained in:
hekaiyu 2025-11-12 11:48:43 +08:00
parent 528479f777
commit e62f546a95

View File

@ -136,7 +136,7 @@ public class StasSyncStrategyServiceImpl extends ServiceImpl<StasSyncStrategyMap
* @return 创建表的SQL语句
* @throws SQLException 数据库异常
*/
private static String getCreateTableSql(Connection conn, String sourceOwner, String targetOwner,
private String getCreateTableSql(Connection conn, String sourceOwner, String targetOwner,
String table, Integer sourceDbType, Integer targetDbType) throws SQLException {
if (!isTableExists(conn, sourceOwner, table, sourceDbType)) {
throw new SQLException("" + table + " 在源数据库中不存在");
@ -146,16 +146,114 @@ public class StasSyncStrategyServiceImpl extends ServiceImpl<StasSyncStrategyMap
// Oracle转PostgreSQL的特殊处理
return generatePgCreateTableFromOracle(conn, sourceOwner, targetOwner, table);
} else {
// 其他情况使用原始方式
return String.format("CREATE TABLE \"%s\".\"%s\" AS SELECT * FROM \"%s\".\"%s\" WHERE 1=0",
targetOwner.toUpperCase(), table, sourceOwner.toUpperCase(), table);
return generateOracleCreateTable(conn, sourceOwner, targetOwner, table);
}
}
public String generateOracleCreateTable(Connection conn, String sourceOwner, String targetOwner, String tableName) {
try {
DatabaseMetaData metaData = conn.getMetaData();
StringBuilder ddl = new StringBuilder();
// 使用双引号括起targetOwner和tableName
ddl.append("CREATE TABLE \"").append(targetOwner).append("\".\"").append(tableName).append("\" (\n");
// 获取列信息
String columnSql = "SELECT column_name, data_type, data_length, data_precision, data_scale, nullable " +
"FROM all_tab_columns " +
"WHERE owner = ? AND table_name = ? " +
"ORDER BY column_id";
try (PreparedStatement pstmt = conn.prepareStatement(columnSql)) {
pstmt.setString(1, sourceOwner.toUpperCase());
pstmt.setString(2, tableName.toUpperCase());
ResultSet rs = pstmt.executeQuery();
boolean first = true;
while (rs.next()) {
if (!first) {
ddl.append(",\n");
}
String columnName = rs.getString("column_name");
String dataType = rs.getString("data_type");
int dataLength = rs.getInt("data_length");
int dataPrecision = rs.getInt("data_precision");
int dataScale = rs.getInt("data_scale");
String nullable = rs.getString("nullable");
String isNullable = "";
if ("N".equalsIgnoreCase(nullable)) {
isNullable = " NOT NULL";
}
// 列名也用双引号括起来
ddl.append(" \"").append(columnName).append("\" ").append(dataType);
// 处理数据类型长度/精度
if (dataPrecision > 0) {
// 数字类型NUMBER(p,s), NUMERIC(p,s)
ddl.append("(").append(dataPrecision);
if (dataScale > 0) {
ddl.append(",").append(dataScale);
}
ddl.append(")");
} else if (dataLength > 0 &&
("VARCHAR2".equalsIgnoreCase(dataType) ||
"CHAR".equalsIgnoreCase(dataType) ||
"NVARCHAR2".equalsIgnoreCase(dataType) ||
"NCHAR".equalsIgnoreCase(dataType) ||
"RAW".equalsIgnoreCase(dataType))) {
// 字符类型和RAW类型
ddl.append("(").append(dataLength).append(")");
} else if ("DATE".equalsIgnoreCase(dataType) ||
"CLOB".equalsIgnoreCase(dataType) ||
"BLOB".equalsIgnoreCase(dataType) ||
"LONG".equalsIgnoreCase(dataType) ||
"FLOAT".equalsIgnoreCase(dataType)) {
// 这些类型不需要长度/精度信息
// 什么也不做
} else {
// 其他可能需要长度的类型
ddl.append("(").append(dataLength).append(")");
}
ddl.append(isNullable);
first = false;
}
}
// 获取主键信息
ResultSet primaryKeys = metaData.getPrimaryKeys(null, sourceOwner.toUpperCase(), tableName.toUpperCase());
List<String> pkColumns = new ArrayList<>();
while (primaryKeys.next()) {
// 主键列名也用双引号括起来
pkColumns.add("\"" + primaryKeys.getString("COLUMN_NAME") + "\"");
}
primaryKeys.close();
if (!pkColumns.isEmpty()) {
ddl.append(",\n PRIMARY KEY (");
ddl.append(String.join(", ", pkColumns));
ddl.append(")");
}
// 移除末尾的分号只保留右括号
ddl.append("\n)");
return ddl.toString();
} catch (SQLException e) {
throw new RuntimeException("生成表DDL失败: " + e.getMessage(), e);
}
}
/**
* 生成从Oracle到PostgreSQL的建表语句
*/
private static String generatePgCreateTableFromOracle(Connection conn, String sourceOwner,
private String generatePgCreateTableFromOracle(Connection conn, String sourceOwner,
String targetOwner, String tableName) throws SQLException {
StringBuilder sqlBuilder = new StringBuilder();
//模式名称
@ -236,7 +334,7 @@ public class StasSyncStrategyServiceImpl extends ServiceImpl<StasSyncStrategyMap
/**
* Oracle数据类型到PostgreSQL的映射
*/
private static String mapOracleTypeToPg(String oracleType, int length, int precision, int scale) {
private String mapOracleTypeToPg(String oracleType, int length, int precision, int scale) {
switch (oracleType.toUpperCase()) {
case "VARCHAR2":
return "VARCHAR(" + (length > 0 ? length : 255) + ")";
@ -284,7 +382,7 @@ public class StasSyncStrategyServiceImpl extends ServiceImpl<StasSyncStrategyMap
* @return 表是否存在
* @throws SQLException 数据库异常
*/
private static boolean isTableExists(Connection conn, String schema, String tableName, Integer dbType) throws SQLException {
private boolean isTableExists(Connection conn, String schema, String tableName, Integer dbType) throws SQLException {
String sql;
if (SourceDataTypeEnum.ORACLE.getKey().equals(dbType)) {
sql = "SELECT COUNT(*) FROM all_tables WHERE owner = ? AND (table_name = ? OR table_name = ?)";
@ -321,7 +419,7 @@ public class StasSyncStrategyServiceImpl extends ServiceImpl<StasSyncStrategyMap
* @return 列是否存在
* @throws SQLException 数据库异常
*/
private static boolean isColumnExists(Connection conn, String schema, String tableName,
private boolean isColumnExists(Connection conn, String schema, String tableName,
String columnName, Integer dbType) throws SQLException {
String sql;
if (SourceDataTypeEnum.ORACLE.getKey().equals(dbType)) {