Oracle資料庫常見問題答疑
最後更新:2017-02-28
來源:互聯網
上載者:User
oracle|資料|資料庫|問題 Oracle資料庫以其強大的功能和穩定性而著稱,但同時,在開發和管理方面也存在很多困難,筆者在此總結了一些Oracle資料庫開發和管理的常見問題,希望能對大家有所協助。
問:如果發現表中有壞塊,如何檢索其它未壞的資料?
答:首先需要找到壞塊的ID(可以運行dbverify實現),假設為1234。運行下面的查詢尋找段名:
select segment_name, segment_type, block_id, blocks
from dba_extents
where (1234 between block_id and (block_id + blocks - 1));
一旦找到壞段名稱,若段是一個表,則最好建立一個暫存資料表,存放好的資料。若段是索引,則刪除它,再重建。
create table good_table
as
select from bad_table where rowid not in
( select /+index(bad_table, any_index)/ rowid
from bad_table where substr( rowid, 1, 8 ) = 1234)
問:如請問如何關閉FORM調用REPORT時的小視窗?
答:在利用Oracle資料庫的Develop 2000設計開發介面的過程中,當FORM調用REPORT時,會顯示一個背景視窗REPORT BACKGROUD ENGINE,等待FORM對REPORT的調用,當FORM調用其它REPORT時,也使用這個後台伺服器,不論調用多少個REPORT,這個後台伺服器存在且只有一個。但當FORM與REPORT全部退出後,該視窗仍處於等待狀態,不會關閉,這時,我們需要手工將其關閉。
我們可以使用以下參數在FORM調用REPORT時不顯示這個小視窗:
Add_Parameter( pl_id, 'ORACLE_SHUTDOWN',TEXT_Parameter, 'Yes' );
需要注意的是,該參數必須加在所有參數的前面,即它必須為第一個參數。
問:請問如何根據查詢條件在REPORT中動態顯示記錄?
答:1. 在REPORT的“資料模型”下面的“使用者參數”中,建立使用者自訂參數W_CLAUSE,W_CLAUSE為從FORM傳遞過來的查詢條件,資料類型為字元型,預設值為NULL。
2. 修改查詢Q_1,將SQL查詢語句修改為select from dept &&w_clause。
3. 在運行報表時,報表會自動將符合&&w_clause的查詢條件記錄顯示出來。
如果從FORM傳遞過來的w_clause為where dept=1,本報表的SQL查詢自動轉換為select from dept where dept=1,並在報表運行結果中顯示符合該查詢條件的記錄,如果從FORM傳遞過來的w_cluase為where to_char(年度,'YYYY.MM')='2000.03',則在報表運行結果中自動顯示2000年3月份的記錄。
問:在Oracle中,我們如何查看某表上的約束?
答:我們可以使用下面語句從all_constraints視圖中查看某表上的約束:
SELECT constraint_name, table_name, r_owner, r_constraint_name
FROM all_constraints
WHERE table_name = 'table_name' and owner = 'owner_name';
另一個視圖ALL_CONS_COLUMNS也包括組成表上約束列的資訊。
問:如何將資料庫從noarchivelog方式改變為archivelog方式?
答:首先開啟Init.ora檔案,確儲存檔日誌目標指向一有效目錄。
然後啟動Server Manager
svrmgrl〉 shutdown immediate
svrmgrl〉 startup mount
svrmgrl〉 alter database archivelog;
svrmgrl〉 alter database open;
svrmgrl〉 archive log list;
在init.ora中設定參數archive_log_start=TRUE,它設定存檔日誌為自動啟動。在Oracle 8i中支援多個存檔日誌的目標,因此參數修改為log_archive_dest[n],其中n為1到5。
問:在Oracle資料庫中,我們如何增加資料表空間的大小?
答: 在開發Oracle資料庫中,我們有兩種方法增加資料表空間的大小:
1.增加額外的資料檔案到資料表空間中
例如:alter tablespace users add datafile '/u01/oradata/orcl/users02.dbf' size 25m;
2.修改資料表空間當前的資料檔案
例如:alter database datafile
'/u01/oradata/orcl/users01.dbf' resize 50M;
問:請問如何在REPORT中設定動態顯示域?
答:在REPORT中設定動態顯示域的方法如下:
1. 在REPORT的“資料模型”下面的“使用者參數”中,建立使用者自訂參數,如RQ,RQ是從FORM傳遞過來的顯示日期,資料類型為字元型。
2. 在布局模型中,建立一個顯示域F_1,在屬性選項板中修改該顯示域的源為使用者自訂參數RQ,並且設為“不可見的”。
3. 在動態預覽中,建立一個文本域D_1,調整該文本域的位置和寬度,在該域的內容中輸入&&F_1,則該域會動態顯示使用者定義參數RQ的值。
問:有關口令
我在Solaris系統上運行 Oracle8i 8.1.7企業版。我建立了兩個資料庫:SUGAR和TestDb。將兩者的remote_login_passwordfile都設定為 “獨佔(exclusive)”。我試圖以SYSDBA身份串連到TestDb,但未能成功。下面是我的做法:
$sqlplus /nolog
SQL> conn sys/change_on_install@testdb
Connected.(已串連)
SQL> select * from v$pwfile_users;
username sysdb sysop
-----------------------------------------
internal true true
sys true true
SQL> conn sys/change_on_install@testdb as
sysdba
ERROR(錯誤)
ORA-01017: invalid username/password; logon
denied(無效的使用者名稱/口令,登入被拒絕)
Warning: You are on longer connected to
ORACLE(警告:你已經與ORACLE中斷連線)
我為什麼不能以SYSDBA身份串連到TestDb?
答:通常Oracle中的SYS口令與INTERNAL口令是同步的,SYS口令儲存於口令檔案中。在上述情況下你建立了包含有一個口令的口令檔案,而不是使用預設的 “change_on_install,”這就是問題之所在。
希望下面的方法對你有所協助。首先,建立一個口令檔案,其中包含一個口令,這個口令不要與系統口令匹配:
$ orapwd file=orapw password=foobar
entries=40
然後,進入伺服器,啟動資料庫:
$ svrmgr
SVRMGR> connect internal
Connected.(已串連)
SVRMGR> startup
ORACLE instance started.(ORACLE 執行個體已啟動)
Total System Global Area (系統全域地區大小)
193073136 bytes
Fixed Size (固定大小)
69616 bytes
Variable Size (可變大小)
141639680 bytes
Database Buffers (資料庫緩衝區)
45056000 bytes
Redo Buffers (重做緩衝區)
6307840 bytes
Database mounted. (資料庫已載入)
Database opened.資料庫已開啟。
現在使用SYS使用者的口令,以SYS身份串連:
SVRMGR> connect sys/change_on_install@ora81
Connected.(已串連)
成功了。現在試著以SYSDBA身份串連:
SVRMGR> connect sys/change_on_install@ora81
as sysdba;
ORA-01017: invalid username/password; logon
denied(無效的使用者名稱/口令;登入被拒絕)
這裡出現了你所說的錯誤。你的SYS口令為:change_on_install,但口令檔案中的口令卻是foobar。SYS使用者是專用的,以SYSDBA身份串連就像是以INTERNAL串連,你必須使用口令檔案中的口令。試試這樣做:
SVRMGR— connect sys/foobar@ora81 as sysdba;
Connected.(已串連)
並不是每個人都需要使用口令檔案中的口令;使用者需要使用他們自己的口令。通過授權SYSDBA給SCOTT,你就可以明白這一點:
SVRMGR> grant sysdba to scott;
Statement processed.(已處理)
這個命令將SCOTT以SCOTT的憑證加入到口令檔案中。如果你改變了SCOTT的口令,口令檔案也會自動同步改變。現在,你可以試試以SYSDBA身份串連SCOTT了:
SVRMGR> connect scott/tiger@ora81 as sysdba;
Connected.(已串連)
一切正常。現在可以使用ALTER USER 命令來改變SYS使用者的口令。
SVRMGR> alter user sys identified by
change_on_install;
Statement processed.(已成功更改)
SVRMGR≫ connect sys/change_on_install@ora81
as sysdba;
Connected.(已串連)
你還可以用change_on_install,因為改變SYS使用者口令將同時改變口令檔案中的口令。當你建立了口令檔案後,Oracle資料庫在其中放入兩個帳號:SYS和INTERNAL,並將你在命令列中提供的口令作為這兩個賬戶的口令。當你改變資料庫中的SYS使用者口令時,資料庫將衝掉口令檔案中的SYS和INTERNAL口令。下面操作將顯示口令foobar已經是無效的了:
SVRMGR> connect sys/foobar@ora81 as sysdba;
ORA-01017: invalid username/password; logon
denied(無效的使用者名稱/口令,登入被拒絕)
問:利用QUERY選項輸出資料
我知道在Oracle8i中,可以使用QUERY有選擇地輸出表資料。我想用EXP命令來實現,但沒有成功。下面是我所寫的命令,以及得到的錯誤資訊:
exp ddd/ddd file=/dbf/u11/customer.dmp
tables=AASC.AST_CUSTOMER_KEEP
query=\'where CUA_TRANS_DTS \<
add_months\(sysdate, -6\)\'
table_export[2]: CUA_TRANS_DTS: not found.(沒有找到)
答:作業系統不同,用來指定QUERY=參數的方法也不同。WHERE 語句裡面往往有很多特殊的字元,如=.>.<和空格等等。而UNIX和Windows作業系統中的外殼命令提示是不歡迎這些字元的,這些字元將被忽略。你應該根據不同的作業系統採用不用的方法。我一般使用帶有QUERY選項的參數檔案(PARFILE),利用PARFILE,可以不考慮作業系統平台而使用完全相同的方法。
下面給出一個例子。我用select * from all_objects建立了一個表T,我希望輸出所有object_id 小於5000的行。在Windows中,必須這樣做:
C:\exp>exp userid=tkyte/tkyte tables=t
query="""where object_id < 5000"""
注意:在windows中,需要在WHERE語句的兩端使用三個雙引號。在UNIX中,必須這樣做:
$ exp userid=/ tables=t query=\"where
object_id \< 5000\"
exp userid=/ tables=t parfile=exp.par
如果使用包含query="where object_id < 5000"的PARFILE檔案,我可以在兩個系統中使用相同的一個命令:
exp userid=/ tables=t parfile=exp.par
在兩種作業系統中,完全相同。這相對於在不同的平台中使用不同的QUERY字串容易多了。
問:DBMS_RANDOM
您能否告訴我寫一個能產生大於0小於1的隨機數的隨機數產生器的最好方法?
答:Oracle8 8.0版介紹了DBMS_RANDOM包,Oracle8i 8.1.6版介紹了DBMS_RANDOM包的新功能,但Oracle8i 文檔中沒有詳細全面介紹其功能。幸運的是:有一個新的DBMS_RANDOM包函數能夠返回0-1之間的隨機數。這個新函數是:
FUNCTION value RETURN NUMBER;
FUNCTION value (low IN NUMBER, high IN
NUMBER) RETURN NUMBER;
FUNCTION normal RETURN NUMBER;
FUNCTION string (opt char, len NUMBER)
RETURN VARCHAR2;
VALUE函數的第一種形式返回一個大於或等於0且小於1的隨機數;第二種形式返回一個大於或等於LOW,小於HIGH的隨機數。下面是其用法的一個樣本:
SQL> select dbms_random.value,
dbms_random.value(55,100)
2 from dual;
VALUE DBMS_RANDOM.VALUE(55,100)
--------------- -----------------------------
.782821936 79.6367038
NORMAL函數返回服從常態分佈的一組數。此常態分佈標準差為1,期望值為0。這個函數返回的數值中有68%是介於-1與+1之間,95%介於-2與+2之間,99%介於-3與+3之間。事實上,這就是你在清單1中所看到的。
最後,是STRING函數。它返回一個長度達60個字元的隨機字串。參數OPT可以是清單2顯示的值中的任何一個單個字元。
關於這些函數及DBMS_RANDOM包的檔案都包含在SQLPlus中:
select text
from all_source
where name = 'DBMS_RANDOM'
and type = 'PACKAGE' order by line;
問:串連次序與謂詞求值
在下面的查詢中,WHERE 語句的哪一部分先執行?
Select field names from emp, dept
where emp.dept_num = dept.num and
emp.name Like 'S%' and dept.name='IT';
答:執行次序隨已有的索引、統計、和session/init.ora參數的不同而變化。
假定已有一個建立在DEPT(name)和EMP(dept_num)上的索引。假定最佳化器認為DEPT是唯一的,它可能按下面的順序進行操作:
利用建立在DEPT(name)上的索引尋找dept列
利用建立在EMP(dept_num)上的索引尋找匹配的emp列(即串連emp.dept_num = dept.num)
依據建立在emp.ename like 'S%'進行過濾
現在,我們假定沒有建立在EMP(dept_num)上的索引,也沒有建立在DEPT(name)上的索引,而存在建立在EMP(name)和DEPT(num)上的索引。最佳化器可能按下面的次序進行操作:
利用建立在EMP(name)上的索引找到帶有S的EMPS
利用建立在DEPT(num)上的索引找到匹配項
根據dept.name = 'IT'過濾結果
謂詞求值的次序是不確定的,可以隨時間的改變而改變,並由最佳化器決定。不要假定任何事情會按一定的次序發生。如果你那麼做,隨著時間的推移,你的應用程式可能會出現一些看起來非常奇怪的錯誤。看以下的例子:建立一個表,輸入一些資料。當X='a’時,第二列的資料“Y”是一個數值,當X='b’時,“Y”不是數字。
SQL> create table t ( x varchar2(1), y varchar2(1) );
Table created.
SQL> insert into t values ( 'a', '1' );
1 row created.
SQL> insert into t values ( 'b', 'x' );
1 row created.
現在根據這個表運行一個查詢:尋找滿足x='a',y=1的行。
SQL> select * from t where x = 'a' and
y = 1;
ERROR:
ORA-01722: invalid number
no rows selected(錯誤,無效的數字,沒有選擇任何行)
呦,沒有成功。在這種情況下,資料庫首先執行Y=1,當找到Y='X'的行後,很顯然,它不能將'X'轉換為一個數字,所以失敗了。而下面的程式將給出不同的結果:
SQL> analyze table t compute statistics;
Table analyzed.(表已經分析過)
SQL> select * from t where x = 'a' and
y = 1;
X Y
- -
a 1
使用不同的最佳化器模式,成功了!為什嗎?最佳化器說:“嘿,檢查x= 'a'要比檢查y=1來得快,因為在y=1中有一個將y從字元變為數位轉換。所以,我先檢查x= 'a',然後再檢查y=1。”
這個例子說明謂詞執行的次序可能是不確定的,你不能指望有一種特定的執行次序。也就是說,當你依靠一個隱含的轉換時,必須非常謹慎。
問:顯示SGA--fixed size(固定大小)與variable size(可變大小)
當在svrmgr提示符下運行 “show SGA”時,fixed size和variable size是什麼意思?
答:fixed size就是SGA中固定組件(它在編譯oracle 資料庫本身時就固定於其中)的大小。它是固定大小的記憶體,用來指向SGA的其它部分。SGA這一部分的大小是不能改變的。
variable size指分配的記憶體塊大小可變。SGA的可變塊,分為共用池、大池、JAVA池、遊標區和其他結構。