0

最適化しようとしている Pro*C クエリに問題があります。

説明すると、アプリケーションは巨大なデータベースで行を検索します。これらの行は複数の言語に存在し、古いコードでは配列内の言語ごとに行が選択されていました。これらのクエリはアプリで最も時間のかかる部分であるため、配列に直接書き込むクエリを 1 つだけ作成したいと考えました。

言語コードは 2 文字の ISO-639 コードです (英語は en、フランス語は fr)。

古い方法 (これは意図を示すための単純化されたコードにすぎません)

struct ROW arr[MAX_LAN];
struct ROW_IND arr_ind[MAX_LAN];
uint_t LanIdx;
for(LanIdx=0; LanIdx<MAX_LAN; LanIdx++) {
  EXEC SQL SELECT *  /* Don't look at the *, it's for obfuscation only */
      INTO :arr[LanIdx]:arr_ind[LanIdx]
      FROM table WHERE id=:uniqid AND language=:LanCode[LanIdx];
}

私はこのようなことをしたいと思います:

EXEC SQL SELECT *  /* Don't look at the *, it's for obfuscation only */
    INTO :arr:arr_ind
    FROM table WHERE id=:uniqid AND language IN (:LanCodes);

しかし、LanCodes をどのように定義すればよいかわかりません。

このような定数(コンパイル時)リストで動作します

EXEC SQL SELECT *  /* Don't look at the *, it's for obfuscation only */
    INTO :arr:arr_ind
    FROM table WHERE id=:uniqid AND language IN ('en','fr','de');

ただし、言語は場合によって異なる可能性があるため、これは役に立ちません。

のようなものを書くと

char LanCodes[MAX_LANS*5];
sprintf(LanCodes, "%s", LanCode[LanIdx]);

EXEC SQL SELECT *  /* Don't look at the *, it's for obfuscation only */
    INTO :arr:arr_ind
    FROM table WHERE id=:uniqid AND language IN (:LanCodes);

文字列に言語コードが 1 つある場合にのみ機能します。

だから私の質問は、誰かがこれを機能させる方法を知っていますか? Oracle のドキュメントは膨大で、どこを見ればよいかわかりません。さまざまな方法を試しましたが、どれもうまくいきませんでした。

編集 OK、私はうまくいく解決策を見つけました。エレガントではなく、高度でもありませんが、うまく機能します。OR 句のリストをクエリに入れると、必要なものが必要な形式で返されます。

EXEC SQL SELECT *  /* Don't look at the *, it's for obfuscation only */
    INTO :arr:arr_ind
    FROM table WHERE id=:uniqid AND (
                language=:v1[ 0] OR
                language=:v1[ 1] OR
                language=:v1[ 2] OR
                language=:v1[ 3] OR
                language=:v1[ 4] OR
                language=:v1[ 5] OR
                language=:v1[ 6] OR
                language=:v1[ 7] OR
                language=:v1[ 8] OR
                language=:v1[ 9] OR
                language=:v1[10] OR
                language=:v1[11] OR
                language=:v1[12] OR
                language=:v1[13] OR
                language=:v1[14] OR
                language=:v1[15] OR
                language=:v1[16] OR
                language=:v1[17] OR
                language=:v1[18] OR
                language=:v1[19] OR
                language=:v1[20] OR
                language=:v1[21] OR
                language=:v1[22] OR
                language=:v1[23] OR
                language=:v1[24] OR
                language=:v1[25] OR
                language=:v1[26] OR
                language=:v1[27] OR
                language=:v1[28] OR
                language=:v1[29] OR
                language=:v1[30]);

2 つ以上の言語がある場合は高速なので、フェッチする言語の数に応じて、このバリアントまたは古いバリアントを呼び出します。

4

4 に答える 4

1

OracleDynamicSQLなしではこれを行うことはできません。実行時にIN句を作成し、すぐに実行する必要があります。少なくとも、クエリに基づいて方法1を使用できます。

于 2009-11-17T15:46:19.560 に答える
1

おそらく、このAskTom の記事が役に立ちます。

于 2009-11-17T18:43:10.550 に答える
0

...メイン文字列:='Select * FROM table WHERE id =:uniqid AND language IN'; --2つに分割して:uniqdを受け入れることができます...x_tableからv_stringにLanguage_codeを選択します。ループCopy&Concat v_string to LanCode_String and with''、; ループの終了; ..Lancodeをメイン文字列に連結します。..メイン文字列を準備して実行します。

于 2009-11-19T16:33:12.370 に答える
0

I have used a table before composed of an ID and a set of rows where the rows are the permutation of the possible values in the "in" list. Then I join to the table based on the ID and it gives me the results I need.

create table permute (
  id number,
  lang char(2)
);
create index permute_p1 on permute ( lang, id );
insert into permute ( id, lang ) values ( 1, 'en' );
insert into permute ( id, lang ) values ( 2, 'en' );
insert into permute ( id, lang ) values ( 2, 'fr' );
...

All you have to do then is pick the correct "ID" value 2, 3, 4 ... and put that into the join.

于 2009-11-18T17:08:24.540 に答える