2

私が Oracle を旅していたとき、その場で動的 SQL クエリを作成しなければならなかったとき、'stragg' 関数、または 'String Aggregator' は命を救ってくれました。

ここでそれについて読むことができます: http://www.oratechinfo.co.uk/delimited_lists_to_collections.html

それの基本的な使用法は次のとおりです。

select stragg(fruit) from food;

fruit
-----------
apple,pear,banana,strawberry

1 row(s) returned

とても使いやすく、chr(13) を連結すると長いリストになり、システム テーブルから情報を選択すると、動的に生成された SQL (監査トリガーなど) に対する 5 分のソリューションが得られました。

現在、私は監査に関連するオラクルの機能を Sybase に移行する責任を負っています。この目的には、Stragg に似た機能が理想的です。

例えば

select @my_table = 'table_of_fruit'

select 'insert into '+@mytable+'_copy (' +char(10)
   + stragg(c.name) +char(10)
   + 'select '
   + stragg('inserted.'+c.name) + char(10)
   + 'from '+@mytable
from syscolumns c
where objectid(@mytable) = c.id


------------------------------------------
insert into table_of_fruit_copy
(fruit, sweetness, price) 
select fruit, sweetness,price 
from inserted

終わり。単純。

ただし、文字列集計関数を Sybase で動作させる方法がわかりません。

この種のことをしようとする試み、またはこの方法で使用できる stragg と同じように機能するコードを知っている人はいますか?

現時点での代替手段は、複雑なカーソルなどに基づいてコードを出力すること (サンプル LOC: 500)、または静的文字列とユーザー テーブルの列を組み合わせた select ステートメント (サンプル LOC: 200) です。Stragg はこのコードの複雑さを大幅に軽減し、将来的に大きな助けになるでしょう (サンプル LOC: 誰が知っているか、おそらく 50?)

psシェルスクリプトを介してこれらの選択を呼び出し、ファイルにパイプしてから、iSQLを介してファイルを実行しています。最も良い解決策ではありませんが、代替案よりは優れています。

4

2 に答える 2

2

3つの別々の答えがあります

質問

あなたは単純さについてコメントしましたが、解決策にたどり着く前に対処する必要があります。

A、B、C、Dなどの区切られた値のリストを取得し、このデータをテーブル内の行のセットであるかのように扱うことができる、またはその逆を行うことができるのは一般的な要件です。

  1. これは、私が最近読んだ最悪のプログラミング手法のトップ10の1つです。

  2. 一般に、Sybaseタイプは、Oracleタイプよりも学術的および関係的に適格である傾向があるため、SybaseLandまたはDB2Landではそのようなことは行いません。

  3. Sybaseでの20年間の作業で、プロジェクトの一部として1回だけコーディングする必要がありました。これは、結果セットをMSAccessにロードした非技術的な監査人のためのものでした。

  4. 一方、Oracleデータベースにインポートするためのテキストファイルを作成する場合は、少なくとも12回コーディングする必要がありました(外部要件を満たすことはプロジェクトの範囲外ですが、そのような要件はすべて無料で満たします)。明らかに、ターゲットデータベースは標準以下で非リレーショナルでした(複数のデータを含む列をロードすると1NFが壊れ、更新異常が作成されます)。これは、Oracleタイプが速度を上げるために行う必要がある典型的なことです。

  5. したがって、いいえ、少なくともその原則の意味では、それは単純ではありません。それは定義上、複雑さです。

  6. 「配列」への参照が正しくありません。すべての商用dbmsは、ISO / IEC / ANSI SQLに従って配列を処理します(STRAGGRおよびLIST演算子は非標準SQLであるため、SQLではありません)。Sybaseは、配列の処理に非常に優れています。それが配列の場合、それを処理するために特別なハンドコーディングは必要ありません(そしてあなたの質問に従ってそうします)。これは配列ではなく、セルの定義はありません。これは、単一の連結されたスカラー文字列です。

  7. ピボットはまったく異なるプロセスであり、セット処理を使用します。行処理は必要ありません。(私は、Oracleがスカラーサブクエリに絶望的であることを理解しています。したがって、Oracleの人々は、[非常に非効率的な]結合またはインラインビューとしてそれらを記述し、フィルタリングすることに慣れています。これらはすべて、スカラーサブクエリを介してセット処理に昇格できます。 、そしてそれははるかに速く実行されます。特にあなたのピボット。)

  8. あなたのリンクの作者でさえ、次のように投稿しています。注意事項をよく理解してください。

これは簡単です。特定のプロセスに渡されるデータ要素の数に論理的な制限がないシステムが必要な場合は、次のメカニズムを忘れてください。それらは単に問題に取り組むための間違った方法です。

  1. したがって、あなたがしていることはすべて標準以下であり、非リレーショナルであり、制限されていることを知ってください。目を開けて進んでください。そのふりをして無駄です:それは壊れません。制限はありません。それは「配列」です。または、SybaseにはOracleのような小さな機能がありません。どんな専門家もそれをすべて見通すでしょう。また、文字列の長さを超えた場合は、神のために、その状態を識別するインジケーター(文字列の「!Exceeded」)を呼び出し元に送り返します。

  2. 基本的に、セット処理エンジンを頭に置き、行処理モードに強制するため、非常に遅くなります。WHILEループはカーソルよりも明らかに高速ですが、どちらも同じクラスの行プロセッサーです。

