Oracleで、1度のクエリで一括更新を行いたい

解決


yamada  2012-06-04 11:36:03  No: 42424  IP: 192.*.*.*

環境は
Delphi2010 Pro
Oracle 11gです。

Oracleへは、ADOで接続しています。

条件により、
複数回のUPDATEを行います。

SQL Serverで例にとると

var Query:TADOQuery;

Query.Add('UPDATE Tabele1 SET B = 10 WHERE A = 1;')
Query.Add('UPDATE Tabele1 SET B = 20 WHERE A = 2;')
Query.Add('UPDATE Tabele1 SET B = 30 WHERE A = 3;')
Query.Execute;



var sql:string;

sql:='UPDATE Tabele1 SET B = 10 WHERE A = 1;';
sql:=sql+'UPDATE Tabele1 SET B = 20 WHERE A = 2;';
sql:=sql+'UPDATE Tabele1 SET B = 30 WHERE A = 3;';
Query.Add(sql);
Query.Execute;

というような一括更新を行いたいのですが、
Oracleでの作り方がわかりません。

「/」で一文を区分けするようで、

Query.Add('UPDATE Tabele1 SET B = 10 WHERE A = 1');
Query.Add('/');
Query.Add('UPDATE Tabele1 SET B = 20 WHERE A = 2');
Query.Add('/');
Query.Add('UPDATE Tabele1 SET B = 30 WHERE A = 3');

とやってみましたが、やはりダメでした。



プロシージャの追加は事情によりできません。


ご教授いただけましたら、助かります。
宜しくお願いします。

編集 削除
初心者  2012-06-04 13:23:34  No: 42425  IP: 192.*.*.*

ダメだったとはどのようなエラーが表示されたのでしょうか?

編集 削除
yamada  2012-06-04 15:21:22  No: 42426  IP: 192.*.*.*

以下のエラーが表示されます。

---------------------------
デバッガ例外通知
---------------------------
プロジェクト Project1.exe は例外クラス EOleException (メッセージ 'ORA-00936: 式がありません。')を送出しました。
---------------------------
ブレーク(B)   継続(C)   ヘルプ   
---------------------------

編集 削除
初心者  2012-06-04 15:58:03  No: 42427  IP: 192.*.*.*

TQueryのコンポーネントを使って
SQLの中に
UPDATE Tabele1 SET B = 10 WHERE A = 1
/
UPDATE Tabele1 SET B = 20 WHERE A = 2
/
UPDATE Tabele1 SET B = 30 WHERE A = 3
を入れて実行してもエラーは表示されますか?

編集 削除
yamada  2012-06-04 16:12:29  No: 42428  IP: 192.*.*.*

残念ながら、同様の結果でした。

編集 削除
初心者  2012-06-04 16:18:41  No: 42429  IP: 192.*.*.*

UPDATE Tabele1 
SET B = decode(A,1,10,2,20,3,30) 
WHERE A in (1,2,3)
ではどうでしょう?

編集 削除
yamda  2012-06-04 16:44:20  No: 42430  IP: 192.*.*.*

ご教授ありがとうございます。

1万件以上の更新件数でして、
DECODEのパラメータ数の上限は 255らしく、、
今回は使えません。。。。

編集 削除
初心者  2012-06-04 16:58:02  No: 42431  IP: 192.*.*.*

となると実際のSQLを見ないとわからないですね、
エラー内容はSQL文が間違っているとしか言えない状況なので・・・

編集 削除
yamada  2012-06-04 17:09:13  No: 42432  IP: 192.*.*.*

そうですかぁ。

UPDATE Tabele1 SET B = 10 WHERE A = 1
の1行だけなら、問題ないのですが、続けて発行したいとなると
難しいのですかね。

1点伝え忘れたことがありました。
「/」は、ObjectBrowserというツール上の話でして、
Delphiからも、同様のことができるかな、と思い質問させていただきました。

