4

元のテーブルからシャドウテーブルの膨大なリストを作成する必要がある監査証跡モジュールに取り組んでいました。別のテーブルからシャドウテーブルを生成できるストアドプロシージャを作成することを考えていました。このテーブルは、任意のテーブル、任意のデータ型の3つのフィールドで構成されるtable_A、または任意のデータ型の10個のフィールドで構成されるtable_Bであり、ストアード・プロシージャーへのパラメーターの受け渡しに基づくことができます。

次のように、syscolumnsおよびsystablesから特定のtable_Aで使用可能なフィールドのリストを取得できることを知っています。

select * from syscolumns where tabid = (select tabid from systables where tabname='table_A')

このステートメントから返されるフィールドのリストがあります。たとえば、field_Aとすると、このfield_Aの名前を変更してpre_field_Aとpost_field_Aの2つの新しいフィールドを作成し、これら2つの新しいフィールドを使用してshadow_table_Aのシャドウテーブルを作成します。この概念を残りのフィールドに適用します。この情報はすでにsyscolumnsにあるので、フィールドのデータ型について心配する必要はありません。シャドウテーブルに複製するだけです。

通常、どのテーブルも複数のフィールドで構成されているため、現在、上記のステートメントから返される値のリストをどのように格納できるかについて悩んでいます。アレイを使用して実行できますか?または、監査証跡の目的でシャドウテーブルを作成するための代替ソリューションはありますか?

4

2 に答える 2

4

クエリは機能しますが、結合を使用する方が慣用的かもしれません。

SELECT *
  FROM "informix".systables AS t
  JOIN "informix".syscolumns AS c ON t.tabid = c.tabid
 WHERE t.tabname = 'table_a';

table_Aまた、環境にDELIMIDENTを設定し、名前を二重引用符で囲んでテーブルを作成した場合にのみ、システムカタログに大文字と小文字が混在することに注意してください。通常、テーブル名はシステムカタログではすべて小文字になります。列名についても同様です。

しかし、それはすべてあなたの質問に正接しています。すべての栄光の中でユーザー定義の型を扱うのは苦痛です。ただし、通常のデータベースを扱っている場合は、確かにそのように作業できますが、DB-Schema(dbschema)を使用してテーブルのスキーマを生成し、それをトラップする方が簡単な場合があります。実際には、SYSTEMステートメントを使用してストアドプロシージャを介してこれを行うことができますが、おそらくストアドプロシージャの外部から行うでしょう。それはあなたが他に何をする必要があるかに依存します。各フィールドのプレイメージとポストイメージは、適度にコストがかかる可能性があります。

IBM Informix Dynamic Server 11.70を使用している場合は、CREATE {audit} TABLEステートメントを動的に作成してから、ステートメントを実行できます。したがって、ストアドプロシージャでFOREACHループを使用してクエリを作成し、各列を順番に追加してから、ステートメントを実行して監査テーブルを作成します。タイプもデコードする必要があります。そのための手順も使用できます/使用する必要があります。tabnameこれはストアドプロシージャに渡される変数であり、、、はc_colnoローカル変数であると想定しています(のように、'create table statement'の略であり、):c_colnamec_typenamectspad

LET cts = 'CREATE TABLE ' || tabname || '(';
LET pad = '';
FOREACH SELECT c.colno, c.colname, type_name(c.coltype, c.collength)
          INTO c_colno, c_colname, c_typename
          FROM "informix".systables AS t
          JOIN "informix".syscolumns AS c
            ON t.tabid = c.tabid
         WHERE t.tabname = tabname
         ORDER BY c.colno
    LET cts = cts || pad || 'pre_'  || c_colname || ' ' || c_coltype;
    LET cts = cts || ',' || 'post_' || c_colname || ' ' || c_coltype;
    LET pad = ',';
END FOREACH;
LET cts = cts || ');';

NOT NULLや主キーの制約など、さまざまなことを処理したい場合がありますが、これにより、基本的な作業が可能になります。

于 2012-04-12T03:46:13.027 に答える
3

