プロが教えるわが家の防犯対策術!

いつもお世話になっています。
PL/SQLでストアドを作成中なのですが、
あるUPDATE分のWHERE句の条件として“IS NULL”を使用したいのですが、監督者から “IS NULL”はNGという指示が出てしまい困っています。
(理由はNULLは索引の対照外だからということです。)
以前、“IS NOT NULL”の代用として、“項目名 ≧ 0”が使えることを学んだのですが、“IS NULL”にも同じように代用できる条件の記述方法はありますか?
“IS NOT NULL”が“項目名 ≧ 0”なら
“IS NULL”は“項目名 < 0”というのは無謀でしょうか?

このQ&Aに関連する最新のQ&A

A 回答 (2件)

こんにちは。



確かに「IS NULL」は、INDEXを使いませんが、
NULLかどうかを判断するなら、仕方がないと思います・・・。
「NVL」で変換すれば何とかなりそうですが、レスポンス的には意味がありません・・・。
WHERE句の条件としてNULLを使用できないのなら、元のテーブル構造に問題があると言わざるを得ません・・・。

この場合はいたしかたないかと・・・。
(^^ゞ
    • good
    • 0

EXISTS は確かインデックスを使用したような・・・




UPDATE TABLE1
SET FIELD1 = 'HOGE'
WHERE FIELD2 IS NULL;

の代用として

UPDATE TABLE1 T1
SET FIELD1 = 'HOGE'
WHERE NOT EXISTS (SELECT T2.任意フィールド FROM TABLE1 T2 WHERE T2.FIELD2 >=0 AND T2.キー項目 = T1.キー項目);

ではダメでしょうか?
(パフォーマンスとかは未チェックですが・・・)
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

関連するカテゴリからQ&Aを探す

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q【SQLServer】IS NULLのパフォーマンス

お世話になっております。SQLSERVER初心者です。

NULLを含む列COL1を検索条件に入れる場合、
パフォーマンスの観点から

WHERE COL1 IS NULL とするのではなく
WHERE ISNULL(COL1,'') = '' とするよう有識者から言われました。

そこで質問なのですが、

(1)IS NULL は基本的に上記のように変換したほうが早くなるのですか?
(2)COL1にもしインデックスが設定されていたとしても、上記の場合だとどちらも効かないですよね?

詳しい方おしえてください。
よろしくおねがいします。

Aベストアンサー

試しにこちらの適当なテーブルに索引をつけて検索してみました。

(1)WHERE COL1 IS NULL
INDEX SEEKになりました

(2)WHERE ISNULL(COL1,'') = ''
INDEX SCANになりました

INDEX SEEKなので(1)の方が効率がよさそうです。
ManagementStudioでSQL実行時に「実際の実行プランを含める」のオプションつきで実行してみてください。

でも、(2)は長さ0の空文字も対象にするから(1)と(2)は結果が変りますよね。このことを考慮してますか?

※長さ0の文字列とNULLを区別するかどうかはDBによって異なります。

QViewにインデックスは張れますか?

件名の通りなのですが、作成したViewが遅くて困っています。
改善方法としてはViewを作成しないで従来のSQLにインデックスを張って取得する方法にしようかなと考えています。
なにかいい方法はありますか?

Aベストアンサー

Viewの元テーブルに適切なIndexを貼る、ではいけないのですか?

QNVLとDECODEのスピード差

現在、ORACLE9iで開発していましてPLSQLの中で
ある項目がヌルの時に他の項目とするような場合、
以下の2種類の関数で実現できるのですが
どちらの使い方がスピードが速いのか知りたいのですがよろしくお願いします
1.DECODE(A,NULL,B,A)
2.NVL(A,B)

Aベストアンサー

普通に考えたらNVLだと思います。
DECODEは
1.関数の認識
2.値Aの一致性確認
3.置き換え文字の確認B
の3ステップがかかりますが
NVLは
1.関数の確認
2.値Aの一致性確認
だけで済みますから。
NVLよりDECODEがいいのであればNVLは存在意義がなくなります。しかし厳密な速さは違いがあるでしょうか
迷うことは杞憂かと思われます。(ほかのことを悩んだ方が良いでしょう)
あとはコードの可読性ですね。
DECODEよりNVLの方が関数を見ただけで何がしたいのかすぐにわかるので可読性があがります。
よくDECODEを変換表のようにやたらめったら使っているSQLを見ますがあれを見るとプログラマの技術を疑います...

Q実行計画の「COST」と「BYTE」について教えていただきたいです。

実行計画の「COST」と「BYTE」について教えていただきたいです。

書籍には
COST・・・・CBOによって見積もられた操作コスト。
BYTE・・・・アクセスされるバイト数のCBOのアプローチによる見積もり。
と書かれていますが、いまいちピンときません。


私は、
COSTは、検索するテーブルのデータ量が多いほうがコスト値が大きくなる。
BYTEは、検索条件に合致して取得できるデータが多いほうがバイト値が大きくなる。
と思っているのですが、正しいでしょうか?

Aベストアンサー

このあたりを参考にしてください。
COSTはデータ量だけではなく、その表やViewのアクセスに要する時間やSortや結合が必要なら、そのために必要なCPU時間等も考慮されています。
表があるHDDのアクセス速度なんかも考慮されているし、表のエクステントが複数になっているかとかも考慮されています。
書籍はわかりにくいかもしれませんが、嘘は少ないと思います。著者が思い違いをしてないとは言い切れませんが。

参考URL:http://otn.oracle.co.jp/forum/message.jspa?messageID=35016743

Qテーブルからのselectにおいてデータの有無により結果をわけたい

id | point
----+-------
1 | 10
2 | 9
3 | 5
....
というテーブルがあるとします.
idを指定してpointを得たいのですが、そのidがこのテーブルに存在しない場合は空の結果ではなく0を返したいのです.
plpgsqlなどを使いif文で場合分けすればできることはわかっているのですがSQL文だけで(それもできれば1文で)これを実現する方法はあるでしょうか?
よろしくお願い致します。

Aベストアンサー

変則的ですが、これでよければidがユニークでなくても大丈夫ですし、集合関数を使わなくてもOKです。

select dm.id,case when ex1.point is null then 0 else ex1.point end from
(select ? as id) as dm left join ex1 on dm.id = ex1.id;

?を適当に変えてください。
chukenkenkouさんの発想はこれですよね。

Q外部結合のパフォーマンスチューニングできますか

下のSQL文がパフォーマンスが非常に悪いです。
何かチューニングする方法ありませんか。

Oracle8.1.7 
OSはWin2000serverSP2

◇SQL文
SELECT A.HINCD , B.TANCD ,A.SIZE,A.COLOR
FROM TB_TBLA A ,TB_TBLB B
WHERE A.KA_CD = B.KA_CD(+)"
AND A.HINCD = B.HINCD(+)
AND A.JIGYOCD = 1
AND A.BRCD = 20
AND A.BUCD = 300

TB_TBLAの主キーは、JIGYOCD、BRCD、BUCDです。
TB_TBLBの主キーは、KA_CDです。

また、TB_TBLAの件数は、約10万件、TB_TBLBは3万件だとしたら、
読み込み件数は10万*3万件となるのでしょうか。

よろしくお願いします。

Aベストアンサー

>"iniSID.ora”の中の”SORT_AREA_SIZE”を変更するような感じで色々書いてあるのですが、iniファイルには”SORT_AREA_SIZE”たる記述がありません。
初期化パラメータファイル(init.ora)にありませんか。
ただ初期化パラメータの「sort_area_size」を大きめに変更する場合、同時に「sort_area_retained_size」も変更しないと意味がないかと思います。

それと、init.oraを変更して、Oracleを再起動する野は大変ですよね。
ALTER SESSION SET SORT_AREA_SIZE=値;で設定していろいろ試してから変更するほうがらくだと思います。

QOracleの排他制御について教えてください

質問内容は結論から言うと、
INSERT文の時の排他制御について
知りたい。

以下の私の認識を踏まえた上で、
INSERT文の排他制御について
質問させてください。
なお、私の認識に誤りがあれば
指摘してください。

### 私の認識 start ######

1)Oracle
では、select文の時に
for updateを
書かなければ、なんのロックもかからず、
読み取り専用リソースへのアクセスで
ない限り、
ダーティーリードの可能性がある。

