jack hace 2 meses
commit
34446e44ae
Se han modificado 9 ficheros con 290 adiciones y 0 borrados
  1. BIN
      .DS_Store
  2. 6 0
      db_config.txt
  3. 5 0
      go.mod
  4. 2 0
      go.sum
  5. BIN
      main
  6. 49 0
      main.go
  7. 3 0
      table_list.txt
  8. 122 0
      utils/database.go
  9. 103 0
      utils/file_loader.go

BIN
.DS_Store


+ 6 - 0
db_config.txt

@@ -0,0 +1,6 @@
+# 数据库配置
+host=127.0.0.1
+port=5432
+username=jack
+password=aaaAAA111
+database=dis

+ 5 - 0
go.mod

@@ -0,0 +1,5 @@
+module pg2csv
+
+go 1.25.1
+
+require github.com/lib/pq v1.10.9

+ 2 - 0
go.sum

@@ -0,0 +1,2 @@
+github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
+github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=

BIN
main


+ 49 - 0
main.go

@@ -0,0 +1,49 @@
+package main
+
+import (
+	"fmt"
+	"pg2csv/utils"
+)
+
+func main() {
+	// 测试加载表列表
+	tables, err := utils.LoadTableList()
+	if err != nil {
+		fmt.Printf("加载表列表错误: %v\n", err)
+	} else {
+		fmt.Printf("加载的数据表列表: %v\n", tables)
+	}
+
+	// 测试加载数据库配置
+	config, err := utils.LoadDBConfig()
+	if err != nil {
+		fmt.Printf("加载数据库配置错误: %v\n", err)
+	} else {
+		fmt.Printf("加载的数据库配置: %v\n", config)
+	}
+
+	if tables == nil || config == nil {
+		fmt.Println("程序退出!")
+		return
+	}
+
+	// 连接数据库
+	db, err := utils.ConnectDB(config)
+	if err != nil {
+		fmt.Printf("数据库连接失败: %v\n", err)
+		return
+	}
+	defer db.Close()
+
+	fmt.Println("数据库连接成功!")
+
+	// 导出所有表到CSV
+	fmt.Println("开始导出数据表到CSV...")
+	dbName := config["database"]
+	if err := utils.ExportAllTables(db, dbName, tables); err != nil {
+		fmt.Printf("导出数据失败: %v\n", err)
+		return
+	}
+
+	fmt.Println("所有表导出完成!")
+}

+ 3 - 0
table_list.txt

@@ -0,0 +1,3 @@
+# 表列表,每行一个表名
+sale_order
+sale_order_line

+ 122 - 0
utils/database.go

@@ -0,0 +1,122 @@
+package utils
+
+import (
+	"database/sql"
+	"encoding/csv"
+	"fmt"
+	"os"
+	"path/filepath"
+
+	_ "github.com/lib/pq"
+)
+
+// ConnectDB 连接数据库
+func ConnectDB(config map[string]string) (*sql.DB, error) {
+	// 构建连接字符串
+	connStr := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=disable",
+		config["host"], config["port"], config["username"], config["password"], config["database"])
+
+	db, err := sql.Open("postgres", connStr)
+	if err != nil {
+		return nil, fmt.Errorf("数据库连接失败: %v", err)
+	}
+
+	// 测试连接
+	err = db.Ping()
+	if err != nil {
+		return nil, fmt.Errorf("数据库连接测试失败: %v", err)
+	}
+
+	return db, nil
+}
+
+// ExportTableToCSV 导出表数据到CSV
+func ExportTableToCSV(db *sql.DB, dbName string, tableName string) error {
+	// 查询表数据
+	query := fmt.Sprintf("SELECT * FROM %s ORDER BY id DESC", tableName)
+	rows, err := db.Query(query)
+	if err != nil {
+		return fmt.Errorf("查询表 %s 失败: %v", tableName, err)
+	}
+	defer rows.Close()
+
+	// 获取列名
+	columns, err := rows.Columns()
+	if err != nil {
+		return fmt.Errorf("获取列名失败: %v", err)
+	}
+
+	// 创建输出目录
+	outputDir := filepath.Join("output", dbName)
+	if err := os.MkdirAll(outputDir, 0755); err != nil {
+		return fmt.Errorf("创建输出目录失败: %v", err)
+	}
+
+	// 创建CSV文件
+	filePath := filepath.Join(outputDir, tableName+".csv")
+	file, err := os.Create(filePath)
+	if err != nil {
+		return fmt.Errorf("创建CSV文件失败: %v", err)
+	}
+	defer file.Close()
+
+	writer := csv.NewWriter(file)
+	defer writer.Flush()
+
+	// 写入列名
+	if err := writer.Write(columns); err != nil {
+		return fmt.Errorf("写入列名失败: %v", err)
+	}
+
+	// 准备接收数据的切片
+	values := make([]interface{}, len(columns))
+	valuePtrs := make([]interface{}, len(columns))
+	for i := range columns {
+		valuePtrs[i] = &values[i]
+	}
+
+	// 读取数据并写入CSV
+	recordCount := 0
+	for rows.Next() {
+		err := rows.Scan(valuePtrs...)
+		if err != nil {
+			return fmt.Errorf("读取数据失败: %v", err)
+		}
+
+		// 转换数据为字符串
+		record := make([]string, len(columns))
+		for i, val := range values {
+			if val == nil {
+				record[i] = ""
+			} else {
+				record[i] = fmt.Sprintf("%v", val)
+			}
+		}
+
+		// 写入CSV
+		if err := writer.Write(record); err != nil {
+			return fmt.Errorf("写入CSV数据失败: %v", err)
+		}
+
+		recordCount++
+	}
+
+	// 检查遍历过程中是否有错误
+	if err := rows.Err(); err != nil {
+		return fmt.Errorf("遍历数据失败: %v", err)
+	}
+
+	fmt.Printf("表 %s 导出完成,共 %d 条数据,文件位置: %s\n", tableName, recordCount, filePath)
+	return nil
+}
+
+// ExportAllTables 导出所有表到CSV
+func ExportAllTables(db *sql.DB, dbName string, tables []string) error {
+	for _, table := range tables {
+		fmt.Printf("正在导出表: %s\n", table)
+		if err := ExportTableToCSV(db, dbName, table); err != nil {
+			return fmt.Errorf("导出表 %s 失败: %v", table, err)
+		}
+	}
+	return nil
+}

