../../image/benilogo.gifDelphi7 について


Windows 環境 Delphi 7 から PostgreSQL の データー更新について。

 単純に TDBNavigatir でのデーター修正が出来るのか? の実験です。

動作画面
image/test_update01_a.gif
  • 単純に TDBEDit と TDBNavigator
  • データーベースに接続する。

実行画面
image/update_error01.gif
    



    ナビゲーターの修正ボタンを押すと左図のエラーとなる。


    修正出来ないのか?  

    と、思いながら また別のテーブルを修正すると問題なく Update 出来る。
    いろいろ変えてみたところ どうやら 修正できるものと
    出来ないものがあるようなのです。

 
    




修正出来ないのならば 追加( Insert ) はどうなのか?

SQLエクスプローラー
  • 0000-0005 と 0000-0006 SQLエクスプローラーより追加( INSERT )する。
  • 追加出来ました。

ここでの修正( UPDATE )の結果は

と、こんな状況になりました。
どこが違うのだろうか?
beniya=# select * from bhnmst where bhn_code > '0000-0005';
  bhn_code  | bhn_name |  bhn_yomi  --- 中略 ---|         bhn_koshinbi          |         bhn_sakuseibi
------------+----------+------------            +-----------+-------------------------------
 0000-0006  | fffff    | エフgggg               | 2005-01-17 00:00:00+09        | 2005-01-17 00:00:00+09
 0000-0007  | 次は七   | つぎはなな              | 2005-01-17 19:35:15.392055+09 | 2005-01-17 19:35:15.392055+09
(2 rows)


UPDATE が有効なデータと無効になるデーター( レコード ) の違いは何なのか?

