質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Q&A

解決済

2回答

2581閲覧

【PostgreSQL】Shift-JISのCSVファイルをCOPYコマンドでインサートする方法が上手くいかないです

koburon

総合スコア30

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

0グッド

0クリップ

投稿2023/02/21 01:19

編集2023/02/21 01:21

前提

VBAでCSVファイルを出力するマクロを作っています。
CSVファイルはPostgreSQLの社員マスタにインポートできるように形式を調整して作成します。下記URLを参考にして作成しました。
【超簡単】ワンタッチでエクセルからCSV出力するVBAプログラム
PostgreSQLでCSVファイルをインポート/エクスポートする方法

該当のソースコード

社員マスタのテーブルです。文字数制限のため一部省略しますが、文字型は全てcharacterです。

t_社員マスタ

1CREATE TABLE public."t_社員マスタ" ( 2 "社員番号" character(8) NOT NULL, 3 "氏名" character(16), 4 "氏名カナ" character(24), 5 "所属コード" character(3), 6 "所属" character(30), 7 "支社コード" character(3), 8 "支社" character(20), 9 "役職名" character(30), 10); 11ALTER TABLE ONLY public."t_社員マスタ" 12 ADD CONSTRAINT "pk_t_社員マスタ" PRIMARY KEY ("社員番号");

全てのセル値を「""」で囲んでCSV出力するコードです。

VBA

1Public Sub writeCSV() 2 Dim ws As Worksheet 3 Dim maxrow As Long 4 Dim fileNo As Integer 5 Dim wrow As Long 6 Dim wcol As Long 7 Dim i As Long 8 Dim val As String 9 Dim out_line As String 10 Const stCol = 1 11 Const enCol = 144 12 Dim arrVal(enCol - stCol) As String 13 Set ws = Worksheets("Sheet1") 14 maxrow = ws.Cells(Rows.Count, 1).End(xlUp).Row 15 fileNo = FreeFile 16 17 ' ワークシートに出力している間の画面更新を停止 18 Application.ScreenUpdating = False 19 20 ' ---------------------------- 21 ' ファイルの出力処理 22 ' ---------------------------- 23 Dim myFileName, fileName, fileDateNm As String 24 25 ' ファイル名を作成する 26 fileDateNm = Replace(CStr(Date), "/", "") 27 fileName = "UpdateMaster_" & fileDateNm 28 ' ダイアログ表示 29 myFileName = Application.GetSaveAsFilename(InitialFileName:=fileName, FileFilter:="CSV ファイル (*.csv),*.csv") 30 ' キャンセルなら終了 31 If myFileName = "False" Then 32 Exit Sub 33 End If 34 35 ' 保存 36 Open myFileName For Output As #fileNo 37 For wrow = 3 To maxrow 38 i = 0 39 For wcol = stCol To enCol 40 ' 1データ取得 41 val = ws.Cells(wrow, wcol).Value 42 ' データをダブルクオートでくくり、配列へ格納 43 arrVal(i) = wrap_data(val) 44 i = i + 1 45 Next 46 ' カンマで連結 47 out_line = Join(arrVal, ",") 48 Print #fileNo, out_line 49 Next 50 Close #fileNo 51 52 MsgBox ("CSVファイルを「Shift_JIS」で出力しました。レコード部分のみ出力しています。") 53 54 ' 画面更新を元に戻す 55 Application.ScreenUpdating = True 56End Sub 57 58' 入力文字列をダブルクオートでくくる 59Private Function wrap_data(ByVal val As String) As String 60 wrap_data = """" & val & """" 61End Function

CSVファイルをインサートするCOPYコマンドです。

PostgreSQL

1COPY t_社員マスタ from '/public/csv/UpdateMaster_20230221.csv' ;

実現したいこと

社員マスタで主キー制約が機能しているか確認するため、社員番号が重複しているレコードをCOPYで実行してエラーが発生させるのが目的です。

発生している問題

CSVファイルは問題なく出力されますが、COPYコマンド実行時、以下の構文エラーが発生しました。

COPY t_社員マスタ from '/public/csv/UpdateMaster_20230221.csv' ERROR: 符号化方式"UTF8"で無効なバイトシーケンスです: 0x8d CONTEXT: t_社員マスタのCOPY。行番号 1

試したこと

CSVファイルをテキストエディタ(NewQX)で確認したところ文字化けは特に発生していません。encodingを指定すると正しく実行されると参考サイトに書かれていたので、修正して再度実行しましたが、以下のように構文エラーが発生しました。

COPY t_社員マスタ from '/public/csv/UpdateMaster_20230221.csv' with encoding 'sjis' csv ERROR: "encoding"またはその近辺で構文エラー LINE 1: ...from '/public/csv/UpdateMaster_20230221.csv' with encoding '...

レコード重複した場合のエラーメッセージがどういうものか分かっていないのですが、これは明らかにそれ以前の原因のエラーだとは思います。
どこかで表記ミスしているのか、アドバイスいただけると幸いです。
よろしくお願いいたします。

補足情報(FW/ツールのバージョンなど)

PC:Windows11
Excelのバージョン:Microsoft365 Excel
PostgreSQLのバージョン:9.0.1
PSqlEditのバージョン:5.2.3.9

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2023/02/21 01:21

UTF8でCSVを生成すれば良いのでは。
koburon

2023/02/21 01:49