+ 103 - 0
utils/file_loader.go

@@ -0,0 +1,103 @@
+package utils
+
+import (
+	"fmt"
+	"os"
+	"strings"
+)
+
+func LoadTableList() ([]string, error) {
+	// 检查文件是否存在
+	if _, err := os.Stat("table_list.txt"); os.IsNotExist(err) {
+		// 文件不存在,创建文件
+		file, err := os.Create("table_list.txt")
+		if err != nil {
+			return nil, fmt.Errorf("创建 table_list.txt 文件失败: %v", err)
+		}
+		defer file.Close()
+
+		// 可以写入一些示例内容
+		_, err = file.WriteString("# 表列表,每行一个表名\n# users\n# orders\n# products\n")
+		if err != nil {
+			return nil, fmt.Errorf("写入 table_list.txt 文件失败: %v", err)
+		}
+
+		return nil, fmt.Errorf("table_list.txt 文件不存在,已创建空文件")
+	}
+
+	// 读取文件内容
+	content, err := os.ReadFile("table_list.txt")
+	if err != nil {
+		return nil, fmt.Errorf("读取 table_list.txt 文件失败: %v", err)
+	}
+
+	// 按行分割内容
+	lines := strings.Split(string(content), "\n")
+	var tables []string
+
+	for _, line := range lines {
+		line = strings.TrimSpace(line)
+		// 跳过空行和注释行
+		if line == "" || strings.HasPrefix(line, "#") {
+			continue
+		}
+		tables = append(tables, line)
+	}
+
+	return tables, nil
+}
+
+func LoadDBConfig() (map[string]string, error) {
+	// 检查文件是否存在
+	if _, err := os.Stat("db_config.txt"); os.IsNotExist(err) {
+		// 文件不存在,创建文件
+		file, err := os.Create("db_config.txt")
+		if err != nil {
+			return nil, fmt.Errorf("创建 db_config.txt 文件失败: %v", err)
+		}
+		defer file.Close()
+
+		// 写入默认配置示例
+		defaultConfig := `# 数据库配置
+host=localhost
+port=3306
+username=root
+password=
+database=test
+`
+		_, err = file.WriteString(defaultConfig)
+		if err != nil {
+			return nil, fmt.Errorf("写入 db_config.txt 文件失败: %v", err)
+		}
+
+		return nil, fmt.Errorf("db_config.txt 文件不存在,已创建示例配置文件")
+	}
+
+	// 读取文件内容
+	content, err := os.ReadFile("db_config.txt")
+	if err != nil {
+		return nil, fmt.Errorf("读取 db_config.txt 文件失败: %v", err)
+	}
+
+	// 解析配置
+	config := make(map[string]string)
+	lines := strings.Split(string(content), "\n")
+
+	for _, line := range lines {
+		line = strings.TrimSpace(line)
+		// 跳过空行和注释行
+		if line == "" || strings.HasPrefix(line, "#") {
+			continue
+		}
+
+		// 解析 key=value 格式
+		parts := strings.SplitN(line, "=", 2)
+		if len(parts) == 2 {
+			key := strings.TrimSpace(parts[0])
+			value := strings.TrimSpace(parts[1])
+			config[key] = value
+		}
+	}
+
+	return config, nil
+}