[pgsql-jp: 33235] Re: PostgrsSQL7.4.2 ecpgの prepare,execute でnull 値が渡せない

aya shigeto_aya_za @ mail.toyota.co.jp
2004年 6月 15日 (火) 10:35:05 JST


返信ありがとうございます。綾です。

さっそくNULLIFの使い方を調べ、動かしてみたところうまく動きました。
NULLIF2つの引数が等しい場合にNULL値を生成してくれる関数とのこと、

NULL値をinsertするしないに関わらず、プログラムは全て
同じにしようと思っているので、
全てのvalues句の?をNULLIF(?,?)に一括置き換えて、、、
(null値許さない列を調べるのが大変だし、間違えそうだし、、、
プログラム変更に弱そうだし、、、)

execute文はNULL値以外を入れる場合、
異なる値を定義しなければいけないのですが、
timestamp型やinterval型はホスト変数で
入れているので、型としておかしいものを入れておき、、、

と思ったのですが、偶然同じがあったらNULLになるとまずい、
プログラムバグがnull insertで正常に動くという
場合が想定されないこともない、、、
万が一発生すると調査が大変そうなので、、、
関数作って、明らかに異なる値を生成する
仕組みを作るようにしようと思います。

ありがとうございます。7.4.2に進める突破口が開けました。

こんな問題で新バージョンに進めなくなる恐ろしさが
PostgreSQLにあるのかと、、今回痛感しました。
サポートなしというのは非常に怖いですね、、、

まだ、7.4.2はこの問題で止まっていて、他の検証が
なされていない状態です、まだ、何かあるかも
しれないと思うと憂鬱です。

また、対応方法は教えていただいたとおりなのですが、
上記修正を全ソースに加えるのにどれだけの工数が
かかるか、、、
ここでは明かせませんが、テストも含めると、、、

今回、岡野さんからの返信が無かったら、
暗礁に乗り上げるところでした、
座礁状態から抜けるのはかなり大変なのですが、
とにかく進めるようになりました。

ありがとうございました。


Katsuhiko Okano wrote:

> 岡野と申します。
> 
> aya wrote:
> 
>>実際のアプリケーションではテーブル名が
>>動的にかわるためどうしても動的SQLで
>>null値をinsertする必要があります。
> 
> 
> 「動的SQLでnull値をinsertする」
> の意味をうまく理解できていなかったらすみません。
> 
> 方法は2つあると思います。
> 1)SQL文を2つ用意して、C言語のif文でどちらかを実行する
> 2)SQL文にCASE式のNULLIF形式を書いて、NULLか、指定した値かのどちらかを使う
> #strcpy()で作る動的SQLを毎回書き換えるとか、INSERT文のVALUES句に何も書かない
> #とかも考えましたが、綾さんのケースだと使えそうに無いですね(^^;)
> 
> 1つのSQL文で行う場合、ホスト変数のNULLとデータベースのNULLは違うため、
> oracleのNVL関数のような変換が必要だと思います。
> 
> 
> なぜPostgreSQL7.3.3で動いて、PostgreSQL7.4.2で動かないのかは分かりません(--;)
> 
> 
> 2)の方法で以下のコードを使ってNULLを入れることができたので付けておきます。
> (綾さんのソースの39行目にある内容でtmptableテーブルを作成してから実行しました)
> 長くなってすみません。
> 
> #include <stdio.h>
> #include <sqlca.h>
> 
> void error_exit(void);
> 
> int main( int argc, char* argv[] ){
> 
>     /* ホスト変数 */
>     exec sql begin declare section;
>         int indata;
>         char sqlstring[1000];
>     exec sql end declare section;
> 
>     /* エラートラップ定義 */
>     exec sql whenever sqlerror do error_exit();
> 
>     /* データベースopen */
>     EXEC SQL connect to tcp:postgresql://mymachine:12345/testdb02;
> 
>     /* 動的にinsertする準備 */
>     memset(sqlstring,'\0',sizeof(sqlstring));
>     strcpy( sqlstring , "insert into tmptable values ( NULLIF(?,?) )");
>     EXEC SQL prepare ins_cur from :sqlstring;
> 
>     /* 動的に通常のデータ登録 */
>     indata=44;
>     EXEC SQL execute ins_cur using :indata,10;
> 
>     /* 動的にNULL値のデータ登録 */
>     indata=10;
>     EXEC SQL execute ins_cur using :indata,10;
> 
>     /* commit */
>     exec sql commit work;
> 
>     /* データベースclose */
>     exec sql disconnect;
> 
>     exit(0);
> }
> 
> 
> /* エラー処理 */
> void error_exit(void){
>     fprintf(stderr, "PostgreSQL error : %d[%.*s]\n",
>             sqlca.sqlcode, sqlca.sqlerrm.sqlerrml,sqlca.sqlerrm.sqlerrmc);
> 
>     exec sql whenever sqlerror continue;
>     exec sql rollback;
>     exec sql disconnect;
> 
>     exit(1);
> }
> 
> 
> /*
> testdb02=> -- psqlで結果を確認する
> testdb02=> select CASE WHEN row1 IS NULL THEN 999 ELSE row1 END from tmptable;
> 
>  row1
> ------
>    44
>   999
> (2 rows)
> 
> testdb02=>
> */
> 
> 
> 




pgsql-jp メーリングリストの案内