>m.ts10806様 CSVをexcelの「名前を付けて保存」⇒「CSV UTF-8(コンマ区切り)」で保存し、この状態をCSVでCOPYしましたが、以下のようなエラーが発生しました。 ERROR: 値は型character(8)としては長すぎます CONTEXT: t_社員マスタ_マクロテストのCOPY。行番号 1。列 社員番号: "'11111','〇〇〇〇','..." 社員番号と氏名で区切りが出来ておらず長い値になってしまっているということでしょうか?
tatsu99

2023/02/21 01:50

9.0.1ではencodingはサポートされてないようですね。9.1.5ならサポートされています。 以下、https://www.postgresql.jp/document/ からの抜粋です。 9.0.1 名前 COPY -- ファイルとテーブルの間でデータをコピーする 概要 COPY table_name [ ( column [, ...] ) ] FROM { 'filename' | STDIN } [ [ WITH ] ( option [, ...] ) ] COPY { table_name [ ( column [, ...] ) ] | ( query ) } TO { 'filename' | STDOUT } [ [ WITH ] ( option [, ...] ) ] ここでoptionは以下のいずれかです。 FORMAT format_name OIDS [ boolean ] DELIMITER 'delimiter_character' NULL 'null_string' HEADER [ boolean ] QUOTE 'quote_character' ESCAPE 'escape_character' FORCE_QUOTE { ( column [, ...] ) | * } FORCE_NOT_NULL ( column [, ...] ) 9.1.5 名前 COPY -- ファイルとテーブルの間でデータをコピーする 概要 COPY table_name [ ( column [, ...] ) ] FROM { 'filename' | STDIN } [ [ WITH ] ( option [, ...] ) ] COPY { table_name [ ( column [, ...] ) ] | ( query ) } TO { 'filename' | STDOUT } [ [ WITH ] ( option [, ...] ) ] ここでoptionは以下のいずれかです。 FORMAT format_name OIDS [ boolean ] DELIMITER 'delimiter_character' NULL 'null_string' HEADER [ boolean ] QUOTE 'quote_character' ESCAPE 'escape_character' FORCE_QUOTE { ( column [, ...] ) | * } FORCE_NOT_NULL ( column [, ...] ) | ENCODING 'encoding_name' よって、CSVファイルをUTF8形式で作成するしかないかと思います。 (postgresqlのバージョンを変えられるなら話は別ですが)
koburon

2023/02/21 02:12

>tatsu99様 詳しいオプションを記入いただきありがとうございます。 UTF8形式で保存して、「WITH CSV DELIMITER ',';」を指定したところ、 -------------------------------------------------------------------------------- COPY t_社員マスタ_マクロテスト from '/public/csv/UpdateMaster_20230221.csv'WITH CSV DELIMITER ',' ERROR: 重複キーが一意性制約"pk_t_社員マスタ_マクロテスト"に違反しています DETAIL: キー ("社員番号")=(11111 ) はすでに存在します CONTEXT: t_社員マスタ_マクロテストのCOPY。行番号 2: "11111,..." -------------------------------------------------------------------------------- こちらで自己解決とします。 バージョンを変えるのは現時点では厳しいので、 仰る通り、Excelの段階でUTF8でCSVを作成しようと思います。
guest

回答2

0

既に締め切られていますが
Shift-JISのCSVファイルをCOPYコマンドで取り扱う方法です。
案1:
PSqlEditのバージョンのバージョンを下げる。
PSqlEditのバージョン4からUNICODE対応になってます。
従って、バージョン3を利用すれば、Shift-JISのCSVファイルを扱うことが可能です。
(バージョン3ではUTF8のCSVファイルを扱うことはできません)
下記の
http://www.hi-ho.ne.jp/a_ogawa/psqledit/index.htm

Version 3.3.1.0 psqledit_3310.zip(378kb)
が利用可能です。
PSqlEditは、解凍するだけで使用可能になるので、複数のバージョンが共存可能です。

案2:
(PostgreSQL、PSqlEditのバージョンはそのままでの案)

PsqlEditの代わりにPostgresqlに標準で提供されているpsqlコマンドを使う。
コマンドプロンプトを表示して
①起動例
psql -h localhost -U postgres -d postgres
②パスワード入力
クライアント側の文字コードをSJISに設定
③set client_encoding to 'sjis';
を行うと、以降、Shift-JISのCSVファイルを扱うことが可能になります。

上記の③はコマンドプロンプトを起動する都度、行う必要があります。
(恒久的にクライアント側の文字コードをSJISにしたい場合は、
Postgresqlのpostgresql.confファイルにclient_encodingを指定する箇所があるのでそれを'sjis'に変えて
Postgresqlを再起動すれば、③の設定は不要になります)

投稿2023/02/25 02:40

編集2023/02/25 02:44
tatsu99

総合スコア5438

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

koburon

2023/02/27 07:59

回答ありがとうございます。 締切ってしまい申し訳ありません。 psqlコマンドを使う方法もあるのですね。 参考にさせていただきます。
guest

0

自己解決

バージョン:9.0.1で使用できるオプションをコメントでいただきました。
UTF8形式で保存して、「WITH CSV DELIMITER ',';」を指定したところ、

COPY t_社員マスタ from '/public/csv/UpdateMaster_20230221.csv'WITH CSV DELIMITER ',' ERROR: 重複キーが一意性制約"pk_t_社員マスタ"に違反しています DETAIL: キー ("社員番号")=(11111 ) はすでに存在します CONTEXT: t_社員マスタのCOPY。行番号 1: "11111,..."

主キー制約が機能していることが確認できたので、こちらで自己解決とします。

投稿2023/02/21 02:16

koburon

総合スコア30

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問