2

これはばかげた問題ですが、私はそれを回避できないようです。OCIプログラムで問題を引き起こしているクエリがあるので、SQL * Plusで手動で実行して、そこに違いがあるかどうかを確認したいと思います。これはクエリです:

select e.label as doc_name,
                       e.url,
                       i.item_id,
                       'multi' as form_type
                from cr_items i, cr_extlinks e
                where i.parent_id = :comment_id
                and e.extlink_id = i.item_id
               UNION
                select null as doc_name,
                       utl_raw.cast_to_varchar2(DBMS_LOB.SUBSTR(r.content, 2000, 1))  as url,
                       r.item_id,
                       'single' as form_type
                from cr_revisions r
                where r.revision_id = ( select content_item.get_latest_revision(:comment_id) from dual);
end;

comment_idを値3052753にバインドしたかったので、次のようにしました。

    DECLARE
     comment_id number := 3052753;
    BEGIN
    select e.label  ,
                           e.url,
                           i.item_id,
                           'multi'  
                    from cr_items i, cr_extlinks e
                    where i.parent_id = :comment_id
                    and e.extlink_id = i.item_id
                   UNION
                    select null  ,
                           utl_raw.cast_to_varchar2(DBMS_LOB.SUBSTR(r.content, 2000, 1))  as url,
                           r.item_id,
                           'single'  
                    from cr_revisions r
                    where r.revision_id = ( select content_item.get_latest_revision(:comment_id) from dual);
    END;
/

これにより、このエラーが発生します。

ORA-06550: line 4, column 1:
PLS-00428: an INTO clause is expected in this SELECT statement

さて、このクエリを根本的に変更したくないので、私はすでに不満を持っていますが、とにかく私は前進してこれを思いつきます(INTOとUNIONはそれほどスムーズに連携しません):

DECLARE
 comment_id number := 3052753;
 x_label VARCHAR2(50);
 x_url VARCHAR2(500);
 x_item number;
 x_thing VARCHAR2(50);
BEGIN
select label, url, item_id, thing into x_label, x_url, x_item, x_thing from (
select e.label  ,
                       e.url,
                       i.item_id,
                       'multi' as thing  
                from cr_items i, cr_extlinks e
                where i.parent_id = :comment_id
                and e.extlink_id = i.item_id
               UNION
                select null  ,
                       utl_raw.cast_to_varchar2(DBMS_LOB.SUBSTR(r.content, 2000, 1))  as url,
                       r.item_id,
                       'single' as thing 
                from cr_revisions r
                where r.revision_id = ( select content_item.get_latest_revision(:comment_id) from dual)) ;
END;
/

しかし今、もちろん、私は1行以上を返すので、完全に予測可能になります

ORA-01422: exact fetch returns more than requested number of rows

これで、カーソルなどを使い始めることができますが、私の小さなクエリは、元の自己からますます歪んでいます。私がやりたかったのは、comment_idの値でクエリが正常に実行されたかどうかを確認することだけでした。もちろん、comment_idをクエリにハードコーディングするだけで、問題なく機能します。ただし、OCIでも正常に機能するため、SQL * PLusで、OCIコードに表示されているバインド変数の問題を再現します。しかし、SQL * Plusでこれを行うのはなぜそんなに苦労するのでしょうか?私は本当に明白な何かを逃したことがありますか?

データベースはOracle10.2.0.1.0です-RedHatEnterprise Linux ESリリース4(Nahant Update 8)で実行されている64ビット

4

2 に答える 2

3

@Glennのアプローチに似ていますが、SQL * Plusでバインド変数を宣言し、それをプレーンSQLクエリで使用できます。var[iable]まず、次のコマンドで宣言します。

variable comment_id number;

次にexec[ute]、基本的に匿名ブロックであるコマンドで設定します。

execute :comment_id := 3052753;

次に、参照を使用して元のクエリを実行し、:comment_idnoBEGINまたはEND

select e.label as doc_name,
                       e.url,
                       i.item_id,
                       'multi' as form_type
                from cr_items i, cr_extlinks e
                where i.parent_id = :comment_id
                and e.extlink_id = i.item_id
               UNION
                select null as doc_name,
                       utl_raw.cast_to_varchar2(DBMS_LOB.SUBSTR(r.content, 2000, 1))  as url,
                       r.item_id,
                       'single' as form_type
                from cr_revisions r
                where r.revision_id = ( select content_item.get_latest_revision(:comment_id) from dual);

個人的な好みを超えて、2つのアプローチの間に機能的な違いはあまりないと思います。どちらも、SQL Developer(スクリプトとして実行する場合)でも機能します。:バインド形式をすでに使用しているPro*CファイルからコピーしたSQLを実行すると、コードをまったく変更する必要がないため、これが簡単になります。


ちなみに、あなたは書くことができます:

where r.revision_id = ( select content_item.get_latest_revision(:comment_id) from dual)

余分なものなしで、次のselectように:

where r.revision_id = content_item.get_latest_revision(:comment_id)
于 2012-06-22T13:53:11.427 に答える
2

匿名ブロックを作成するのではなく、sqlplusで環境変数を定義することをお勧めします。

DEFINE comment_id = 3052753

次に、クエリで&comment_idを参照します。

select e.label as doc_name,
                       e.url,
                       i.item_id,
                       'multi' as form_type
                from cr_items i, cr_extlinks e
                where i.parent_id = &comment_id
                and e.extlink_id = i.item_id
               UNION
                select null as doc_name,
                       utl_raw.cast_to_varchar2(DBMS_LOB.SUBSTR(r.content, 2000, 1))  as url,
                       r.item_id,
                       'single' as form_type
                from cr_revisions r
                where r.revision_id = ( select content_item.get_latest_revision(&comment_id) from dual);
于 2012-06-22T13:33:38.077 に答える