3

任何人都可以帮我解决 FIXME 吗?

-- Task: Get records with given rowid IN STRING from a table.
-- NOTICE: I do not known where the given rowid comes from.

-- OUTPUT 'AAAAB0AABAAAAOhAAA'
SELECT ROWID FROM DUAL; 
-- OK, one record
SELECT * FROM DUAL WHERE ROWID IN ('AAAAB0AABAAAAOhAAA');
-- run with no errors, and no records
SELECT INFO_ID FROM TM_INFO_CATALOG  WHERE ROWID IN (SELECT ROWID FROM DUAL);
-- ERROR: ORA-01410 invalid ROWID, WHY ?????????? (This is my sql statement)
SELECT INFO_ID FROM TM_INFO_CATALOG  WHERE ROWID IN ('AAAAB0AABAAAAOhAAA');  -- FIXME

-- Question: How to check an rowid is exists in a table?

-- The following is my way:
-- FIRST, I need check whether the given rowid is from the table to query.
-- OK, but, low performance, as using function 'ROWIDTOCHAR()' (I think so.)
SELECT 1 FROM TM_INFO_CATALOG WHERE 'AAAAB0AABAAAAOhAAA' IN (SELECT ROWIDTOCHAR(ROWID) FROM TM_INFO_CATALOG);
-- ERROR: ORA-01410 
SELECT 1 FROM TM_INFO_CATALOG WHERE 'AAAAB0AABAAAAOhAAA' IN (SELECT ROWID FROM TM_INFO_CATALOG);

-- THEN, select the record using the exist rowid
-- SELECT * from TM_INFO_CATALOG WHERE ROWID = %theGivenRowIdWhichExistInThisTable%

我想我需要强调一点:
如果 rowid 与给定的 rowid 匹配,我只想从表(例如 TABLE_A)中选择记录。
当所有给定的 rowid 都来自 TABLE_A(要查询的)时,就可以了。
但是,只要一个给定的 rowid 来自其他表(TABLE_B 或 DUAL,例如),就会出现“ORA-01410 invalid ROWID”。我想解决这个问题。
我希望有人可以运行第四个 SQL(或具有相同模式的另一个 SQL),然后给我你的解决方案。而且,第三条和第四条 SQL 语句除了一个是 SQLID 类型而另一个是 STRING 类型之外,有什么区别?如何解决第四个 SQL 的问题?

4

5 回答 5

4

假设您有“Oracle 呈现”格式的 ROWID,它看起来像这样:

AAACiZAAFAAAAJEAAA

Oracle 格式是 Base64 字符串编码。从 Oracle 中选择一个 ROWID 将导致该值的 Base64 显示。

在此结构中编码了四段数据:

  1. 对象的数据对象编号
  2. 行所在的数据文件(第一个文件是 1)。
  3. 行所在的数据文件中的数据块
  4. 该行在数据块中的位置(第一行为0)

格式为:OOOOOO.FFF.BBBBBB.RRR

  OOOOOO is the object ID
  FFF is the file number
  BBBBBB is the block number
  RRR is the row number

数据文件编号在数据库中是唯一的。您可以从 DBA_DATA_FILES 视图中检索它。每个数据文件都被分成块,dba_extents 表将为您提供记录的段名和段类型。

于 2011-03-04T08:49:12.393 回答
3

您可以使用 JOIN

select * 
from TABLE a 
     join (select chartorowid('AAAEqwAAEAAAAD/AAA') rid from dual) b 
         on b.rid=a.rowid;
于 2011-03-04T20:46:28.453 回答
3

ROWID 是一种特殊的数据类型,而不是字符串。那就是我们需要使用的ROWIDTOCHAR()功能。

由于 ROWID 标识特定表中的特定行,为什么您希望 DUAL 中的 ROWID 匹配任何其他表中的任何内容?

ROWID 是访问行的更快方法。但是需要将 ROWID 作为字符串进行处理是非常不寻常的。更常规的做法是:

declare    
    lv_row_id rowid;
    l_blah t23.whatever%type;
begin
    ....
    select rowid into lv_row_id 
    from t23
    where pk_col = 42;

    do_some_stuff;

    update t23
    set whatever = l_blah
    where rowid = lv_row_id;
    ....

但更正常的是使用 SELECT ... FOR UPDATE 语法,它隐含地使用 ROWID 而我们不必费心。

因此,鉴于您尝试做的事情有点不寻常,我认为您应该更多地解释一下您的目标。这样,我们可以帮助您找到实现目标的最佳方式。

于 2011-03-04T08:19:31.573 回答
2

只是一个提示:

你写了“我不知道给定的 rowid 来自哪里。”。

好吧,DBMS_ROWID.ROWID_OBJECT 会给你对象的 id(然后你可以在 ALL_OBJECTS 视图中找到对象)。

无论如何,似乎虽然没有记录,但每次当您尝试使用一个表中的 rowid 查询另一个表时,您都会收到 ORA-01410 错误。因此,与其试图强迫 oracle 改变其行为,您可以简单地使用一些程序代码来包装您的查询,例如:

BEGIN
   SELECT INFO_ID INTO yourvariable
     FROM TM_INFO_CATALOG  
    WHERE ROWID IN (yourrowid);

   do_something_with_yourvariable;

EXCEPTION
  WHEN invalidrowid THEN
     NULL;
END;
/

或者

BEGIN
   IF DBMS_ROWID.ROWID_OBJECT(:yourrowid) = id_of_TM_INFO_CATALOG THEN
      SELECT INFO_ID INTO yourvariable
        FROM TM_INFO_CATALOG  
       WHERE ROWID IN (yourrowid);

      do_something_with_yourvariable;
   END IF;
END;
/
于 2011-03-04T08:45:18.590 回答
1

听起来您可能正在尝试使用 ROWID 来存储表之间的引用。也许您已将一张表中的 ROWID 存储在另一张表中?

如果是这种情况,这种方法是不正确的。ROWID 是物理指针,可以在不通知的情况下更改。我不知道在任何情况下将 ROWID 作为数据存储在任何表中都是有用的。

表之间的参照完整性应通过存储唯一标识符(即目标表中UNIQUE定义了约束的列)来实现。

于 2011-03-07T07:00:56.103 回答