JonathanLeffler回答に加えて、次のtype_name手順があります。

    CREATE PROCEDURE type_name(coltype INTEGER, colsize INTEGER)
            RETURNING VARCHAR(128);
            DEFINE toRet                    VARCHAR(128);

            DEFINE size_5                   VARCHAR(5);
            DEFINE decimal_p, decimal_s     INTEGER;
            DEFINE decimal_t                VARCHAR(16);
            DEFINE varchar_m, varchar_n     INTEGER;
            DEFINE varchar_t                VARCHAR(16);

            LET size_5 = '(' || TRIM(CAST(colsize AS CHAR(5))) || ')'; 
            -- Precision
            LET decimal_p = TRUNC(colsize/256);
            -- Scale
            LET decimal_s = colsize - 256 * decimal_p;
            -- Decimal total
            LET decimal_t = '(' || TRIM(CAST(decimal_p as VARCHAR(8))) || ',' || TRIM(CAST(decimal_s as VARCHAR(8))) || ')';

            -- VARCHAR(M,N)
            LET varchar_n = decimal_p;
            LET varchar_m = decimal_s;
            LET varchar_t = '(' || TRIM(CAST(varchar_m as VARCHAR(8))) || ',' || TRIM(CAST(varchar_n as VARCHAR(8))) || ')';

            SELECT
                CASE coltype
                    WHEN 0   THEN 'char' || size_5 
                    WHEN 1   THEN 'smallint'
                    WHEN 2   THEN 'integer'
                    WHEN 3   THEN 'float'
                    WHEN 4   THEN 'smallfloat'
                    WHEN 5   THEN 'decimal' || decimal_t
                    WHEN 6   THEN 'serial'
                    WHEN 7   THEN 'date'
                    WHEN 8   THEN 'money' || decimal_t
                    WHEN 9   THEN 'null'
                    WHEN 10  THEN 'DATETIME YEAR TO FRACTION(3)'
                    WHEN 11  THEN 'byte'
                    WHEN 12  THEN 'TEXT'
                    WHEN 13  THEN 'VARCHAR' || varchar_t
                    WHEN 14  THEN 'INTERVAL'
                    WHEN 15  THEN 'NCHAR' || size_5
                    WHEN 16  THEN 'NVARCHAR' || varchar_t
                    WHEN 17  THEN 'INT8'
                    WHEN 18  THEN 'SERIAL8'
                    WHEN 19  THEN 'SET'
                    WHEN 20  THEN 'MULTISET'
                    WHEN 21  THEN 'LIST'
                    WHEN 22  THEN 'ROW'
                    WHEN 23  THEN 'COLLECTION'
                    WHEN 24  THEN 'ROWDEF'
                    WHEN 40  THEN 'LVARCHAR'  || size_5 
                    WHEN 256 THEN 'CHAR' || size_5 || ' NOT NULL'
                    WHEN 257 THEN 'SMALLINT NOT NULL'
                    WHEN 258 THEN 'INTEGER NOT NULL'
                    WHEN 259 THEN 'FLOAT NOT NULL'
                    WHEN 260 THEN 'SMALLFLOAT NOT NULL'
                    WHEN 261 THEN 'DECIMAL' || decimal_t || ' NOT NULL'
                    WHEN 262 THEN 'SERIAL NOT NULL'
                    WHEN 263 THEN 'DATE NOT NULL'
                    WHEN 264 THEN 'MONEY' || decimal_t || ' NOT NULL'
                    WHEN 265 THEN 'null NOT NULL'
                    WHEN 266 THEN 'DATETIME YEAR TO FRACTION(3) NOT NULL'
                    WHEN 267 THEN 'BYTE NOT NULL'
                    WHEN 268 THEN 'TEXT NOT NULL'
                    WHEN 269 THEN 'VARCHAR' || varchar_t || ' NOT NULL'
                    WHEN 270 THEN 'INTERVAL NOT NULL'
                    WHEN 271 THEN 'nchar(' || size_5 || ') NOT NULL'
                    WHEN 272 THEN 'nvarchar' || varchar_t || ' NOT NULL'
                    WHEN 273 THEN 'int8 NOT NULL'
                    WHEN 274 THEN 'serial8 NOT NULL'
                    WHEN 275 THEN 'set NOT NULL'
                    WHEN 276 THEN 'multiset NOT NULL'
                    WHEN 277 THEN 'list NOT NULL'
                    WHEN 278 THEN 'row NOT NULL'
                    WHEN 279 THEN 'collection NOT NULL'
                    WHEN 280 THEN 'rowdef NOT NULL'
                    WHEN 296 THEN 'LVARCHAR'  || varchar_t || ' NOT NULL'
                    ELSE 'ERROR'
                END datatype
            INTO toRet
            FROM systables
            WHERE tabid = 1;
            IF toRet = 'ERROR' THEN
               RAISE EXCEPTION -746, 0, 'Unknow datatype ' || coltype;
            END IF

            RETURN toRet;
    END PROCEDURE;

これへのクレジット。

于 2014-08-21T17:37:46.923 に答える