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%

この点を強調する必要があると思い
ます。行 ID が指定された行 ID と一致する場合、テーブル (TABLE_A など) からレコードを選択するだけです。
指定されたすべての行 ID が (クエリ対象の) TABLE_A に由来する場合、問題ありません。
ただし、1 つの行 ID が他のテーブル (TABLE_B または DUAL など) から取得されている限り、「ORA-01410 無効な ROWID」が発生しました。この問題を修正したい。
誰かが 4 番目の SQL (または同じパターンの別の SQL) を実行して、解決策を教えてください。また、3 番目と 4 番目の SQL ステートメントの違いは、一方が SQLID 型で、もう一方が STRING 型であることを除いて何ですか? 4 番目の SQL の問題を解決するには?

4

5 に答える 5

4

ROWID が「Oracle 提示」形式であると仮定すると、次のようになります。

AAACiZAAFAAAAJEAAA

Oracle 形式は Base64 文字列エンコーディングです。Oracle から ROWID を選択すると、Base64 で値が表示されます。

4 つのデータがこの構造でエンコードされます。

  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 テーブルはレコードの segment_name と segment_type を提供します。

于 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エラーが発生するようです。したがって、オラクルの動作を強制的に変更する代わりに、次のような手続き型コードでクエリをラップするだけです。

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 に答える