2)
select文で for update
を指定した場合は
該当行について
共有ロックがかかる。
行単位の共有ロックがかかる。
その際、
他のトランザクションが
for updateつきで
selectしてきても、
共有ロック同士なので、
互い排他制御しない。

(3)
update 文の場合は
該当行について、
占有ロックがかかる
行単位の占有ロックがかかる。

(4)
INSERT文の時には、
ロックをかけようにも
INSERT前の段階では、
ロック対象行は存在しない。
複数のトランザクションが
INSERTした行のPK
の値が偶然同じであった場合
ロストアップデートの危険があるので
私の創造では、INSERT文の時は
テーブル全体をロックしないと、
うまくいかないように思えます。

(5)
update, insert文については、
Oracleでは、自動的に該当行について
占有ロックを行う。
なお、INSERT文については、
下記の質問事項における疑問点
が解消されていないため、
行単位なのかどうか、私の中では
自身がもてないのが現状です。
### 私の認識 end ######

### 主な質問内容 start ###
私の認識の(4)を踏まえた上で
INSERT文の時のはいた制御
の範囲や挙動について、
教えてください。
### 主な質問内容 end ###

以上です。

質問内容は結論から言うと、
INSERT文の時の排他制御について
知りたい。

以下の私の認識を踏まえた上で、
INSERT文の排他制御について
質問させてください。
なお、私の認識に誤りがあれば
指摘してください。

