註:與3中定一個record相比,一步就完成,而3中定義分二步:a. 所有的成員變數都要申明; b. 執行個體化變數;
5. TABLE類型
答:TYPE tabletype IS TABLE OF type INDEX BY BINARY_INTEGER;
例:DECLARE
TYPE t_StuTable IS TABLE OF Student%ROWTYPE INDEX BY BINARY_INTERGER;
v_Student t_StuTable;
BEGIN
SELECT * INTO v_Student(100) FROM Student WHERE id = 1001;
END;
註:1) 行的數目的限制由BINARY_INTEGER的範圍決定;
1. 條件陳述式
答:IF boolean_expression1 THEN
...
ELSIF boolean_expression2 THEN /*注意是ELSIF,而不是ELSEIF*/
... /*ELSE語句不是必須的,但END IF;是必須的*/
ELSE
...
END IF;
2. 迴圈語句
答:1) Loop
...
IF boolean_expr THEN /* */
EXIT; /* EXIT WHEN boolean_expr */
END IF; /* */
END LOOP;
2) WHILE boolean_expr LOOP
...
END LOOP;
3) FOR loop_counter IN [REVERSE] low_blound..high_bound LOOP
...
END LOOP;
註:a. 加上REVERSE 表示遞減,從結束邊界到起始邊界,遞減步長為一;
b. low_blound 起始邊界; high_bound 結束邊界;
3. GOTO語句
答:GOTO label_name;
1) 只能由內部塊跳往外部塊;
2) 設定標籤:<>
3) 樣本:
LOOP
...
IF D%ROWCOUNT = 50 THEN
GOTO l_close;
END IF;
...
END LOOP;
<>;
...
4. NULL語句
答:在語句塊中加空語句,用於補充語句的完整性。樣本:
IF boolean_expr THEN
...
ELSE
NULL;
END IF;
5. SQL in PL/SQL
答:1) 只有DML SQL可以直接在PL/SQL中使用;
第五章
1. 遊標(CURSOR)
答:1) 作用:用於提取多行資料集;
2) 聲明:a. 普通申明:DELCARE CURSOR CURSOR_NAME IS select_statement /* CURSOR的內容必須是一條查詢語句*/
b. 帶參數申明:DELCARE CURSOR c_stu(p_id student.ID%TYPE) SELECT * FROM student WHERE ID = p_id;
3) 開啟遊標:OPEN Cursor_name; /*相當於執行select語句,且把執行結果存入CURSOR;
4) 從遊標中取數:a. FETCH cursor_name INTO var1, var2, ...; /*變數的數量、類型、順序要和Table中欄位一致;*/
b. FETCH cursor_name INTO record_var;
註:將值從CURSOR取出放入變數中,每FETCH一次取一條記錄;
5) 關閉遊標: CLOSE Cursor_name;
註:a. 遊標使用後應該關閉;
b. 關閉後的遊標不能FETCH和再次CLOSE;
c. 關閉遊標相當於將記憶體中CURSOR的內容清空;
3. 遊標的FETCH迴圈
答:1) LOOP
FETCH cursor INTO ...
EXIT WHEN cursor%NOTFOUND; /*當cursor中沒記錄後退出*/
END LOOP;
2) WHILE cursor%FOUND LOOP
FETCH cursor INTO ...
END LOOP;
3) FOR var IN cursor LOOP
FETCH cursor INTO...
END LOOP;
第六章
1. 異常
答:DECLARE
...
e_TooManyStudents EXCEPTION; /* 申明異常 */
...
BEGIN
...
RAISE e_TooManyStudents; /* 觸發異常 */
...
EXCEPTION
WHEN e_TooManyStudents THEN /* 觸發異常 */
...
WHEN OTHERS THEN /* 處理所有其他異常 */
...
END;
2. 預存程序例子
答:CREATE OR REPLACE PROCEDURE ModeTest(
p_InParm IN NUMBER,
p_OutParm OUT NUMBER,
p_InOutParm IN OUT NUMBER)
IS
v_LocalVar NUMBER; /* 聲明部分 */
BEGIN
v_LocalVar:=p_InParm; /* 執行部分 */
p_OutParm:=7;
p_InOutParm:=7;
...
EXCEPTION
... /* 異常處理部分 */
END ModeTest;
cursor_declaration
END pack_name;
3) 樣本:
CREATE OR REPLACE PACKAGE pak_test AS
PROCEDURE RemoveStudent(p_StuID IN students.id%TYPE);
TYPE t_StuIDTable IS TABLE OF students.id%TYPE INDEX BY BINARY_INTEGER;
END pak_test;
3. 包主體
答:1) 包主體是可選的,如包頭中沒有任何函數與過程,則包主體可以不需要。
2) 包主體與包頭存放在不同的資料字典中。
3) 如包頭編譯不成功,包主體無法正確編譯。
4) 包主體包含了所有在包頭中聲明的所有過程與函數的代碼。
5) 樣本:
CREATE OR REPLACE PACKAGE BODY pak_test AS
PROCEDURE RemoveStudent(p_StuID IN students.id%TYPE) IS
BEGIN
...
END RemoveStudent;
TYPE t_StuIDTable IS TABLE OF students.id%TYPE INDEX BY BINARY_INTEGER;
END pak_test;
1. 觸發器
答:1) 觸發器與過程/函數的相同點
a. 都是帶有名字的執行塊;
b. 都有聲明、執行體和異常部分;
2) 觸發器與過程/函數的不同點
a. 觸發器必須儲存在資料庫中;
b. 觸發器自動執行;
2. 建立觸發器
答:1) 文法:
CREATE [OR REPLACE] TRIGGER trigger_name
{BEFORE|AFTER} triggering_event ON table_reference
[FOR EACH ROW [WHEN trigger_condition]]
trigger_body;
2) 範例:
CREATE OR REPLACE TRIGGER UpdateMajorStats AFTER INSERT OR DELETE OR UPDATE ON students
DECLARE
CURSOR c_Statistics IS
SELECT * FROM students GROUP BY major;
BEGIN
...
END Up;
3. 觸發器
答:1) 三個語句(INSERT/UPDATE/DELETE);
2) 二種類型(之前/之後);
3) 二種層級(row-level/statement-level);
所以一共有 3 X 2 X 2 = 12
很多朋友在Java開發中,使用Oracle資料庫的時候,經常會碰到有ORA-01000: maximum open cursors exceeded.的錯誤。
實際上,這個錯誤的原因,主要還是代碼問題引起的。
ora-01000: maximum open cursors exceeded.
表示已經達到一個進程開啟的最大遊標數。
這樣的錯誤很容易出現在Java代碼中的主要原因是:Java代碼在執行conn.createStatement()和conn.prepareStatement()的時候,實際上都是相當與在資料庫中開啟了一個cursor。尤其是,如果你的createStatement和prepareStatement是在一個迴圈裡面的話,就會非常容易出現這個問題。因為遊標一直在不停的開啟,而且沒有關閉。
一般來說,我們在寫Java代碼的時候,createStatement和prepareStatement都應該要放在迴圈外面,而且使用了這些Statment後,及時關閉。最好是在執行了一次executeQuery、executeUpdate等之後,如果不需要使用結果集(ResultSet)的資料,就馬上將Statment關閉。
對於出現ORA-01000錯誤這種情況,單純的加大open_cursors並不是好辦法,那隻是治標不治本。實際上,代碼中的隱患並沒有解除。
而且,絕大部分情況下,open_cursors只需要設定一個比較小的值,就足夠使用了,除非有非常特別的要求。
(5)在store procedure中執行 DDL語句
一是:execute immediate 'update '||table_chan||' set '||column_changed||' = '''||v_trans_name||''' where empid = '''||v_empid||'''' ;
二是:The DBMS_SQL package can be used to execute DDL statements directly from PL/SQL.
2 如何找資料庫表的主鍵欄位的名稱?
SQL>SELECT * FROM user_constraints
WHERE CONSTRAINT_TYPE='P' and table_name='TABLE_NAME';
3 如何查詢資料庫有多少表?
SQL>select * from all_tables;
4 使用sql統配符
萬用字元 描述 樣本 % 包含零個或更多字元的任一字元串。 WHERE title LIKE '%computer%' 將尋找處於書名任意位置的包含單詞 computer 的所有書名。 _(底線) 任何單個字元。 WHERE au_fname LIKE '_ean' 將尋找以 ean 結尾的所有 4 個字母的名字(Dean、Sean 等)。 [ ] 指定範圍 ([a-f]) 或集合 ([abcdef]) 中的任何單個字元。 WHERE au_lname LIKE '[C-P]arsen' 將尋找以arsen 結尾且以介於 C 與 P 之間的任何單個字元開始的作者姓氏,例如,Carsen、Larsen、Karsen 等。 [^] 不屬於指定範圍 ([a-f]) 或集合 ([abcdef]) 的任何單個字元。 WHERE au_lname LIKE 'de[^l]%' 將尋找以 de 開始且其後的字母不為 l 的所有作者的姓氏。
5使普通使用者有查看v$Session的許可權
GRANT SELECT
ON "SYS"."V_$OPEN_CURSOR" TO "SFISM4";
GRANT SELECT
ON "SYS"."V_$SESSION" TO "SFISM4";
常用函數
distinct
去掉重複的
minus 相減
在第一個表但不在第二個表
SELECT * FROM FOOTBALL MINUS SELECT * FROM SOFTBALL;
intersect 相交
INTERSECT 返回兩個表中共有的行。
SELECT * FROM FOOTBAL;
UNION ALL 與UNION 一樣對錶進行了合并但是它不去掉重複的記錄。
彙總函數
count
select count(*) from test;
SUM
SUM 就如同它的本意一樣它返回某一列的所有數值的和。
SELECT SUM(SINGLES) TOTAL_SINGLES FROM TEST;
SUM 只能處理數字如果它的處理目標不是數字你將會收到如下資訊
輸入/輸出
SQL>SELECT SUM(NAME) FROM TEAMSTATS;
ERROR
ORA-01722 invalid number
no rows selected
該錯誤資訊當然的合理的因為NAME 欄位是無法進行匯總的。
AVG
AVG 可以返回某一列的平均值。
SELECT AVG(SO) AVE_STRIKE_OUTS FROM TEAMSTATS;
MAX
如果你想知道某一列中的最大值請使用MAX。
SELECT MAX(HITS) FROM TEAMSTATS;
MIN
MIN 與MAX 類似它返回一列中的最小數值。
VARIANCE
VARIANCE 方差不是標準中所定義的但它卻是統計領域中的一個至關重要的數值。
SELECT VARIANCE(HITS) FROM TEAMSTATS;
STDDEV
這是最後一個統計函數STDDEV 返回某一列數值的標準差。
SELECT STDDEV HITS FROM TEAMSTATS;
日期時間函數
ADD_MONTHS
ADD_MONTHS也可以工作在select 之外
該函數的功能是將給定的日期增加一個月舉例來說由於一些特殊的原因上述的計劃需要延遲兩個月那麼就用到了。
LAST_DAY
LAST_DAY 可以返回指定月份的最後一天.
MONTHS_BETWEEN
如果你想知道在給定的兩個日期中有多少個月可以使用MONTHS_BETWEEN。
select task, startdate, enddate ,months between(Startdate,enddate) duration from project;
返回結果有可能是負值.
可以利用負值來判斷某一日期是否在另一個日期之前下例將會顯示所有在1995 年5 月19 日以前開始的比賽.
SELECT * FROM PROJECT
WHERE MONTHS_BETWEEN ('19-MAY-95', STARTDATE)>0;
NEW_TIME
如果你想把時間調整到你所在的時區你可以使用NEW_TIME.
SQL>SELECT ENDDATE EDT, NEW_TIME('ENDDATE',' EDT',' PDT') FROM PROJECT;
NEXT_DAY
NEXT_DAY 將返回與指定日期在同一個星期或之後一個星期內的你所要求的星期天
數的確切日期如果你想知道你所指定的日期的星期五是幾號可以這樣做.
SQL>SELECT STARTDATE, NEXT_DAY(STARTDATE,' FRIDAY') FROM PROJECT;
SYSDATE
SYSDATE 將返回系統的日期和時間。
SELECT DISTINCT SYSDATE FROM PROJECT;
數學函數
ABS
ABS 函數返回給定數位絕對值
CEIL 和FLOOR
CEIL 返回與給定參數相等或比給定參數在的最小整數.FLOOR 則正好相反它返回
與給定參數相等或比給定參數小的最大整數.
COS COSH SIN SINH TAN TANH
COS SIN TAN 函數可以返回給定參數的三角函數值預設的參數認定為弧度制.
EXP
EXP 將會返回以給定的參數為指數以e 為底數的冪.
LN and LOG
這是兩個對數函數其中LN 返回給定參數的自然對數.
MOD
知道在ANSI 標準中規定模數運算的符號為%在一些解譯器中被函數MOD 所取代.
POWER
該函數可以返回某一個數對另一個數的冪在使用冪函數時第一個參數為底數第二個為指數。
SIGN
如果參數的值為負數那麼SIGN 返回-1 如果參數的值為正數那麼SIGN 返回1,如果參數為零那麼SIGN 也返回零.
SQRT
該函數返回參數的平方根,由於負數是不能開平方的所以我們不能將該函數應用於負數.
字元函數
CHR
該函數返回與所給數值參數等當的字元返回的字元取決於資料庫所依賴的字元集.
CONCAT
和||一個作用,把兩個字串串連起來.
INITCAP
該函數將參數的第一個字母變為大寫此外其它的字母則轉換成小寫.
LOWER 和UPPER
如你所料LOWER 將參數轉換為全部小寫字母而UPPER 則把參數全部轉換成大寫字母.
LPAD 與RPAD
這兩個函數最少需要兩個參數最多需要三個參數每一個參數是需要處理的字串
第二個參數是需要將字串擴充的寬度第三個參數表示加寬部分用什麼字元來做填補
第三個參數的預設值為空白格但也可以是單個的字元或字串.
LTRIM 與RTRIM
LTRIM 和RTRIM至少需要一個參數最多允許兩個參數第一個參數與LPAD 和RPAD
類似是一個字串第二個參數也是一個字元或字串預設則是空格如果第二個
數不是空格的話那麼該函數將會像剪除空格那樣剪除所指定的字元.
REPLACE
它的工作就如果它的名字所說的那樣該函數需要三個參數第一個參數是需要搜尋
的字串(列名),第二個參數是搜尋的內容第三個參數則是需要替換成的字串如果第三個
參數省略或者是NULL 那麼將只執行搜尋操作而不會替換任何內容.
SUBSTR
這個函數有三個參數允許你將目標字串的一部份輸出,第一個參數為目標字串,
第二個字串是將要輸出的子串的起點,第三個參數是將要輸出的子串的長度。
如果第二個參數為負數那麼將會從源串的尾部開始向前定位至負數的絕對值的位置。
TRANSLATE
這一函數有三個參數,目標字串、源字串和目的字串,在目標字串與源字元
串中均出現的字元將會被替換成對應的目的字串的字元。
INSTR
如果需要知道在一個字串中滿足特定的內容的位置可以使用INSTR ,它的第一個參
數是目標字串,第二個參數是匹配的內容,第三和第四個參數是數字用以指定開始搜
索的起點以及指出第幾個滿足條件的將會被返回。
LENGTH
LENGTH將返回指定字串的長度。
轉換函式
轉換函式有三個可以使你方便地將資料從一種類型變換為另一種類型。
TO_CHAR
該函數的最初功能是將一個數字轉換為字元型,不同的解譯器可能會使用它來轉換其它的
資料類型例如日期型轉換為字元型或者是擁有更多的參數。
TO_NUMBER
該函數與TO_CHAR 函數相對應顯而易見它是將一個字串型數字轉換為數值型。
其他函數
GREATEST 與LEAST
這兩個函數將返回幾個運算式中最大的和最小的。
SELECT GREATEST(‘ALPHA’,‘ BRAVO’,‘ FOXTROT’,‘ DELTA’) FROM CONVERT;
看來有必要使用FROM 子句可是如果FROM 子句沒有的話你將會收到一個錯誤資訊每
一個SELECT 語句都需要FROM 子句。
USER
該函數返回當前使用資料庫的使用者的名字