makimasa
@makimasa

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Go言語でテキストファイルの内容をpsqlDBにインポートしたい

解決したいこと

コードをどのように修正すれば解決できるのか教えていただきたいです。
下記のコードでテキストファイルの内容を条件分岐によってDBにコミットしたいのですが、うまくいきません。
テキストファイルの内容から必要なものは変数に代入、足りないものは別に用意してSQLを作成するようにしています。

急に野に放たれプログラムを作成してとのことで、chatGPTを活用しながらここまで来たのですがこの先に進めず困っています。

必要な情報もこれで良いのかも分かりませんが、どうかよろしくお願いいたします。

テキストファイルの内容
0000000000001,20230317,0,仮名 太郎,,19000101,2,長野県飯田市北方9999-1,,,0123456789
0000000000003,20221231,0,仮名 次郎,,19000101,1,長野県飯田市北方9999-2,,,1234567890
0000000000004,20230307,0,仮名 花子,,19000101,1,長野県飯田市北方123-3,,,2345678901
0000000000006,20230311,0,仮名 良子,,19000101,2,長野県飯田市鼎切石1234-4,,,3456789012

DB情報
user_cd character varying(8) Yes
connect_kbn integer
pointcardno character varying
user_nm character varying
user_kn character varying
user_pw character varying
user_mail character varying
birthday date
gender character varying(2)
add1 character varying
add2 character varying
userphone integer
imported character varying(1)
points integer

発生している問題・エラー

SQLが実行されているか分からない。
DBへのコミットが実行されない

該当するソースコード

package main

import (
	"bufio"
	"database/sql"
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	_ "github.com/go-sql-driver/mysql"
	_ "github.com/lib/pq"
	"golang.org/x/text/encoding/japanese"
	"golang.org/x/text/transform"

)

func convertShiftJISToUTF8(file string) error {
	// shiftjisファイルを開く
	f, err := os.Open(file)
	if err != nil {
		return err
	}
	defer f.Close()

	// ShiftJISからUTF-8に変換するReaderを作成
	utf8Reader := transform.NewReader(f, japanese.ShiftJIS.NewDecoder())

	// 変換したデータを読み込む
	data, err := ioutil.ReadAll(utf8Reader)
	if err != nil {
		return err
	}

	// 変換したデータを元のファイルに上書きする
	err = ioutil.WriteFile(file, data, os.ModePerm)
	if err != nil {
		return err
	}

	return nil
}