### 私の認識 start ######

1)Oracle
では、select文の時に
for updateを
書かなければ、なんのロックもかからず、
読み取り専用リソースへのアクセスで
ない限り、
ダーティーリードの可能性がある。

2)
select文で for update
を指定した場合は
該当行について
共有ロッ...続きを読む

Aベストアンサー

#2 補足です。
2)
SELECT FOR UPDATE文は
NO WAIT オプションをつけたときは即時エラーに、
つけないときはロック解除待ちになります。
どちらを使うかはアプリケーションの作り方のポリシーによります。

セッション=クライアントとサーバの間の接続。データベースに接続してから切断するまでの間の接続が確立している状態

トランザクション=データベースの処理をひとまとまりにしたモノ。たとえば、口座Aから口座Bへの振り込み処理の場合、口座Aからの引き出し、口座Bへの振り込みの処理を1トランザクションとして扱います。どちらかが失敗した場合はロールバック(巻き戻し)、成功した場合はコミット(確定)します。

業務用アプリケーションの場合、大抵、1回のセッションの中では複数回のトランザクションが発生します。複数のユーザーがそのアプリケーションを利用していればその数だけセッションが張られます。(Webアプリに関してはその限りではないですが)

デッドロック=
Aと言うセッションがトランザクション内で
1-1 表Xのa行に更新をかけます。
1-2 次に表Yにb行に更新をかけます。
1-3 コミットします(トランザクションの終了)。

同時に
Bと言うセッションがトランザクション内で
2-1 表Yにb行に更新をかけます。
2-2 次に表Xのa行に更新をかけます。
2-3 コミットします(トランザクションの終了)。

これが、1-1 2-1 1-2 2-1 1-3 2-3
と言う順番で実行された場合デッドロックが発生します。つまりAは、X-aにロックをかけたままY-bにロックをかけようとして待ち状態になる。逆にBは、Y-bにロックをかけたまま、X-aにロックをかけようとして待ち状態になる。この状態をデッドロックと呼びます。

なお、Oracleでは、UNDOセグメントではなくロールバックセグメントと呼びます。

a)アーキテクチャに突っ込んだ話になるので、詳しくはOracle データベース概要のドキュメントを読んでください。