編集 削除
初心者  2012-06-04 17:14:28  No: 42433  IP: 192.*.*.*

SQLはループ処理でaddしてると思うのですが、ループが終了した段階で
SQLの内容をtextで出力して、ObjectBrowserで動かしてみてはどうでしょうか?
動かないのならどこかでSQLが間違っている可能性があります

編集 削除
yamada  2012-06-04 17:30:57  No: 42434  IP: 192.*.*.*

先ほどの書込みで、
TQueryのコンポーネントを使って
SQLプロパティの中に文を入れて実行して、エラーが出力されてましたが、

同様の文をObjectBrowserにコピー貼り付けして実行すると、
問題なく、2回応答が返ってきます。

UPDATE文自体は、
UPDATE SyohinMst SET Zaiko = 10 WHERE SyohinNo = 1
というシンプルなものです。

編集 削除
nobukoshi802  2012-06-04 20:47:33  No: 42435  IP: 192.*.*.*

ストアドプロシージャはNGですが
無記名ストアドプロシージャはダメでしょうか?



declare
 vCount NUMBER(4) := 0;
begin
UPDATE Tabele1 SET B = 10 WHERE A = 1;
UPDATE Tabele1 SET B = 20 WHERE A = 2;
UPDATE Tabele1 SET B = 30 WHERE A = 3;
end;

編集 削除
yamada  2012-06-05 09:08:30  No: 42436  IP: 192.*.*.*

nobukoshi802さんありがとうございます。

知識不足ですいませんが、
無記名ストアドプロシージャとは何でしょう?
検索しましたが、それらしきものはなく、
どのようなものか教えて下さい。

よろしくお願いします。

編集 削除
初心者  2012-06-05 10:17:35  No: 42437  IP: 192.*.*.*

DECODEが無理ならcase文ならいけるのでは?と思いました。

編集 削除
nobukoshi802  2012-06-05 11:39:14  No: 42438  IP: 192.*.*.*

書き方が悪かったですね、無記名ストアドプロシージャ
では無く、無名ストアドプロシージャが一般的でした。

多分、ストアドが利用出来ないのは、Oracleのストアドが読め無い
もしくは、管理したくない場合と思われます。

SQL Plusで、Create Stored〜の部分無しで
declareから始まるSQLを発行して見てください。
それで、ストアドスロシージャが実行されます。

これでOracleのストアド知識も向上するので、がんばってください。

編集 削除
yamada  2012-06-07 17:56:55  No: 42439  IP: 192.*.*.*

nobukoshi802さんありがとうございます。

ストアドプロシージャに関しては、
あまりまだ作ったことがないので、
登録したくないな、というのはありました。


無名ストアドプロシージャに関しては、
調べまして、登録なしで使えるということはわかりました。

SQL Plus上で実行させてみて、実際に使えましたが、
どうDelphiで反映させればよいのかがわかりません。

TADOStoredProcコンポーネントは、
登録されているプロシージャの実行が、
基本であるという認識なのですが。

あらかじめ、スクリプトファイルを作成しなくても
リアルタイムでDelphi上から実行させたいのですが、
方法をご存知でしたら教えてください。
宜しくお願いします。

編集 削除
nobukoshi802  2012-06-07 20:14:45  No: 42440  IP: 192.*.*.*

yamadaさんが、SQL Plusで実行したSQLをTADOQueryで実行してください。
変数が必要な場合は、declareから開始します。
変数が不要なら、beginから開始します。

編集 削除
yamada  2012-06-18 15:07:08  No: 42441  IP: 192.*.*.*

初心者さん、
nobukoshi802さん、
ありがとうございました。

上記のnobukoshi802さんの方法解決いたしました。
質問内容的には、わからずじまいですが、
代替の方が応用効きそうなので、
こちらの方を使わせて頂きます。

色々と勉強になりました。

お二方に感謝です。
ありがとうございました!

編集 削除