1

我的挑战是在多个表中找到某些字符。

在我的工作中,数据库设置为将所有日期值保存在名为 d_date、d_inserteby_id、d_valid_to 等的列中。但下划线是 SQL 权限中的保留字符,因此像 '%D_%' 这样的直截了当不起作用。

因此,当我查找包含对日期的引用的行时,我必须比 '%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

我仍然不确定你为什么要使用 ASCII 值而不是文字下划线,但也许这就是你想要的(95 是 '_' 的 ASCII 代码):

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

请注意,如果您尝试将 95 替换为例如 65(对于“A”),这将引发错误,因为您无法转义普通字符。

要处理这个问题,您需要某种逻辑来区分正常字符和必须转义的字符。

于 2013-03-20T14:04:37.857 回答
0

@Shogoot:如果我对您的理解正确,您希望能够搜索具有任何列的任何 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 回答