2011-03-04 92 views
1

任何人都可以幫我解決FIXME嗎?如何從表(Oracle)中獲取給定rowid列表中的記錄IN STRING?

-- 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% 

我想我需要強調點:
我只是想從一個表(如TABLE_A)選擇的記錄,如果rowid給定rowid的匹配。
當所有給定的rowid來自TABLE_A(要查詢)時,那麼它是正確的。
但是,只要給出一個rowid來自其他表(如TABLE_B或DUAL等),則會發生「ORA-01410無效的ROWID」。我想修正這個問題。
我希望有人可以運行第四個SQL(或使用相同模式的其他SQL),然後給我你的解決方案。 而且,第三個和第四個SQL語句除了一個是SQLID類型而另一個是STRING類型之外還有什麼區別?如何解決第四個SQL的問題?

+0

您使用的是哪個版本的Oracle?我沒有在11.2.0.1.0上運行您的代碼時出現任何錯誤。 – 2011-03-05 02:25:03

回答

2

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; 
    .... 

但更正常的是使用the SELECT ... FOR UPDATE syntax,其中隱含使用ROWID沒有我們不必理會。

所以,鑑於你想要做的事情有點不尋常,我想你應該多解釋一下你的目標。這樣我們可以幫助您找到實現它們的最佳方式。

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; 
/
+0

好吧,實際上,我並不關心給定的ROWID來自何處。反正, – btpka3 2011-03-04 10:34:33

+0

,謝謝。 – btpka3 2011-03-04 11:34:16

3

假設你有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表將爲您提供記錄的segment_name和segment_type。

+0

感謝您解釋ROWID是什麼。但我認爲不是我正在尋找的東西。我想通過給定的ROWID(可能來自其他表)計算表中的記錄 – btpka3 2011-03-04 11:07:09

1

您可以使用JOIN

select * 
from TABLE a 
    join (select chartorowid('AAAEqwAAEAAAAD/AAA') rid from dual) b 
     on b.rid=a.rowid; 
+0

此SQL可用於替換第5個SQL,並具有更好的性能。 – btpka3 2011-03-05 03:29:02

1

這聽起來像你可能會試圖使用的ROWID存儲表之間的引用。也許你已經從另一個表中的一個表中存儲了ROWID?

如果是這種情況,這種方法是不正確的。 ROWID是物理指針,可以在沒有通知的情況下更改。我沒有意識到將ROWIDs作爲數據存儲在任何表中的情況。

表之間的參照完整性應該通過存儲一個唯一標識符(即來自目標表的已定義約束條件的一列或多列)來實現。

+0

是的,但我有一個案例來存儲許多其他表中的rowid。那麼我需要用rowid從這些表中挑出記錄。由於每個表的主鍵都是不同的,因此存儲PK可能是更好的選擇。如果數據從一個遷移到另一個,或者正在執行'TRUNCATE TABLE ...',則需要更新新的rowid。 – btpka3 2011-03-08 11:52:57

+0

@ btpka3,不幸的是你的方法不起作用。就那麼簡單。 ROWID可以改變,並且沒有方法可以檢測到並更新所有的引用。您需要存儲每個表中主鍵的值。 – 2011-03-09 01:19:07

相關問題