C# PostgreSQL 部分一致検索するってのをやってみました。
C#のFormにCrystalReportsViewerとテキストボックスとコマンドボタンを設置して
phoneticカラムをLikeで部分一致検索するってのをやってみました。
.rptとかはできているという前提で...省略...
最初は、SelectCommandのSQL文字列にLike '%:phonetic%' とかやってみたけど動かず。。。
しばし悩んだ結果、Parameters.AddWithValueに"%"を埋め込んでやることで解決。
ただし、SQLインジェクションとか対応するにはもっと適切な方法があるんだと思う。
private void but_name_search_Click(object sender, EventArgs e) { if (txt_phonetic.Text == null) { da.SelectCommand = new NpgsqlCommand ( "select id, name, phonetic from users_rep_view order by id", m_conn ); } else { da.SelectCommand = new NpgsqlCommand ( "select id, name, phonetic from users_rep_view where phonetic Like :phonetic order by id", m_conn ); } } if (txt_phonetic.Text == null) { da.SelectCommand.Parameters.Add(new NpgsqlParameter("phonetic", NpgsqlTypes.NpgsqlDbType.Char, 0, "phonetic", ParameterDirection.Input, false, 0, 0, DataRowVersion.Current, DBNull.Value)); } else { da.SelectCommand.Parameters.AddWithValue("phonetic", "%" + txt_phonetic.Text + "%"); } if (ds.Tables["users_rep_view"] != null) ds.Tables["users_rep_view"].Clear(); da.Fill(ds, "users_rep_view"); Cr_users_rep myReport = new Cr_users_rep(); myReport.SetDataSource(ds); Crv_users_rep.ReportSource = myReport; }
PostgreSQLでストリーミング・レプリケーションの構築
2台のサーバーはFreeBSD 9.0-RELEASE + PostgreSQL 9.1.3
【マスターサーバー】 = 192.168.0.30
【スレーブサーバー】 = 192.168.0.50
とりあえず、マスタサーバーのディスク故障に備えたリアルタイム・バックアップの用途
【マスターサーバー】
マスターサーバーのPostgreSQLを停止 # /usr/local/etc/rc.d/postgresql stop 次に、各設定ファイルの編集 [postgresql.conf] listen_addresses = '*' port = 5432 wal_level = hot_standby archive_command = 'scp %p /usr/local/pgsql/data/pg_archive/%f' max_wal_senders = 2 hot_standby = off
[pg_hba.conf] host replication all 192.168.0.50/24 trust
【スレーブサーバー】
スレーブサーバーのPostgreSQLを停止 # /usr/local/etc/rc.d/postgresql stop 次に、各設定ファイルの編集 [postgresql.conf] listen_addresses = '*' port = 5432 wal_level = hot_standby archive_mode = on archive_command = 'scp %p /usr/local/pgsql/data/pg_archive/%f' max_wal_senders = 2 wal_keep_segments = 8 hot_standby = on
[pg_hba.conf] host replication all 192.168.0.30/24 trust
[recovery.conf] restore_command = 'scp /usr/local/pgsql/data/archive_log/%f %p' standby_mode = 'on' primary_conninfo = 'host=192.168.0.30' trigger_file = '/tmp/trigger'
【バックアップとデータ転送】
マスターサーバーのPostgreSQLを起動 # /usr/local/etc/rc.d/postgresql start
マスターサーバーのdataディレクトリのバックアップを取ります。 # cd /usr/local/pgsql # tar zcvf data.tar.gz data
マスターサーバーのdataディレクトリのバックアップを スレーブサーバーのpgsqlディレクトリへ転送する。 # scp data.tar.gz 192.168.0.50:/usr/local/pgsql/
スレーブサーバーのdataディレクトリで.confファイルのバックアップをとっておきます。 # cd /usr/local/pgsql # mkdir ./conf_backup # cp -a data/*.conf ./conf_backup/
スレーブサーバーにマスターデータから転送したdataディレクトリのバックアップを 展開します。 # tar zxvf data.tar.gz
スレーブサーバーに先ほどバックアップした.confファイルを戻します。 # cp -a ~/conf_backup/*.conf data/
スレーブサーバーにマスターデータから転送したdataディレクトリ内に プロセスIDが残っているとエラーが出るので、予め削除しておきます。 # rm -f data/postmaster.pid
スレーブサーバーのPostgreSQLを起動 # /usr/local/etc/rc.d/postgresql start
【結果確認】
SELECT * FROM pg_stat_replication;
# 24.4.19 加筆しました。
Npgsql ExecuteScalarメソッドを使用してみました
入力値をチェックする方法にもいろいろな方法があると思いますが
今回は、データグリッドビューに値を入力する際にマスタテーブルに
登録されたIDを参照して、マスタにIDがあればエラーメッセージを表示し
入力をキャンセル、無ければ登録するという仕組みのもの。
あとから、「マスタに登録したIDが間違っていた!」なんていう場合は
とりあえず、マスタからIDを削除してから、入力しなおすことにすれば
いいかっていう、かなり柔軟な設計(w。
private void dataGridView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e) { DataGridView dgv = (DataGridView)sender; if (!dgv.IsCurrentCellDirty) return; if (dgv.Columns[e.ColumnIndex].Name == "id") { try { da.SelectCommand = new NpgsqlCommand ( "select" + " id" + " from" + " duplicate_view" + " where id=:id", m_conn ); da.SelectCommand.Parameters.AddWithValue("id", e.FormattedValue.ToString()); da.Fill(dupds, "duplicate_view"); m_conn.Open(); object dup_id; dup_id = da.SelectCommand.ExecuteScalar(); if (dup_id != null) { MessageBox.Show("その「id」= " + dup_id.ToString() + "は、リタイヤ済みです!" , "リタイヤ済み", MessageBoxButtons.OK, MessageBoxIcon.Error); //キャンセルする e.Cancel = true; //入力した値をキャンセルして元に戻す dgv.CancelEdit(); } } finally { m_conn.Close(); } } }
もっと、いい方法があれば教えてください。
同時実行違反にドハマりする
Formにデータグリッドビュー配置して
PostgreSQL DBのデータを表示・追加・更新・削除を行う
アプリケーションを作成する過程での更新処理で
「同時実行違反:UpdateCommand によって、処理予定の 1 レコードのうち 0 件が処理されました。」
今日は、この「わかりやすいんだかわかりにくいんだか」というエラーにどハマリました。
「SELECTでの接続とUPDATEでの接続が同時実行違反しているのか?」とか考えて
データアダプタを別にしてみたり、データセットも別に作ってみたりしてみても変わらず...
打つ手が無くなったところで、もう一人の俺が「まさかPKの値が無いんじゃないか?」と囁く。。。
とりあえずデータグリッドビューで非表示にしているPKを表示してみると
?ん
PKのフィールドに値が表示されていないことに気付く・・・
まったく、もう...
文字列関数 CONCAT() を使ってみる
SQL中で文字列を連結する際に
現在は'||'を使って
SELECT (first_name || ' ' || last_name) full_name FROM user;
のように使っているのですが
もし、'first_name' か 'last_name'のどちらかがNULLだと
連結すると結果はがNULLになってしまうということで
(SELECT coalesce(first_name, '') || ' ' || coalesce(last_name, '') full_name FROM user;とすればいいようですが...)
文字列関数 concat()に置き換えてみることにしました。
SELECT concat(first_name , ' ' , last_name) full_name FROM user;
うまく置き換え出来るようです。(postgreSQL 9.1以降で使えるようです)