これを確かめるにはどうすればいいか? 簡単なテーブルを作り、挿入と修正をやってみると違いがはっきりするのではないだろうか。
という事で、
  1. char だけの レコード で実験
    beniya=# create table a_test1 ( a1 char, a2 char );
    CREATE
    beniya=# insert into a_test1 values( 'a','d' );
    INSERT 22278 1
    beniya=# insert into a_test1 values( 'b','c' );
    INSERT 22279 1
    beniya=# select * from a_test1;
     a1 | a2
    ----+----
     a  | d
     b  | c
    (2 rows)
    
    
    image/a_test1_a.gif a1 は 'a' -> 'e' に Update 出来ている。
    これは何の問題もなく、挿入・修正が可能です。

  2. それでは、次に timestamp型のフィールドを追加してみる。
    beniya=# create table a_test2 ( a1 char(20), a2 char( 10 ), 
    beniya(# a3 timestamp not null);
    CREATE
    beniya=# select \d a_test2;
                    Table "a_test2"
     Column |           Type           | Modifiers
    --------+--------------------------+-----------
     a1     | character(20)            |
     a2     | character(10)            |
     a3     | timestamp with time zone | not null
    
    beniya-# insert into a_test2 values( 'abcde',fghij','now');
    ERROR:  parser: parse error at or near "values"
    beniya=# insert into a_test2 values( 'abcde','fghij','now');
    INSERT 22282 1
    beniya=# insert into a_test2 values( 'hijk','lmnop','now');
    INSERT 22283 1
    b
    
    image/a_test2_a.gif
    image/update_error01.gif
    • 同じError になる。
    • timestamp型 だとエラーになる。
      NOT NULL だからなのか? 
    それでは、このテーブルに追加出来るかどうかを試してみる。
    image/a_test2_c.gif
    • 追加出来る。
    • 追加したものは修正も出来る。 (もともとのデーターはやはり変更出来ない。)
    • a3 Field の 日付は 時間が消えている。
      これは 2005/01/18 00:00:00 として入力したもの
    • 2003/10/10 は日付だけ  これでも登録は出来た。
    このときの psql でのデーターはどうなっているのだろえか?
     select * from a_test2;
              a1          |     a2     |              a3
    ----------------------+------------+-------------------------------
     abcde                | fghij      | 2005-01-18 11:36:44.821445+09
     hijk                 | lmnop      | 2005-01-18 11:37:05.06198+09
     ggg                  |            | 2005-01-18 00:00:00+09
                          |            | 2003-10-10 00:00:00+09
    (4 rows)
    
    
    • 見た目の違いは timestamp の時間の部分だけ
      これが関係しているのだろうか?

    どうやら timestamp型に問題がありそう。  これは NOT NULL でなければどうだろう?

  3. それじゃあ NOT NULL でない NULL を許可するテーブルを作成してみる。
    beniya=# create table a_test3( a1 char(20),a2 char(10) primary key Not NULL,
    beniya(# a3 timestamp);
    NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index 'a_test3_pkey' for table 'a_test3'
    CREATE
    beniya=# select \d a_test3;
                    Table "a_test3"
     Column |           Type           | Modifiers
    --------+--------------------------+-----------
     a1     | character(20)            |
     a2     | character(10)            | not null
     a3     | timestamp with time zone |
    Primary key: a_test3_pkey
    
    
    • a2 は primary key

    image/a_test3_a.gif
    • 追加可能
    • 追加したものの修正可能
    • 追加したものは a2 Key も変更可能
    • timestamp に linux で 値が入っているものは更新出来ない。

なるほど、結果はそういうことのようです。
しかし、 Delphi から送られる SQL はどうなっているのだろうか? これも 確認してみましょう。

SQLモニター で見る
38 SQL Data In: PostgreSQL - Param = 1, Name = a1, Type = fldZSTRING, Precision = 20, Scale = 0, Data = ffffffd
39 SQL Data In: PostgreSQL - Param = 2, Name = a1, Type = fldZSTRING, Precision = 20, Scale = 0, Data = ffff
40 SQL Data In: PostgreSQL - Param = 3, Name = a2, Type = fldZSTRING, Precision = 10, Scale = 0, Data = c
41 SQL Data In: PostgreSQL - Param = 4, Name = a3, Type = fldTIMESTAMP, Precision = 19, Scale = 0,
                                               Data = 1/18/2005 14:30:44:0
42 SQL Execute: PostgreSQL - UPDATE "a_test3" SET "a1"=? WHERE "a1"=? AND "a2"=? AND "a3"=?
43 SQL Vendor: ODBC - SQLAllocStmt

----------- CUT -----------

106 SQL Data Out: PostgreSQL - Column = 2, Name = a2, Type = fldZSTRING, Precision = 10, Scale = 0, Data = dff
107 SQL Data Out: PostgreSQL - Column = 3, Name = a3, Type = fldTIMESTAMP, Precision = 19, Scale = 0, Data = NULL
108 SQL Prepare: PostgreSQL - UPDATE "a_test3" SET "a2"=? WHERE "a1"=? AND "a2"=? AND "a3" IS NULL 
109 SQL Data In: PostgreSQL - Param = 1, Name = a2, Type = fldZSTRING, Precision = 10, Scale = 0, Data = dffg
110 SQL Data In: PostgreSQL - Param = 2, Name = a1, Type = fldZSTRING, Precision = 20, Scale = 0, Data = bbbb
111 SQL Data In: PostgreSQL - Param = 3, Name = a2, Type = fldZSTRING, Precision = 10, Scale = 0, Data = dff
112 SQL Stmt: PostgreSQL - Close
113 SQL Vendor: ODBC - SQLFreeStmt
114 SQL Execute: PostgreSQL - UPDATE "a_test3" SET "a2"=? WHERE "a1"=? AND "a2"=? AND "a3" IS NULL 
115 SQL Vendor: ODBC - SQLAllocStmt


原因
つまり、更新するためには もともとのデーターを検索しなくてはならないわけですが、検索条件がすべての項目となるために
日付( TimeStamp ) も同じものを探そうとする。 ところが Delphi では ・・・ と言うか BDE かな? は 日付/時間 それも 時、分、秒
までしか管理していないのだ!!
PostgreSQL の timestamp は 
timestamp形式 変換されて切捨てが生じる
2005-01-18 11:36:44.821445+09 =======> 1/18/2005 11:36:44:0 .821445+09

ところが Delphi / BDE は 変換されて切り捨てられたデーターで もとのレコードを検索してしまうから、そんなレコードは無い!!と怒られてしまう。

はぁ〜 しかしこの場合 a3 Table1.FiledDefs[2] を ftTimeStamp に変えたらいけそうな気もするのだが・・・・
やってみたけど ダメ でした。 Valiant とか いろいろ変えてみてもダメ。
UPDATE "a_test3" SET "a1"=? WHERE "a1"=? AND "a2"=? AND "a3"=? このときの  a3 = ? が 1/18/2005 14:30:44:0
であるから こりゃあ 当然ながら 存在しませんわなぁ。

結論
 





















目次に戻る

2005/01/18 start ********* Last Update 2006/06/03 15:24 JST

(C) Y.Kondou,2005,2006 All Rights, Reserved.
その他、お気づきの点がありましたら連絡先はこちらから