func main() {

	//dirフラグを定義する
	//dir := flag.String("dir", "C:\\xampp\\htdocs\\point_receive\\00000072", "target directory") //ターゲットのディレクトリ
	dir := flag.String("dir", "C:\\xampp\\htdocs\\point_receive\\00000072", "target directory") //ターゲットのディレクトリ

	// コマンドライン引数を解析する
	flag.Parse()

	//最終更新日を持つファイルを走査
	var latestModtime time.Time
	var latestFile string

	err := filepath.Walk(*dir, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		if info.Mode().IsRegular() && info.ModTime().After(latestModtime) {
			latestModtime = info.ModTime()
			latestFile = path
		}
		return nil
	})

	if err != nil {
		fmt.Println("Error", err)
		return
	}

	fmt.Println("Latest modified file", latestFile)
	fmt.Println("Latest modification time", latestModtime)

	// PostgreSQLデータベースに接続する
	db, err := sql.Open("postgres", "postgres://postgres:masterkey@localhost:5432/loglog?sslmode=disable")
	if err != nil {
		log.Fatal(err)
	}

	defer db.Close()

	//トランザクションを開始
	tx, err := db.Begin()
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println("success!")
	defer func() {
		if p := recover(); p != nil {
			tx.Rollback()
			panic(p)
		} else if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	// defer func() {
	// 	if err != nil {
	// 		fmt.Println(err)
	// 		tx.Rollback()
	// 	} else {
	// 		err = tx.Commit()
	// 		if err != nil {
	// 			fmt.Println(err)
	// 		}
	// 	}
	// }()

	// recordExistsは、指定されたユーザーコードがテーブルに存在するかどうかを確認するヘルパー関数
	// recordExists := func(pointcardno string) bool {
	// 	var exists bool
	// 	err := tx.QueryRow("SELECT EXISTS(SELECT 1 FROM importusers WHERE  pointcardno=$1)", pointcardno).Scan(&exists)
	// 	logError(err, "Failed to check if record exists")
	// 	return exists
	// }
	recordExists := func(pointcardno string) bool {
		var exists bool
		err := tx.QueryRow("SELECT EXISTS(SELECT 1 FROM importusers WHERE pointcardno=$1)", pointcardno).Scan(&exists)
		logError(err, "Failed to check if record exists")
		return exists
	}

	// latestFileのShiftJISをUTF-8に変換する
	err = convertShiftJISToUTF8(latestFile)
	if err != nil {
		fmt.Println(err)
		return
	}

	// ファイルを開く
	file, err := os.Open(latestFile)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer file.Close()

	//スキャナを作成
	scanner := bufio.NewScanner(file)

	//行ごとにデータを読み込む
	for scanner.Scan() {
		fmt.Println(scanner.Text()) //確認用としてターミナルにスキャンしたファイル名を出力
		line := scanner.Text()
		fields := strings.Split(line, ",")
		if len(fields) <= 12 {
			continue
		}

		// SQL をターミナルに出力
		fmt.Println("INSERT INTO importusers (user_cd, connect_kbn, pointcardno, user_nm, user_kn, user_pw, user_mail, birthday, gender, add1, add2, userphone, imported) VALUES (" + fields[0] + ", ',', '" + fields[2] + "', '" + fields[3] + "', '" + fields[4] + "', '', '', '" + fields[6] + "', '', '', '', '', '') ON CONFLICT (user_cd, pointcardno) DO UPDATE SET point = importusers.point + excluded.point, last_date = excluded.last_date;")

		//下記変数がテキストファイルの内容を代入する変数
		user_cd, _ := strconv.Atoi(fields[0])

		last_date := fields[1]

		point := fields[2]

		user_nm := fields[3]
		_ = user_nm
		user_kn := fields[4]
		_ = user_kn
		birthday := fields[5]
		_ = birthday
		gender := fields[6]
		_ = gender
		add1 := fields[7]
		_ = add1
		add2 := fields[8]
		_ = add2
		add3 := fields[9]
		_ = add3
		userphone := fields[10]
		_ = userphone
		imported := "1"

		// 変数が空白なら初期値を代入
		if last_date == "" {
			last_date = "2000/01/01"
		}
		if point == "" {
			point = "0"
		}
		if user_nm == "" {
			user_nm = "''" //ユーザー名が空白の場合は、空文字列を設定する
		}

		if user_kn == "" {
			user_kn = "''" //ユーザーかな名が空白の場合は、空文字列を設定する
		}

		if birthday == "" {
			birthday = "''" //生年月日が空白の場合は、空文字列を設定する
		}

		if gender == "" {
			gender = "''" //性別が空白の場合は、空文字列を設定する
		}

		if add1 == "" {
			add1 = "''" //住所1が空白の場合は、空文字列を設定する
		}

		if add2 == "" {
			add2 = "''" //住所2が空白の場合は、空文字列を設定する
		}

		if add3 == "" {
			add3 = "''" //住所3が空白の場合は、空文字列を設定する
		}

		if userphone == "" {
			userphone = "''" //電話番号が空白の場合は、空文字列を設定する
		}

		//pointcardnoを作成
		pointcardno := "1234567890123"
		num := pointcardno
		pointcardno = addCheckDigit(num) //チェックディジットを付与した結果を取得

		// SQLを作成
		if recordExists(pointcardno) {
			sql := "UPDATE importusers SET point=$1 WHERE user_cd=$2 AND pointcardno=$3 "

			// ステートメントを作成
			stmt, err := tx.Prepare(sql)
			if err != nil {
				logError(err, "Failed to prepare statement")
				return
			}
			defer stmt.Close()

			// パラメータをバインドしてステートメントを実行
			res, err := stmt.Exec(point, user_cd, pointcardno)
			if err != nil {
				logError(err, "Failed to execute statement")
				return
			}
			fmt.Println(res)

		} else {
			sql := "INSERT INTO importusers(user_cd,connect_kbn,pointcardno,user_nm,user_kn,user_pw,user_mail,birthday,gender,add1, add2, userphone, imported, points) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14) ON CONFLICT (pointcardno) DO UPDATE SET point = importusers.points + excluded.points;"

			// ステートメントを作成
			stmt, err := tx.Prepare(sql)
			if err != nil {
				logError(err, "Failed to prepare statement")
				return
			}
			defer stmt.Close()

			// パラメータをバインドしてステートメントを実行
			res, err := stmt.Exec("", "0", pointcardno, user_nm, user_kn, "", "", birthday, gender, add1, add2, userphone, imported, point)
			logError(err, "Failed to execute statement")
			fmt.Println(res)
			if err != nil {
				logError(err, "Failed to execute statement")
				return
			}
			fmt.Println(res)
		}
		// // SQL文をターミナルに出力
		// query := fmt.Printf("User code: %d, connected: %s, point card no: %s, user name: %s, user kana name: %s, email: %s, birthday: %s, gender: %s, address 1: %s, address 2: %s, phone number: %s\n",fields[0], fields[1], fields[2], fields[3], fields[4], fields[5], fields[6], fields[7], fields[8], fields[9], fields[10])
		// fmt.Println(query)
		query := fmt.Sprintf("INSERT INTO importusers (user_cd, connect_kbn, pointcardno, user_nm, user_kn, user_pw, user_mail, birthday, gender, add1, add2, userphone, imported, points) "+
			"VALUES (%s, '','', '%s', '%s', '%s', '', '', '%s', '', '', '', '', ) "+
			"ON CONFLICT (user_cd, pointcardno) DO UPDATE SET point = importusers.point + excluded.point, last_date = excluded.last_date",
			fields[0], fields[2], fields[3], fields[4], fields[6])
		_, err = tx.Exec(query)
		// SQL文を実行
		stmt, err := tx.Prepare(query)
		if err != nil {
			logError(err, "Failed to prepare query")
			return
		}
		defer stmt.Close()

		_, err = stmt.Exec()
		if err != nil {
			logError(err, "Failed to execute query")
			return
		}

	}
	//トランザクションをコミット
	err = tx.Commit()
	if err != nil {
		fmt.Println(err)
		tx.Rollback()
		return
	}
	err = nil

}

自分で試したこと

基本的にchatGPTに質問を投げながら作成しているので、なにをやっているのかも部分部分しか分かっていません。
DBへのアクセスとテキストファイルをコード変換はうまくいっているようです。
情報少なくてすみません。

0

No Answers yet.

Your answer might help someone💌