2022年08月14日 PostgreSQL-14.4 Windows11Pro npgsql.3.1.10 and Tips [長年日記]
_ pg_env.batの修正
PATHに「"」が含まれていると正しく動作しなかったので、「"」を削除する。
REM @SET PATH="C:\Users\USER\Desktop\PostgreSQL\14\bin";%PATH% @SET PATH=C:\Users\USER\Desktop\PostgreSQL\14\bin;%PATH%
_ エンコーディングの設定
@SET PGCLIENTENCODING=UTF8
_ DB作成(例)
> createdb.exe -E UTF8 testdb
_ テーブル作成(例)(psql.exe)
psql.exe -U postgres testdb testdb=# create table tb_sample1 ( testdb=# id integer primary key, testdb=# name varchar(50), testdb=# job varchar(50) testdb=# };
_ psql.exe利用例
出力先をoutput.csvに設定、文字揃えをオフにし、区切り文字をタブに設定、rowのみ出力、tb_sample1テーブルの全てを出力して、出力先を元に戻す。
testdb=# \o output.csv testdb=# \a testdb=# \f '\t' testdb=# \t on testdb=# select * from tb_sample1; testdb=# \o
-Aで文字揃えをオフに、-Fで区切り文字を「カンマ」に指定。
> psql -d testdb -U postgres -c "select * from tb_sample1;" -A -F ',' > output.csv
-Aで文字揃えをオフに、-Fで区切り文字を「タブ」に指定(Powershell限定)。
> psql -d testdb -U postgres -c "select * from tb_sample1;" -A -F "`t" > output.csv
- タブ区切
- 引用符(QUOTE)で囲む
- NULL文字は空文字化
- カラム名を表示
COPY tb_sample1 TO 'c:\temp\output.csv' WITH CSV DELIMITER E'\t' FORCE QUOTE * NULL AS '' HEADER;
_ npgsql.3.1.10.nupkg
pg_hba.confの認証methodを「trust」または「password」に設定する。
本来は、もっと新しいnpgsqlを使うべきだと思われるが、dllの依存関係をどうしても解決できなかった。 結局、このバージョン(3.1.10)と認証method(trust or password)でしか接続できなかった...
_ C#によるPostgreSQLアクセス例
// // Compile: c:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe /r:npgsql.dll npgsqltest.cs // using System; using System.IO; using System.Data; using Npgsql; public class Program{ static void Main(string[] args){ var connString = @"Server=127.0.0.1;Port=5432;UserId=postgres;Password=パスワード;Database=testdb"; var conn = new NpgsqlConnection(connString); conn.Open(); NpgsqlTransaction tran = conn.BeginTransaction(); var cmd = new NpgsqlCommand(@"delete from tb_sample1", conn); cmd.ExecuteNonQuery(); tran.Commit(); tran = conn.BeginTransaction(); cmd = new NpgsqlCommand(@"insert into tb_sample1 (id, name, job) values (:id, :name, :job)", conn); cmd.Parameters.AddWithValue("id", 1); cmd.Parameters.AddWithValue("name", "山田 太郎"); cmd.Parameters.AddWithValue("job", "会社員"); cmd.ExecuteNonQuery(); tran.Commit(); tran = conn.BeginTransaction(); cmd.Parameters.Remove("id"); cmd.Parameters.Remove("name"); cmd.Parameters.Remove("job"); cmd.Parameters.AddWithValue("id", 2); cmd.Parameters.AddWithValue("name", "辻󠄀(一点しんにょうつじ) IVS"); cmd.Parameters.AddWithValue("job", "会社員"); cmd.ExecuteNonQuery(); tran.Commit(); tran = conn.BeginTransaction(); cmd.Parameters.Remove("id"); cmd.Parameters.Remove("name"); cmd.Parameters.Remove("job"); cmd.Parameters.AddWithValue("id", 3); cmd.Parameters.AddWithValue("name", "𠮷(土よし) サロゲート"); cmd.Parameters.AddWithValue("job", "会社員"); cmd.ExecuteNonQuery(); tran.Commit(); tran = conn.BeginTransaction(); cmd.Parameters.Remove("id"); cmd.Parameters.Remove("name"); cmd.Parameters.Remove("job"); cmd.Parameters.AddWithValue("id", 4); cmd.Parameters.AddWithValue("name", "(\uE000) 外字"); cmd.Parameters.AddWithValue("job", "会社員"); cmd.ExecuteNonQuery(); tran.Commit(); // // わざと重複キーでインサートして、どんなエラーメッセージが出るか観察してみる... // tran = conn.BeginTransaction(); cmd.Parameters.Remove("id"); cmd.Parameters.Remove("name"); cmd.Parameters.Remove("job"); cmd.Parameters.AddWithValue("id", 4); cmd.Parameters.AddWithValue("name", "(\uE000) 外字"); cmd.Parameters.AddWithValue("job", "会社員"); try{ cmd.ExecuteNonQuery(); tran.Commit(); }catch (Exception e){ Concole.WriteLine(e.Message); tran.Rollback(); } cmd = new NpgsqlCommand(@"select * from tb_sample1", conn); var dataReader = cmd.ExecuteReader(); while (dataReader.Read()) { Console.WriteLine("{0},{1},{2}", dataReader["id"], dataReader["name"], dataReader["job"]); } dataReader.Close(); tran = conn.BeginTransaction(); cmd = new NpgsqlCommand(@"update tb_sample1 set job = :job where id = :id", conn); cmd.Parameters.AddWithValue("id", 1); cmd.Parameters.AddWithValue("job", "無職"); cmd.ExecuteNonQuery(); cmd.Parameters.Remove("id"); cmd.Parameters.Remove("job"); cmd.Parameters.AddWithValue("id", 2); cmd.Parameters.AddWithValue("job", "無職"); cmd.ExecuteNonQuery(); cmd.Parameters.Remove("id"); cmd.Parameters.Remove("job"); cmd.Parameters.AddWithValue("id", 3); cmd.Parameters.AddWithValue("job", "無職"); cmd.ExecuteNonQuery(); cmd.Parameters.Remove("id"); cmd.Parameters.Remove("job"); cmd.Parameters.AddWithValue("id", 4); cmd.Parameters.AddWithValue("job", "無職"); cmd.ExecuteNonQuery(); cmd = new NpgsqlCommand(@"select * from tb_sample1", conn); dataReader = cmd.ExecuteReader(); while (dataReader.Read()) { Console.WriteLine("{0},{1},{2}", dataReader["id"], dataReader["name"], dataReader["job"]); } dataReader.Close(); tran.Rollback(); cmd = new NpgsqlCommand(@"select * from tb_sample1", conn); dataReader = cmd.ExecuteReader(); while (dataReader.Read()) { Console.WriteLine("{0},{1},{2}", dataReader["id"], dataReader["name"], dataReader["job"]); } dataReader.Close(); conn.Close(); } }
_ エラーメッセージ
- 二重キー
- "0" 個の引数を指定して "ExecuteNonQuery" を呼び出し中に例外が発生しました: "23505: 重複したキー値は一意性制約"tb_sample1_pkey"違反となります"
- デッドロック
- "0" 個の引数を指定して "ExecuteNonQuery" を呼び出し中に例外が発生しました: "40P01: デッドロックを検出しました"
_ PowershellによるPostgreSQLアクセス例
[void][reflection.assembly]::LoadFrom("C:\Users\USER\Desktop\PostgreSQL\Npgsql.dll") $ConnectionString = "Host=127.0.0.1;Username=postgres;Password=パスワード;Database=testdb" $conn = New-Object NpgSql.NpgsqlConnection($ConnectionString) $conn.Open() $tran = $conn.BeginTransaction() $command = New-Object NpgSql.NpgSqlCommand("delete from tb_sample1", $conn) $effected_row_count = $command.ExecuteNonQuery(); $tran.Commit() $tran = $conn.BeginTransaction() $command = New-Object NpgSql.NpgSqlCommand("insert into tb_sample1 (id, name, job) values (:id, :name, :job)", $conn) [void]$command.Parameters.AddWithValue("id", 1) [void]$command.Parameters.AddWithValue("name", "山田 太郎") [void]$command.Parameters.AddWithValue("job", "会社員") $effected_row_count = $command.ExecuteNonQuery(); $tran.Commit() $tran = $conn.BeginTransaction() [void]$command.Parameters.Remove("id") [void]$command.Parameters.Remove("name") [void]$command.Parameters.Remove("job") [void]$command.Parameters.AddWithValue("id", 2) [void]$command.Parameters.AddWithValue("name", "辻󠄀(一点しんにょうつじ) IVS") [void]$command.Parameters.AddWithValue("job", "会社員") $effected_row_count = $command.ExecuteNonQuery(); $tran.Commit() $tran = $conn.BeginTransaction() [void]$command.Parameters.Remove("id") [void]$command.Parameters.Remove("name") [void]$command.Parameters.Remove("job") [void]$command.Parameters.AddWithValue("id", 3) [void]$command.Parameters.AddWithValue("name", "𠮷(土よし) サロゲート") [void]$command.Parameters.AddWithValue("job", "会社員") $effected_row_count = $command.ExecuteNonQuery(); $tran.Commit() $tran = $conn.BeginTransaction() [void]$command.Parameters.Remove("id") [void]$command.Parameters.Remove("name") [void]$command.Parameters.Remove("job") [void]$command.Parameters.AddWithValue("id", 4) [void]$command.Parameters.AddWithValue("name", "(\uE000) 外字") [void]$command.Parameters.AddWithValue("job", "会社員") $effected_row_count = $command.ExecuteNonQuery(); $tran.Commit() # # わざと重複キーでインサートして、どんなエラーメッセージが出るか観察してみる... # $tran = $conn.BeginTransaction() [void]$command.Parameters.Remove("id") [void]$command.Parameters.Remove("name") [void]$command.Parameters.Remove("job") [void]$command.Parameters.AddWithValue("id", 4) [void]$command.Parameters.AddWithValue("name", "(\uE000) 外字") [void]$command.Parameters.AddWithValue("job", "会社員") try{ $effected_row_count = $command.ExecuteNonQuery(); $tran.Commit() }catch{ write-output $_.Exception.Message # "0" 個の引数を指定して "ExecuteNonQuery" を呼び出し中に例外が発生しました: "23505: 重複したキー値は一意性制約"tb_sample1_pkey"違反となります" $tran.Rollback() } $command = New-Object NpgSql.NpgSqlCommand("select * from tb_sample1 order by id", $conn) $datareader = $command.ExecuteReader() while ($datareader.Read()){ write-output($datareader["id"].tostring() + "," + $datareader["name"] + "," + $datareader["job"]) } $datareader.Close() $tran = $conn.BeginTransaction() $command = New-Object NpgSql.NpgSqlCommand("update tb_sample1 set job = :job where id = :id", $conn) [void]$command.Parameters.AddWithValue("id", 1) [void]$command.Parameters.AddWithValue("job", "無職") $effected_row_count = $command.ExecuteNonQuery(); [void]$command.Parameters.Remove("id") [void]$command.Parameters.Remove("job") [void]$command.Parameters.AddWithValue("id", 2) [void]$command.Parameters.AddWithValue("job", "無職") $effected_row_count = $command.ExecuteNonQuery(); [void]$command.Parameters.Remove("id") [void]$command.Parameters.Remove("job") [void]$command.Parameters.AddWithValue("id", 3) [void]$command.Parameters.AddWithValue("job", "無職") $effected_row_count = $command.ExecuteNonQuery(); [void]$command.Parameters.Remove("id") [void]$command.Parameters.Remove("job") [void]$command.Parameters.AddWithValue("id", 4) [void]$command.Parameters.AddWithValue("job", "無職") $effected_row_count = $command.ExecuteNonQuery(); $command = New-Object NpgSql.NpgSqlCommand("select * from tb_sample1 order by id", $conn) $datareader = $command.ExecuteReader() while ($datareader.Read()){ write-output($datareader["id"].tostring() + "," + $datareader["name"] + "," + $datareader["job"]) } $datareader.Close() $tran.Rollback() $command = New-Object NpgSql.NpgSqlCommand("select * from tb_sample1 order by id", $conn) $datareader = $command.ExecuteReader() while ($datareader.Read()){ write-output($datareader["id"].tostring() + "," + $datareader["name"] + "," + $datareader["job"]) } $datareader.Close() $conn.Close()
_ PowershellでUTF8を使う設定
# 標準出力(パイプ)への出力時のエンコーディングをバックアップ $oe = $OutputEncoding # 標準出力(画面)への出力時のエンコーディングをバックアップ $scoe = [System.Console]::OutputEncoding # 標準出力(パイプ)、標準出力(画面)への出力時のエンコーディングをUTF-8BOM無しに設定 $OutputEncoding = [System.Console]::OutputEncoding = New-Object System.Text.UTF8Encoding $false # 標準出力(パイプ)、標準出力(画面)への出力時のエンコーディングをUTF-16、LE、BOM有りに設定 #$OutputEncoding = [System.Console]::OutputEncoding = New-Object System.Text.UnicodeEncoding $false,$true # 標準出力(パイプ)、標準出力(画面)への出力時のエンコーディングをShift-JISに設定 #$OutputEncoding = [System.Console]::OutputEncoding = [Text.Encoding]::GetEncoding("Shift-JIS") # ... UTF-8BOMなしデータを処理 ... Hogge.exe | fuga.exe | foo.exe | bar.exe ... # 標準出力(パイプ)への出力時のエンコーディングを元に戻す $OutputEncoding = $oe # 標準出力(画面)への出力時のエンコーディングを元に戻す [System.Console]::OutputEncoding = $scoe
_ dotnet and npgsql.6.0.6
結局、pg_hba.confの認証methodを「md5」または「scram-sha-256」にする為にはdotnet6環境でのビルドが必要だった。
ソースディレクトリの準備
mkdir npgsqltest cd npgsqltest dotnet new console
npgsql.6.0.6のパッケージ追加(インターネット接続可能な場合)
dotnet add package npgsql
npgsql.6.0.6のパッケージ追加(インターネット接続不可能な場合)
mkdir packages copy anywhere\npgsql.6.0.6.nupkg .\packages\ copy anywhere\ystem.runtime.compilerservices.unsafe.nupkg .\packages\ dotnet add package npgsql -s .\packages
ソースの編集
notepad Program.cs
ビルド
dotnet build
テスト実行
dotnet run
公開(デバッグ)
dotnet publish bin\Debug\net6.0\publish\npgsqltest.exe
公開(本番)
dotnet publish -c Release bin\Release\net6.0\publish\npgsqltest.exe
公開(本番、全部入り)
dotnet publish -c Release --self-contained true -r win-x64 bin\Release\net6.0\win-x64\publish\npgsqltest.exe
公開(本番、全部入り、単一exe)
dotnet publish -c Release --self-contained -p:PublicSingleFile=true -p:PublishTrimmed=true -r win-x64 bin\Release\net6.0\win-x64\publish\npgsqltest.exe