赞
踩
由于工作需要,要将原有的mysql的表结构和数据都迁移到pgsql里面,因为pgsql支持更大数据存储,还能做AI大模型的向量数据库。
网上找了很多种办法,这种跨数据库的迁移方案都是收费的。只有navicate 工具可以免费迁移,怎耐我们公司禁止使用navicate 。
没有办法,我只能首先java代码实现数据库表结构迁移工作。
下面就是代码,本打算从mysql读取所有的数据库结构直接插入到pgsql里面,但是实际却发现有很多不合理的地方,与改成了将所有的mysql结构生成pgsql 的结构打印出来。使用者可以拷贝打印出来的内容形成一个脚本再使用。
里面有类型转换我中用到我们实际使用到的结果,还有不少没列出来,使用时要注意一下。
- import java.sql.*;
- import java.util.*;
-
- public class MysqlToPgsqlMigration {
- private static final String MYSQL_URL = "jdbc:mysql://127.0.0.1:3306/test";
- private static final String MYSQL_USER = "root";
- private static final String MYSQL_PASSWORD = "root";
-
- private static final String POSTGRESQL_URL = "jdbc:postgresql://127.0.0.1:5432/jeecg-boot";
- private static final String POSTGRESQL_USER = "root";
- private static final String POSTGRESQL_PASSWORD = "root1";
-
- public static void main(String[] args) throws SQLException, ClassNotFoundException {
- Class.forName("com.mysql.cj.jdbc.Driver");
- Class.forName("org.postgresql.Driver");
-
- try (Connection mysqlConn = DriverManager.getConnection(MYSQL_URL, MYSQL_USER, MYSQL_PASSWORD);
- Connection pgsqlConn = DriverManager.getConnection(POSTGRESQL_URL, POSTGRESQL_USER, POSTGRESQL_PASSWORD)) {
-
- DatabaseMetaData mysqlMeta = mysqlConn.getMetaData();
- Statement pgsqlStmt = pgsqlConn.createStatement();
-
- ResultSet tablesRs = mysqlMeta.getTables(null, null, "%", new String[]{"TABLE"});
-
- while (tablesRs.next()) {
- String tableName = tablesRs.getString("TABLE_NAME");
- // 重建表结构
- StringBuilder createTableSql = new StringBuilder("CREATE TABLE ");
- createTableSql.append(tableName).append(" (\n");
-
- ResultSet columnsRs = mysqlMeta.getColumns(null, null, tableName, null);
- List<String> primaryKeyColumns = new ArrayList<>();
- List<String> indexKeyColumns = new ArrayList<>();
- List<String> columnComments = new ArrayList<>();
- List<String> uniqueindexKeyColumns = new ArrayList<>();
- while (columnsRs.next()) {
- String columnName = columnsRs.getString("COLUMN_NAME");
- int dataType = columnsRs.getInt("DATA_TYPE");
- String typeName = mapColumnType(dataType);
- int size = columnsRs.getInt("COLUMN_SIZE");
- boolean isNullable = columnsRs.getBoolean("NULLABLE");
- String columnDef = columnsRs.getString("COLUMN_DEF");
- String columnComment = columnsRs.getString("REMARKS");
-
- createTableSql.append("\t").append(columnName).append(' ').append(typeName);
- if (!"INTEGER".equalsIgnoreCase(typeName)
- &&!"int4".equalsIgnoreCase(typeName)
- &&!"int8".equalsIgnoreCase(typeName)
- &&!"smallint".equalsIgnoreCase(typeName)
- &&!"bigint".equalsIgnoreCase(typeName)
- &&!"text".equalsIgnoreCase(typeName)){
- if (size > 0) {
- createTableSql.append('(').append(size).append(')');
- }
- }
-
- if (!isNullable) {
- createTableSql.append(" NOT NULL");
- }
-
- if (columnDef != null) {
- if ("INTEGER".equalsIgnoreCase(typeName)
- ||"int4".equalsIgnoreCase(typeName)
- ||"int8".equalsIgnoreCase(typeName)
- ||"smallint".equalsIgnoreCase(typeName)
- ||"bigint".equalsIgnoreCase(typeName)
- ||"NUMERIC".equalsIgnoreCase(typeName)){
- createTableSql.append(" DEFAULT ").append(columnDef);
- }else if("TIMESTAMP".equalsIgnoreCase(typeName)){
- createTableSql.append(" DEFAULT ").append("TO_TIMESTAMP('2024-02-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')");
- }else{
- createTableSql.append(" DEFAULT ").append("'" + escapeSingleQuotes(columnDef) + "'");
- }
- }
-
- columnComments.add(addColumnComment(tableName, columnName, columnComment, pgsqlStmt));
-
- createTableSql.append(",\n");
-
- // 检查是否为主键
- ResultSet pkRs = mysqlMeta.getPrimaryKeys(null, null, tableName);
- while (pkRs.next() && pkRs.getString("COLUMN_NAME").equals(columnName)) {
- primaryKeyColumns.add(columnName);
- }
- pkRs.close();
-
- }
-
- // 移除最后一个逗号和换行符
- createTableSql.setLength(createTableSql.length() - 2);
-
- // 添加主键约束
- if (!primaryKeyColumns.isEmpty()) {
- createTableSql.append(", \n PRIMARY KEY (")
- .append(String.join(",", primaryKeyColumns))
- .append(")");
- }
-
-
- createTableSql.append("\n);");
- System.out.println(createTableSql);
- //pgsqlStmt.executeUpdate(createTableSql.toString());
-
- // 处理索引及联合索引
- Map<String,List<String>> unIndexMap = new HashMap<>();
- ResultSet uniqueindexSet = mysqlMeta.getIndexInfo(null, null, tableName, true, false);
- while (uniqueindexSet.next()) {
- String indexName = uniqueindexSet.getString("INDEX_NAME"); // 索引名称
- String columnName = uniqueindexSet.getString("COLUMN_NAME"); // 索引列名
- /*boolean isNonUnique = uniqueindexSet.getBoolean("NON_UNIQUE"); // 是否非唯一索引(0表示唯一索引,1表示非唯一索引)
- System.out.println("indexName="+indexName+",columnName="+columnName+",isNonUnique="+isNonUnique);*/
- if ("PRIMARY".equalsIgnoreCase(indexName)){
- continue;
- }
- List<String> indexCols = unIndexMap.get(indexName);
- if (indexCols == null){
- indexCols = new ArrayList<>();
- }
- if (!indexCols.contains(columnName)){
- indexCols.add(columnName);
- }
- unIndexMap.put(indexName,indexCols);
-
- uniqueindexKeyColumns.add(columnName);
- }
- for (Map.Entry<String, List<String>> entry : unIndexMap.entrySet()) {
- String indexName = entry.getKey();
- List<String> list = entry.getValue();
- if (list.size()>1){ // 联合索引
- System.out.println("CREATE UNIQUE INDEX "+indexName+" ON "+tableName+"("+String.join(",",list)+");");
- }else{// 普通索引
- if (indexName.startsWith("uni")||indexName.startsWith("uk_")){
- System.out.println("CREATE UNIQUE INDEX "+indexName+" ON "+tableName+"("+list.get(0)+");");
- }else{
- System.out.println("CREATE INDEX "+indexName+" ON "+tableName+"("+list.get(0)+");");
- }
- }
- }
- uniqueindexSet.close();
-
- // 处理外键索引
- /*ResultSet foreignKeysRS = mysqlMeta.getImportedKeys(null, null, tableName);
- while (foreignKeysRS.next()) {
- String fkName = foreignKeysRS.getString("FK_NAME"); // 外键约束名称
- String fkColumnName = foreignKeysRS.getString("FKCOLUMN_NAME"); // 本表中对应的外键列名
- String pkTableName = foreignKeysRS.getString("PKTABLE_NAME"); // 主键所在的表名
- String pkColumnName = foreignKeysRS.getString("PKCOLUMN_NAME"); // 主键列名
- System.out.println("Foreign Key: " + fkName);
- System.out.println("From Column: " + fkColumnName + " in Table " + tableName);
- System.out.println("References Column: " + pkColumnName + " in Table " + pkTableName);
- }
- foreignKeysRS.close();*/
-
- //字段注释
- if (!columnComments.isEmpty()){
- for (String comment : columnComments) {
- System.out.println(comment);
- }
- }
- // 获取表注释并添加
- String tableComment = getTableComment(tableName, mysqlMeta);
- System.out.println(addTableComment(tableName, tableComment, pgsqlStmt));
- System.out.println("\n");
- // 插入数据
- //copyTableData(tableName, mysqlConn, pgsqlConn);
- }
-
- tablesRs.close();
- }
- }
-
- private static String addTableComment(String tableName, String comment, Statement stmt) throws SQLException {
- /*if (comment != null && !comment.isEmpty()) {
- stmt.executeUpdate("COMMENT ON TABLE " + tableName + " IS '" + escapeSingleQuotes(comment) + "'");
- }*/
- return "COMMENT ON TABLE " + tableName + " IS '" + escapeSingleQuotes(comment) + "';";
- }
-
- private static String addColumnComment(String tableName, String columnName, String comment, Statement stmt) throws SQLException {
- return "COMMENT ON COLUMN " + tableName + "." + columnName + " IS '" + escapeSingleQuotes(comment) + "';";
- /*if (comment != null && !comment.isEmpty()) {
- stmt.executeUpdate("COMMENT ON COLUMN " + tableName + "." + columnName + " IS '" + escapeSingleQuotes(comment) + "'");
- }*/
- }
-
- private static String getTableComment(String tableName, DatabaseMetaData meta) throws SQLException {
- ResultSet rs = meta.getTables(null, null, tableName, null);
- if (rs.next()) {
- return rs.getString("REMARKS");
- }
- return "";
- }
-
- private static String mapColumnType(int mysqlDataType) {
- // 这里仅提供一种简单的映射方式,实际情况可能更复杂
- switch (mysqlDataType) {
- // case Types.BIT:
- // return "BOOLEAN";
- case Types.TINYINT:
- return "SMALLINT";
- case Types.BIGINT:
- return "BIGINT";
- case Types.INTEGER:
- return "INTEGER";
- case Types.DATE:
- return "timestamp";
- case Types.DOUBLE:
- return "NUMERIC";
- case Types.NUMERIC:
- return "NUMERIC";
- case Types.DECIMAL:
- return "NUMERIC";
- case Types.LONGVARCHAR:
- return "text";
- case Types.TIMESTAMP:
- return "TIMESTAMP";
- case Types.BLOB:
- return "BYTEA";
- // 其他类型...
- default:
- return "varchar";
- }
- }
-
- private static void copyTableData(String tableName, Connection mysqlConn, Connection pgsqlConn) throws SQLException {
- String selectAllDataSql = "SELECT * FROM " + tableName;
- PreparedStatement mysqlPs = mysqlConn.prepareStatement(selectAllDataSql);
- ResultSet dataRs = mysqlPs.executeQuery();
- ResultSetMetaData metaData = dataRs.getMetaData();
- StringBuilder insertSql = new StringBuilder("INSERT INTO ").append(tableName).append(" VALUES (");
-
- for (int i = 1; i <= metaData.getColumnCount(); i++) {
- insertSql.append("?");
- if (i < metaData.getColumnCount()) {
- insertSql.append(",");
- }
- }
- insertSql.append(")");
-
- PreparedStatement pgsqlPs = pgsqlConn.prepareStatement(insertSql.toString());
- while (dataRs.next()) {
- for (int i = 1; i <= metaData.getColumnCount(); i++) {
- pgsqlPs.setObject(i, dataRs.getObject(i));
- }
- pgsqlPs.addBatch();
- }
- pgsqlPs.executeBatch();
- }
-
- private static String escapeSingleQuotes(String str) {
- return str.replace("'", "''");
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。