1

私の課題は、複数のテーブルで特定の文字を見つけることです。

私の仕事では、この d_date、d_inserteby_id、d_valid_to などの名前の列にすべての日付値を保持するように DB が設定されています。

したがって、日付への参照を含む行を探すときは、'%D_%' よりももう少しクリエイティブにならなければなりません

自分ができるということがわかっている: select * from table t where Upper(T.column) like '%D_%' escape '\'

しかし、ASCII 値を使用してその d とアンダースコアを検索する方法は?

4

3 に答える 3

3

スキーマが頻繁に変更される場合は、データ ディクショナリを調べて動的 SQL を使用する必要があります。

あなたはできる ...

select table_name,
       column_name
from   all_tab_columns
where  owner = ? -- insert name of table owner
and    upper(column_name) like 'D\_%' escape '\'

検索で D の ASCII 値を使用する利点はありません。コードが難読化されるだけです。LIKE と ESCAPE が正しいアプローチです。

ところで、大文字と小文字が混在するオブジェクト名を使用することは、Oracle では悪い習慣と見なされています。

編集: もちろん、ASCII 文字で文字列を検索したい場合は、次のようにします。

where ascii(substr('D_123',1,1))=68 and
      ascii(substr('D_123',2,1))=95

また

where ascii(substr('D_123',1,1))||ascii(substr('D_123',2,1))='6895'

また

where substr(dump(substr('D_123',1,2)),-6) = ' 68,95'

いつものように、物事を間違った方法で行う方法はたくさんあります。

于 2013-03-20T09:45:00.113 に答える
0

@Shogoot: 私があなたを正しく理解していれば、検索文字列の VALUE を持つ任意の列の ROW を持つすべてのテーブルを検索できるようにしたいと考えています。

上記が正しい仮定である場合、唯一の解決策は、次に示すように PL/SQL のブロックを使用することだと思います。

DECLARE

    -- Find tables that have the right type of columns
    CURSOR cur IS
        SELECT  atc.owner
                ,atc.table_name
                ,atc.column_name
        FROM    all_tab_columns atc
        WHERE   atc.data_type IN ('VARCHAR2', 'CHAR', 'DATE')
        AND     owner IN ('OE')
        ;

    vTestString VARCHAR2(250) := CHR(45); -- CHR(45) = '-'      
    iCount      INTEGER := 0;
    vStatement  VARCHAR2(2000) := '';
BEGIN

    -- Loop through tables and columns 
    FOR rec IN cur LOOP
        BEGIN
            -- Find tables that have the right type of columns
            vStatement  :=  'SELECT COUNT(*) '
                            || 'FROM ' || rec.owner || '.' || rec.table_name || ' '
                            || 'WHERE ' || rec.column_name || ' LIKE ''%' || vTestString || '%'' '
                            ;

            --dbms_output.put_line(vStatement);
            EXECUTE IMMEDIATE vStatement
            INTO iCount
            ;

            IF (iCount > 0) THEN
                dbms_output.put_line('Found ' || iCount || ' matches in: ' || rec.owner || '.' || rec.table_name || '.' ||  rec.column_name);
            END IF;     
        EXCEPTION
            -- Oops, we might end here if there is an error
            WHEN OTHERS THEN
                dbms_output.put_line('Something messed up with: ' || rec.owner || '.' || rec.table_name || '.' ||  rec.column_name || '(' || SQLERRM || ')');
        END;
    END LOOP;
END;

検索文字列を必要なものに変更する必要があります。上記のクエリは Oracle の OE スキーマに基づいており、必要に応じて "cur" クエリを微調整する必要があります。

また、大量のデータを検索する可能性があるため、自分の快適さに基づいて使用してください。

お役に立てれば。

〜TJ

于 2013-03-20T20:03:55.600 に答える
0

リテラルのアンダースコアの代わりに ASCII 値を使用する理由はまだわかりませんが、おそらくこれが必要です (95 は '_' の ASCII コードです)。

  select * 
  from t 
  where upper(t.column1) like '%D\' || chr(95) || '%' escape '\'

通常の文字をエスケープできないため、95 を 65 ('A' の場合) などに置き換えようとすると、エラーが発生することに注意してください。

これを処理するには、通常の文字とエスケープする必要がある文字を区別する何らかのロジックが必要です。

于 2013-03-20T14:04:37.857 に答える