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池、游標區和其他結構。