現時点での代替手段は、複雑なカーソルなどに基づいてコードを印刷することです。

  1. 200または500LoCは何ですか?何かが足りない可能性がありますが、私のコードは、リンクの 「テーブル関数の使用」で識別されているのと同じ数行のコードです。素敵なフォーマットを数えるなら、最大20 。ループ; 初期化; エラー処理。それについて「複雑」なことは何もありません。まったく逆の操作を行って、複数の行から1つの文字列を連結します。これにはストアドプロシージャを使用します(オラクルにはありませんが、実際にはPL / SQLは別の動物です)。ASE 15.0.2以降を使用している場合は、列の代わりに使用できるユーザー定義関数を使用できます。ストアドプロシージャは、真の配列に適しています。

    • Sybaseの連結演算子はプラス記号です。反転(CSV文字列の分解)には、CHARINDEX関数とSUBSTRING関数が必要です。

    • 関数がある場所にコードを書かないようにするために、関数リファレンスマニュアルが必要になる場合があります。

同様に、 RANK()関数もありません。サブクエリに必要な4行のコードに非常に満足しています。サブクエリが機能しなくなるため、Oracleにのみ必要です。


わかりました、私はあなたの質問に答えました、今アプローチに対処するために。

  • SQL標準に対するOracle拡張機能を使用するコードを変更する必要があることに気付くでしょう。

  • SybaseはOracleよりもはるかに自動化されています。その機能セットに精通している場合、多くの場合、コードを記述しなくても(Oracleで行ったのと同じ)同じ結果を得ることができます。コードごとのブロックを作成することは、ブルドーザーのコンテキストで、道路を構築するためのチェーンギャング、岩を壊す方法です。会社にその方法を使用する正当な理由がある場合でも、機能の動作がまったく異なることに注意する必要があります。トリガー、それが私が非常に多くの詳細を投稿している理由です。

  • もう1つの厄介な問題は、Oracleが実際にはANSI SQLに準拠しておらず(準拠しているように見えるように、多くの場所で定義を拡張している)、Sybaseは、顧客ベースを考えると、厳密にSQLに準拠していることです。したがって、同じ機能が異なる方法で、または異なるデプロイメントで機能することに加えて、ANSI SQL準拠のプラットフォームで実行するためだけに、OracleコードをANSI準拠レベルに上げるためにコードの変更が必要になる場合があることに注意する必要があります。

トリガーのコンテンツのコードを記述しようとしているのか、データベースへの変更をキャプチャしようとしているのかはわかりません。私は両方の答えを提供します。

監査

データベースへの変更をキャプチャする

非常に堅牢で高速かつ構成可能な監査サブシステムがあり、大量の銀行レベルの監査要件に適合します。DBAにsybaudit(個別の)データベースをセットアップしてもらい、キャプチャする必要のある変更を正確に構成します。この機能は、トリガーに書き込むことができるどのコードよりもはるかに高速に実行されます(エンジン内、実行中のスレッド内で実行されるため、上記に必要な行ごとの処理よりも100倍高速です)。そしてもちろん、セットアップ時間はコーディング時間のほんの一部です。

トリガー

繰り返しますが、何を達成しようとしているのか正確にはわかりませんが、あるテーブルへのすべての挿入をそのテーブルのコピー(トリガー内)にコピーしたい場合、提供したサンプルコードは機能しません(そして私は構文の問題はカウントしません)。

  1. あなたの例では、さまざまなデータ型を処理するために、さらに多くの作業を行う必要があります。列サイズ; 精度; 規模; そして、おそらくUPDATE()関数は、どの列が変更されたかを識別します(もちろん、UPDATEトリガーの場合)。さまざまなデータ型を文字列に変換するだけの場合は、CONVERT()関数を確認してください。

    • トリガーはトランザクションです。

    • 行処理コードをトリガーに配置しないでください(テーブルが絞め殺されます)

    • 動的SQLをトリガーに配置することはできません。

  2. しかし、Sybaseではそれも必要ありません。ユーザーガイドの第19章を参照してください。トリガーについては、いくつかのバリエーションと例があります。トリガーの内部では、次のことができるはずです。

    INSERT table_copy
        SELECT column_list  -- never use * unless you want the db fixed in cement
            FROM inserted
    
  3. すべてのテーブルへの挿入を1つの監査テーブルにコピーしようとしている場合は、注意してください。それから私はあなたの例をもう少し理解します。高度に対称的なマルチスレッドサーバー(Oracleはアーキテクチャの意味でのサーバーではありません)を強制的にテーブルを介してシングルスレッドにします。監査はマルチスレッドです。

最後に、手動による方法を使用する必要はありません。PSをもう少し拡張できれば、満たそうとしている要件は何ですか。プログラムによる方法を特定できます。PL / SQLアプローチ(非常に制限されています)を使用しようとしているようです。

于 2010-12-12T09:41:57.927 に答える
0

関数を使用するだけLIST()です。これは、関数の直接の置き換えですstragg()。例:

SELECT LIST(state, ', ') FROM cities

結果:

name
CA, CA, MA, NY
于 2015-01-19T02:04:42.497 に答える