基本的に、SELECT中に他のセッション(アプリケーションの方が良いかな?)からの更新が確定した場合、SGA(システムグローバルエリア=Oracleサーバの共有メモリスペース)に前のデータのバックアップを取ります。これによって読み取り一貫性を保証します。ここにデータが入りきらない場合はデータベースのロールバックセグメント(たしか)に吐き出します。

b)
簡単に言えば、Oracleは、行ごとにロックフラグなどを記録する領域を持っています。マニュアルなどに書いてなければおそらく企業秘密です。

#2 補足です。
2)
SELECT FOR UPDATE文は
NO WAIT オプションをつけたときは即時エラーに、
つけないときはロック解除待ちになります。
どちらを使うかはアプリケーションの作り方のポリシーによります。

セッション=クライアントとサーバの間の接続。データベースに接続してから切断するまでの間の接続が確立している状態

トランザクション=データベースの処理をひとまとまりにしたモノ。たとえば、口座Aから口座Bへの振り込み処理の場合、口座Aからの引き出し、口座Bへの振り込みの処理を1トラン...続きを読む

QMAX値を条件にデータを取得するには?

SQL文で困っています。
ご教授下さい。


下記のようなデータがあった場合、それぞれの区分毎に
年月が最大(最新)のデータを取得したいです。
(実際には1レコードにその他項目があり、それらも取得します。)
<検索対象データ>
区分 年月   金額
-----------------------------
A   200412  600
A   200503  560
B   200311  600
B   200508  1000
B   200504  560
C   200508  400
C   200301  1100


<取得したいデータ>

区分 年月   金額
-----------------------------
A   200503  560
B   200508  1000
C   200508  400

よろしくお願いします。

Aベストアンサー

テーブル名をXXXとすると次のようなSQLでよいと思います。(最善の方法かどうかは自信がないですが)

select B.* from (select 区分, max(年月) as 年月 from XXX group by 区分) As A
inner join XXX as B on A.区分 = B.区分 and A.年月 = B.年月
order by B.区分

Q処理速度について(UPDATE)

下記の2つのSQL句があります。
どのSQLが処理速度が速いのでしょうか。
また、一般的なのはどのSQLなのでしょうか。

処理1
UPDATE テーブルA
SET 項目A = '0'
WHERE NVL(項目A,'0') = '0';

処理2
UPDATE テーブルA
SET 項目A = '0'
WHERE 項目A IS NULL;

私としては、処理2の方が早いような気がするのですが・・・

教えてください。お願いします。

Aベストアンサー

歴然とした差はないでしょうが、NVL(項目A,'0') に関数インデックスが張られていない限り、処理2の方が高速になるでしょう。

まず、処理1も処理2も全表走査になりますので、実行計画には差がありません。

解析時間については、NVL(項目A,'0') に関数インデックスが存在するかどうかを調査する時間を考慮すると処理2の方が速いかもしれません。(ミリ秒レベルの差もあるかどうかは分かりませんが)

次に、更新量ですが、処理1の場合、項目Aが NULL の場合だけでなく、'0' の場合も更新対象になってしまうため、項目Aが '0' であるレコードが多い場合は若干遅くなるかもしれません。(これはミリ秒の世界でしょうが)

さらに、処理1の場合は、項目Aの全ての行に対して NVL 関数を適用しなければならないのに対して、処理2では、単純に項目Aが NULL であるかどうかを比較するだけで済んでしまいます。(これもミリ秒の世界でしょうが)

Q3つの表の外部結合

表A、B、Cの3つがあり、Aのすべての行を出力したいと考えています。
外部結合を用いるのだとは思うのですが、3つの表に対して行う場合の
書き方がわからず困っています。
ご教授いただけないでしょうか?
select * from a,b,c
where a.商品ID =b.商品ID (+) and b.商品ID (+) =c.商品ID (+)
としてみましたが、うまくいきませんでした。

Aベストアンサー

ansi構文の趣旨からいえば、結合条件と絞り込み条件は分けて書くので・・

select *
from a
left join b on (a.商品ID =b.商品ID)
left join c on (b.商品ID =c.商品ID)
where a.年月 = 任意の値

と書くのが一般的でしょうね。


人気Q&Aランキング