sql 與Oracle對比

網上已經有很多SQL與ORACLE的對比 ,但本人要講的即不是單純的SQL,也不是單純的ORACLE,更不是評價誰好誰壞(意思不大),而是兩種數據庫之相同和異同,本人曾講授過SQL與ORACLE的課程,講SQL時說SQL好,講ORACLE時又說ORACLE棒,現在終於可以平心而評啦。
估計有人現在會嘿嘿冷笑(又一個誤人子弟的騙子),老實說,當初每次講完課,就有這種感覺—教的人不得其法,學的人不得其道。說點嚴肅的事吧,據說比爾與艾里森在洗手間相遇,兩個又是擁抱,又是KISS,不多久就吵了起來,比爾對查詢分析器(SQL QUERY ANALYZE)贊不經絕口,艾里森嘿嘿冷笑,只說了一句話—SQL PLUS內秀。
言歸正傳,且聽我一一道來


001、SQL與ORACLE的內存分配
ORACLE的內存分配大部分是由INIT.ORA來決定的,一個數據庫實例可以有N種分配方案,不同的應用(OLTP、OLAP)它的配置是有側重的。SQL概括起來說,只有兩種內存分配方式:動態內存分配與靜態內存分配,動態內存分配充許SQL自己調整需要的內存,靜態內存分配限制了SQL對內存的使用。
002、SQL與ORACLE的物理結構


總得講,它們的物理結構很相似,SQL的數據庫相當於ORACLE的模式(方案),SQL的文件組相當於ORACLE的表空間,作用都是均衡DISK I/O,SQL創建表時,可以指定表在不同的文件組,ORACLE則可以指定不同的表空間。
CREATE TABLE A001(ID DECIMAL(8,0)) ON [文件組]
--------------------------------------------------------------------------------------------
CREATE TABLE A001(ID NUMBER(8,0)) TABLESPACE 表空間
注:以後所有示例,先SQL,後ORACLE


003、SQL與ORACLE的日誌模式
SQL對日誌的控制有三種恢復模型:SIMPLE、FULL、BULK-LOGGED;ORACLE對日誌的控制有二種模式:NOARCHIVELOG、ARCHIVELOG。SQL的SIMPLE相當於ORACLE的NOARCHIVELOG,FULL相當於ARCHIVELOG,BULK-LOGGED相當於ORACLE大批量數據裝載時的NOLOGGING。經常有網友抱怨SQL的日誌龐大無比且沒法處理,最簡單的辦法就是先切換到SIMPLE模式,收縮數據庫後再切換到FULL,記住切換到FULL之後要馬上做完全備份。


004、SQL與ORACLE的備份類型
SQL的備份類型分的極雜:完全備份、增量備份、日誌備份、文件或文件組備份;ORACLE的備份類型就清淅多啦:物理備份、邏輯備份;ORACLE的邏輯備份(EXP)相當於SQL的完全備份與增量備份,ORACLE的物理備份相當於SQL的文件與文件組備份。SQL的各種備份都密切相關,以完全備份爲基礎,配合其它的備份方式,就可以靈活地備分數據;ORACLE的物理備份與邏輯備份各司其職。SQL可以有多個日誌,相當於ORACLE日誌組,ORACLE的日誌自動切換並歸檔,SQL的日誌不停地膨脹……SQL有附加數據庫,可以將數據庫很方便地移到別一個服務器,ORACLE有可傳輸表空間,可操作性就得注意啦。

005、SQL與ORACLE的恢復類型
SQL有完全恢復與基於時間點的不完全恢復;ORACLE有完全恢復與不完全恢復,不完全恢復有三種方式:基於取消的、基於時間的、基於修改的(SCN)的恢復。不完全恢復可以恢復數據到某個穩定的狀態點。


006、SQL與ORACLE的事務隔離
SET TRANSACTION ISOLATION LEVEL
SQL有四種事務隔離級別:
READ COMMITTED、READ UNCOMMITTED、REPEATABLE READ、SERIALIZABLE
ORACLE有兩種事務隔離級別
READ COMMITTED、SERIALIZABLE
SQL雖然有四種事務隔離,事務之間還是經常發生阻塞;ORACLE則利用回退段很好地實現了事務隔離,不會產生阻塞。SQL與ORACLE如果發生死鎖,都可以很快地識別並將之處理掉。


007 SQL與ORACLE的外鍵約束
SQL的外鍵約束可以實現級聯刪除與級聯更新,ORACLE則只充許級聯刪除。
CREATE TABLE A001(ID INT PRIMARY KEY,NAME VARCHAR(20))
CREATE TABLE A002(ID INT REFERENCES A001(ID)ON DELETE CASCADE ON UPDATE CASCADE,AGE TINYINT)
CREATE TABLE A001(ID INT PRIMAY KEY,NAME VARCHAR2(20))
CREATE TABLE A002(ID INT REFERENCES A001(ID)ON DELETE CASCADE,AGE NUMBER(2,0))
008、SQL與ORACLE的臨時表


SQL的臨時表用#或##開頭,使用完後自動釋放,ORACLE的臨時表則存在數據庫中,每個會話的數據都互不干涉。oracle臨時表中的紀錄可以被定義爲自動刪除(分commit方式和transaction方式),而表結構不會被自動刪除。臨時表的DML,DDL操作和標準表一樣。
CREATE TABLE #TEMP(ID INT,NAME VARCHAR(20))
-------------------------------------------------------
CREATE GLOBAL TEMPORARY TABLE TEMP(ID INT,VARCHAR2(20))


009、SQL與ORACLE的類型轉換
SQL常用類型轉換函數有:CAST、CONVERT、STR
ORACLE常用類型轉換函數有:TO_CHAR、TO_NUMBER、TO_DATE
SELECT CONVERT(VARCHAR(20),GETDATE(),112)
------------------------------------------------------------------------------------------------
SELECT TO_CHAR(SYSDATE,‘YYYYMMDD’)FROM DUAL


010、SQL與ORACLE的自動編號
SQL的編號一般由IDENTITY字段來提供,可以靈活地設定種子值,增量,取值範圍有BIGINT、INT、SMALLINT、TINYINT、DEIMAL等;ORACLE的編號一般由SEQUENCE來提供,由NEXTVAL與CURVAL函數從SEQUENCES取值。
CREATE TABLE A003(ID INT IDENTITY(-9999,9),NAME VARCHAR(20))
-------------------------------------------------------------------------------------------------------
CREATE SEQUENCE SEQ_001 START 9999 INCREMENT BY 9
CREATE TABLE A004(ID INT)
INSERT INTO A004 VALUES(SEQ_001.NEXTVAL)
INSERT INTO A004 VALUES(SEQ_001.CURVAL+1)


011、SQL與ORACLE的分區表
從嚴格意思上來講,SQL還沒有分區表,它的分區表是以UNION爲基礎,將多個結果集串起來,實際上是視圖;ORACLE的分區表有多種:PARTITION BY RANGE、PARTITION BY HASH、PARTITION BY LIST,其它就是混合分區,以上三種基礎分區的混合使用。當然ORACLE也可以象SQL那樣分區視圖。
CREATE TABLE A1999(ID INT,NAME VARCHAR(20))
CREATE TABLE A2000(ID INT,NAME VARCHAR(20))
CREATE VIEW V_PART AS
SELECT * FROM A1999 UNION SELECT * FROM A2000
--------------------------------------------------
CREATE TABLE A_PART1(ID INT,NAME VARCHAR2(20))
PARTITON BY RANGE(ID)(
PARTITION P1 VALUES LESS THEN (2000000) PATITION P2 VALUES LESS THEN (MAXVALUE))
CREATE TABLE A_PART2(ID INT,NAME VARCHAR2(20))
PARTITION BY HASH(ID) PARTITIONS 2 STORE IN (USERS01,USERS02)
CREATE TABLE A_PART3(ID INT,NAME VARCHAR2(20))
PARTITION BY LIST(ID)(
PARTIION P1 VALUES(‘01’,’03’,’05’) PARTITON P2 VALUES(‘02’,’04’))


012、SQL與ORACLE的存儲過程
SQL的存儲過程可以很方便地返回結果集,ORACLE的存儲過程只有通過遊標類型返回結果集,這種結果集ADO不可識別,如果想使用ORACLE存儲過程的結果集,只有使用ODAC開發包(DELPHI/BCB控件組www.51delphi.com
 與www.playicq.com有下載),SQL的過程參數如果是字符必須指定參數長度,ORACLE的過程則不充許指定字符參數的長度。 
CREATE PROCEDURE UP_001(@ID INT) AS 
BEGIN 
SELECT ID ,SUM(QTY) FROM A_TEST WHERE ID=@ID GROUP BY @ID 
END 
------------------------------------------------------------ 
CREATE OR REPLACE PACKAGE UP_002 AS 
TYPE MYCURSOR IS REF CURSOR; 
FUNCTION GETRECORD RETURN MYCURSOR; 
END; 
CEEATE OR REPLACE PACKAGE BODY UP_002 AS 
FUNCTION GETRECORD RETURN MYCURSOR AS 
MC MYCURSOR; 
SL VARCHAR2(999); 
BEGIN 
OPEN MC FOR SELECT * FROM A001; 
RETURN MC; 
END; 
END; 
ORACLE的存儲函數返回結果這麼艱難,但SQL的觸發器竟然也充許返回結果集就令人費解啦,觸發器的調試比較麻煩,在SQL實際開發中,一般都將觸發器要執行的代碼放到過程中進行調試,在查詢分析器中可以對過程進行設斷點調試。 


013、SQL與ORACLE的觸發器 
觸發器的事務是引起觸發動作事務的延續,在SQL的觸發器中是可以無BEGIN TRAN而可以直接COMMIT TRAN的。SQL的觸發器是表級觸發器,DML影響一行或無數行觸發動作只觸發一次,ORACLE分表級觸發器與行級觸發器,觸發的粒度更細膩一些,SQL在處理多行時就必須使用CURSOR啦。ORACLE使用INSERTING、DELTING、UPDATING判斷執行了什麼DML操作,SQL只有判斷INSERTED、DELETED的記錄數來判斷執行了什麼操作,只有INSERTED映象表記錄數大於0表示INSERT,只有DELETED映象表記錄數大於0表示DELETE,若兩個表記錄數都大於0表示UPDATE。 
用SQL的觸發器實現級聯添加、級聯刪除、級聯更新 
CREATE TABLE A1(ID INT,NAME VARCHAR(20)) 
CREATE TABLE A2(ID INT,NAME VARCHAR(20)) 
CREATE TRIGGER TRI_A1_INS ON A1 
FOR INSERT , DELETE , UPDATE AS BEGIN 
DECLARE @I INT,@D INT,@ID INT 
SELECT @I=COUNT(*) FROM INSERTED 
SELECT @D=COUNT(*) FROM DELETED 
--IF (@I>0 AND @D>0) 執行更新,由於用到遊標,故略去 
IF @I>0 
INSERT INTO A2 SELECT * FROM INSERTED 
IF @D>0 
DELETE FROM A2 WHERE ID=@ID 
END 
---------------------------------------------------------------------- 
用ORACLE的觸發器實現級聯添加、級聯刪除、級聯更新 
CREATE OR REPLACE TRI_A1_INS 
AFTER INSERT OR DELETE OR UPDATE ON A1 
FOR EACH ROW 
BEGIN 
IF INSERTING THEN 
INSERT INTO A2 SELECT * FROM :NEW; 
END IF; 
IF DELETING THEN 
DELETE FROM A2 WHERE ID = :OLD.ID ; 
END IF; 
IF UPDATING THEN 
UPATE A2 SET ID = :NEW.ID , NAME = :NEW.NAME WHERE ID = :OLD.ID ; 
END IF; 
END 


014、SQL與ORACLE的遊標 
SQL的遊標用@@FETCH_STATUS判斷是否還有數據,ORACLE的遊標用%FOUND、%NOTFOUND來判斷遊標是否結束,遊標分服務端遊標與客戶端遊標,在存儲過程、函數、觸發器中聲明的遊標爲服務端遊標,其它處聲明的遊標爲客戶端遊標,遊標需要使用較多的內存,但它比臨時表的性能要優一些,因爲臨時表佔用的是DISK I/O,DISK I/O應該比服務器的內存要更珍貴一些吧。 


015、SQL與ORACLE的重複記錄刪除 
好的數據庫設計重複記錄是不存在的,如果有重複記錄如何刪除呢?SQL可以使用SET ROWCOUNT N設置客戶端緩衝區的記錄來刪除,ORACLE可以使用ROWID來進行,都必須進行一些簡單的編程,SQL可以做用過程,更通用一些,ORACLE如果想做得通過不太容易,字段小些會更方便處理一些。 
DECLARE @M INT 
SELECT @M=COUNT(*) FROM A_TEST WHERE ID=X 
SELECT @M=@M-1 
SET ROWCOUNT @M --限制客戶端緩衝區的記錄數 
DELETE FROM A_TEST WHERE ID=X 
SET ROWCOUNT 0 --取消限制 
說明 刪除某條記錄的重複值,如果想清除表的所有重值要使用遊標,取得所有的X 
--------------------------------------------------------------------- 
DELETE FROM A_TEST A WHERE ROWID!=(SELECT MAX(ROWID) FROM A_TEST B 
WHERE A.ID=B.ID AND A.NAME=B.NAME) 
說明 當數據量較大時,這種方法將會使用系統大量的資源 


016 SQL與ORACLE的對象加密 
SQL與ORACLE的某些對象如過程、視圖、函數、觸發器可能涉及商業,開發商通常希望對這些對象進行加密,SQL的加密方法在創建時帶上WITH ENCRYPTION,ORACLE的對象加密明顯複雜一些,要使用WRAP工具,在ORACLE的BIN目錄內。 

017 SQL與ORACLE的表生成SQL語句 
SQL與ORACLE的表如何才導成SQL語句呢?如果一定要編程實現,SQL需要將其它數據類型的字段轉換成VARCHAR類型,ORACLE則可以隱式進行數據類型轉換。 
CREATE TABLE A_SQL(ID INT,NAME VARCHAR(20)) –假如有兩萬記錄 
SELECT ‘INSERT INTO A_SQL VALUES(‘+CAST(ID 
AS VARCHAR(20))+’,’’’+NAME+’’’)’ FROM A_SQL 
---------------------------------------------------------------- 
SELECT ‘INSERT INTO A_SQL VALUES(‘||ID||’,’||’’’||NAME||’’’||’)’ 
FROM A_SQL 
說明 SQL的字符串連接用+號,ORACLE字符串連接用||,單引號可以做轉義符。 

018、SQL與ORACLE的動態SQL 
SQL與ORACLE都支持動態SQL語句,SQL用EXEC()執行的動態SQL語句,ORACLE用EXECUTE IMMEDIATE執行動態SQL。動態SQL的效率要比非動態SQL性能差,但使用起來非常靈活,可以根據不同條件執行不同的任務。 
DECLARE @SQL VARCHAR(99) 
SELECT @SQL=’declare @m int select @m=count(*) from sysobjects select @m’ 
EXEC(@SQL) 
-------------------------------------------- 
DECLARE 
S VARCHAR2(99); 
BEGIN 
S:='SELECT COUNT(*) FROM '||' USER_TABLES'; 
EXECUTE IMMEDIATE S; 
END; 


19、返回記錄集中前N條記錄的語法? 
SQL只有使用TOP,ORACLE可以使用ROWNUM 
SELECT TOP N * FROM 記錄集(表,視圖,子查詢) 
--------------------------------------------- 
SELECT * FROM 記錄集 WHERE ROWNUM<=N 


20 如何返回記錄集中相臨兩記錄之間某字段的差值? 
CREATE TABLE A001(ID INT,QTY INT) 
INSERT INTO A001 VALUES(1,20) 
INSERT INTO A001 VALUES(4,10) 
SELECT IDENTITY(INT,1,1) CODE,QTY INTO #X FROM A001 
SELECT B.QTY-A.QTY FROM #X A,#X B WHERE A.CODE=B.CODE-1 
DROP TABLE #X 
-------------------------------------------------------- 
CREATE TABLE A002(ID INT) 
INSERT INTO A002 VALUES(1) 
INSERT INTO A002 VALUES(9) 
WITH A AS (SELECT ROWNUM RN,ID FROM A002) 
SELECT A2.ID-A1.ID FROM A A2,A A1 WHERE A2.RN=A1.RN-1 
說明 雖然語法大不相同,但最大的特點是兩者都使用了自連接技術。 


21 如何返回任意某個範圍之間的記錄集? 
CREATE TABLE A03(ID INT) 
DECLARE @I INT 
SELECT @I=1 
WHILE @I<1000 BEGIN 
INSERT INTO A03 VALUES(@I) 
SELECT @I=@I+1 
END 
--前部分是創建環境,後一部分是實現方法,比較牽強 
SELECT IDENTITY(INT,1,1) CODE,ID INTO #X FROM A03 
SELECT ID FROM #X WHERE CODE BETWEEN 10 AND 20 
DROP TABLE #X 
------------------------------------------------------ 
BEGIN 
FOR I IN 1..999 LOOP 
INSERT INTO A03 VALUES(I); 
END LOOP; 
END; 

SELECT * FROM A03 WHERE ROWNUM<20 
MINUS 
SELECT * FROM A03 WHERE ROWNUM<10; 
說明 在數據提取方面,ORACLE有ROWID,ROWNUM使之有相當強的優勢,SQL只有使用函數IDENTITY來構建一個臨時表,這樣來說還不好使用CURSOR來性能會好一些。通過這個例子,大家還可以看出SQL與ORACLE的程序結構,ORACLE更嚴謹、人性化一些。 


22、表A04中的含有A、B、C、D四個字段,當按A字段分組後,如果D等1,則只統計B的值,如果D等0,則只統計C的值。 
CREATE TABLE A04(A VARCHAR(20),B INT,C INT,D INT) 
INSERT INTO A04 VALUES('01',20,7,'0') 
INSERT INTO A04 VALUES('01',10,8,'1') 
INSERT INTO A04 VALUES('02',20,7,'1') 
INSERT INTO A04 VALUES('02',10,8,'0') 
SELECT A,SUM(CASE D WHEN 1 THEN B WHEN 0 THEN C END) FROM A04 GROUP BY A 
--------------------------------------------------------------- 
SELECT A,SUM(DECODE(D,1,B,0,C)) FROM A04 GROUP BY A 
說明 ORACLE 9I可以使用CASE語句來實現這種操作,但也可以用DECODE來作統計,使用CASE比DECODE提供了更爲強大的功能,但DECODE的語法顯然比CASE WHEN THEN END要簡潔得多。 

23、如何刪除數據庫所有表?(ORACLE則是刪除模式所有表) 
DECLARE @SQL VARCHAR(99),@TBL VARCHAR(30),@FK VARCHAR(30) 
DECLARE CUR_FK CURSOR LOCAL FOR 
SELECT OBJECT_NAME(CONSTID),OBJECT_NAME(FKEYID) FROM SYSREFERENCES 
--刪除所有外鍵 
OPEN CUR_FK 
FETCH CUR_FK INTO @FK,@TBL 
WHILE @@FETCH_STATUS =0 
BEGIN 
SELECT @SQL='ALTER TABLE '+@TBL+' DROP CONSTRAINT '+@FK 
EXEC(@SQL) 
--SELECT @SQL='DROP TABLE '+@TBL 
FETCH CUR_FK INTO @FK,@TBL 
END 
CLOSE CUR_FK 
DECLARE CUR_FKS CURSOR LOCAL FOR 
SELECT NAME FROM SYSOBJECTS WHERE XTYPE='U' 
OPEN CUR_FKS 
FETCH CUR_FKS INTO @TBL 
WHILE @@FETCH_STATUS =0 
BEGIN 
SELECT @SQL='DROP TABLE ['+@TBL+']' 
EXEC(@SQL) 
FETCH CUR_FKS INTO @TBL 
END 
CLOSE CUR_FKS 
---------------------------------------------------------------- 
DECLARE 
S VARCHAR2(99); 
CURSOR CUR_F IS SELECT CONSTRAINT_NAME,TABLE_NAME FROM USER_CONSTRAINTS 
WHERE CONSTRAINT_TYPE='R'; 
CURSOR CUR_T IS SELECT TABLE_NAME FROM USER_TABLES; 
BEGIN 
FOR V IN CUR_F LOOP 
S:='ALTER TABLE '||V.TABLE_NAME||' DROP CONSTRAINT '||V.CONSTRAINT_NAME; 
EXECUTE IMMEDIATE S; 
END LOOP; 
FOR T IN CUR_T LOOP 
S:='DROP TABLE '||T.TABLE_NAME; 
EXECUTE IMMEDIATE S; 
END LOOP; 
END; 
說明 SQL刪除數據庫時,用到了兩個系統表:SYSREFERENCES、SYSOBJECTS,前一個可以獲得所有外鍵鍵信息,後者可以獲得所有表的信息,在刪除表時還在表名上加了一對中括號,即使用表名含有空格鍵或其它特殊這符也可以順利刪除。 
在ORACLE中,要刪除模式的所有表,方法和SQL差不多,需要用到的數據字典也有兩個:USER_CONSTRAINTS、USER_TABLES;USER_CONSTRAINTS中CONSTRAINT_TYPE值等於R表示是外鍵,同樣也要用到CURSOR與動態SQL,這裏提醒一下大家,FOR … LOOP內的變量變量是FOR … LOOP聲明的,可以ORACLE的程序結構比SQL簡潔。 


24、如何統計數據庫所有用戶表的記錄數(ORACLE統計模式內所有表的記錄數)? 
CREATE TABLE #TMP (QTY INT) 
CREATE TABLE #TMP1 (TBL VARCHAR(30),QTY INT) 
DECLARE @SQL VARCHAR(99),@TBL VARCHAR(30),@QTY INT 
DECLARE CUR_FKS CURSOR LOCAL FOR 
SELECT NAME FROM SYSOBJECTS WHERE XTYPE='U' 
OPEN CUR_FKS 
FETCH CUR_FKS INTO @TBL 
WHILE @@FETCH_STATUS =0 
BEGIN 
SELECT @SQL='SELECT COUNT(*) FROM '+@TBL 
INSERT INTO #TMP EXEC(@SQL) 
SELECT @QTY=QTY FROM #TMP 
INSERT INTO #TMP1 VALUES(@TBL,@QTY) 
DELETE FROM #TMP 
FETCH CUR_FKS INTO @TBL 
END 
CLOSE CUR_FKS 
SELECT * FROM #TMP1 
--------------------------------------------------------------- 
DESC DBMS_UTILITY 
EXECUTE DBMS_UTILITY.ANALYZE_SCHEMA('SCOTT','COMPUTE'); 
SELECT TABLE_NAME,NUM_ROWS FROM USER_TABLES; 
說明 SQL的EXEC功能可謂十分強大,竟然可以和INSERT INTO合用,將結果集存入一個表中,MS可真牛。ORACLE就只好用個偷懶的方法,首先將要統計的模式進行統計分析,在數據字典中就記載了每個表的行數,ORACLE很簡單吧。 


25、SQL與ORACLE快速建表的方法? 
SELECT * INTO 新表名稱 FROM 子查詢|表名 
----------------------------------------- 
CREATE TABLE 新表名稱 AS 子查詢 
說明 快速建表可以有效地消除碎片,速度極快。 


26、如何實現有一組有規則的編號(如200305310001…200305310999)? 
DECLARE @I INT,@C VARCHAR(20) 
SELECT @I=1 
WHILE @I<1000 BEGIN 
SELECT @C=CASE WHEN @I<10 THEN '000'+CAST(@I AS CHAR(1)) 
WHEN @I BETWEEN 10 AND 99 THEN '00'+CAST(@I AS CHAR(2)) 
WHEN @I BETWEEN 100 AND 999 THEN '0'+CAST(@I AS CHAR(3)) 
END 
SELECT @C=CONVERT(VARCHAR(20),GETDATE(),112)+@C 
SELECT @C --在查詢分析器中輸出 
SELECT @I=@I+1 
END 
--------------------------------------------------------- 
DECLARE 
C VARCHAR2(20); 
BEGIN 
FOR I IN 1 .. 999 LOOP 
DBMS_OUTPUT.PUT_LINE(TO_CHAR(SYSDATE,'YYYYMMDD')||LPAD(I,4,'0')); 
END LOOP; 
END; 
說明 雖然都可以實現,但ORACLE的LPAD果然身手不凡,可憐的MS還沒有類似LPAD的函數,只有用CASE進行判斷組合,真得很蠢,如果你有好的辦法,請明示,甚至連循環結構,SQL稍也不慎,就死循環啦(如果註釋掉加藍顯示那條語句的話)。 


27、關於SQL與ORACLE的分佈式結構 
SQL在分佈式方面做得不錯,不僅提供了鏈接服務器的方式供初級用戶使用,還提供了OPENDATASOURCE、OPENXML、OPENQUERY、OPENROWSET等行集函數,可以方便地通過SQL語句從*.TXT、*.XLS、*.XML、*.MDB、*.DBF等介質獲取數據,還可以從ORACLE、DB2、SYBASE等數據庫獲取數據;ORACLE在同構數據庫之間提供了DB LINK,異構數據庫之間提供了透明網關軟件。 


28、現在有三個表,結構如下 
Score(FScoreId 成績記錄號,FSubID 課程號,FStdID 學生號,FScore 成績) 
student:(FID 學生號,FName 姓名) 
subject:(FSubID 課程號,FSubName 課程名), 
怎麼能實現這個表: 
姓名 英語 數學 語文 歷史 
張薩 78 67 89 76 
王強 89 67 84 96 
李三 70 87 92 56 
李四 80 78 97 66 
SELECT A.FNAME AS 姓名, 
英語 = SUM(CASE B.FSUBNAME WHEN '英語' THEN C.FSCORE END), 
數學 = SUM(CASE B.FSUBNAME WHEN '數學' THEN C.FSCORE END), 
語文 = SUM(CASE B.FSUBNAME WHEN '語文' THEN C.FSCORE END), 
歷史 = SUM(CASE B.FSUBNAME WHEN '歷史' THEN C.FSCORE END) 
FROM STUDENT A, SUBJECT B, SCORE C 
WHERE A.FID = C.FSTDID AND B.FSUBID = C.FSUBID GROUP BY A.FNAME 
------------------------------------------------------------------------ 
SELECT A.FNAME AS 姓名, 
英語 = SUM(DECODE(B.FSUBNAME,’ 英語’,C.FSORE)), 
數學 = SUM(DECODE(B.FSUBNAME,’ 數學’,C.FSORE)), 
語文 = SUM(DECODE(B.FSUBNAME,’ 語文’,C.FSORE)), 
歷史 = SUM(DECODE(B.FSUBNAME,’ 歷史’,C.FSORE)), 
FROM STUDENT A, SUBJECT B, SCORE C 
WHERE A.FID = C.FSTDID AND B.FSUBID = C.FSUBID GROUP BY A.FNAME 
說明 這個案例主要是運用CASE與DECODE,當然也涉及GROUP BY的用法。 


29、有兩個表,用一條SQL語句算出商品A,B目前還剩多少?表結構如下: 
商品名稱mc 商品總量sl 表一(AAA) 
A 100 
B 120 
商品名稱mc 出庫數量sl 表二(BBB) 
A 10 
A 20 
B 10 
B 20 
SELECT TA.商品名稱,A-B AS 剩餘數量 FROM 
(SELECT 商品名稱,SUM(商品總量) AS A FROM AAA GROUP BY 商品名稱)TA, 
(SELECT 商品名稱,SUM(出庫數量) AS B FROM BBB GROUP BY 商品名稱)TB 
WHERE TA.商品名稱=TB.商品名稱 
---------------------------------------------------------- 
SELECT 商品名稱,SUM(商品總量)剩餘數量 FROM 
(SELECT * FROM AAA 
UNION ALL 
SELECT 商品名稱,-出庫數量 FROM BBB)A GROUP BY 商品名稱 


30、如何將A表的某個字段更新到表B的某個字段? 
UPDATE A SET QTY=B.QTY FROM B WHERE A.CODE=B.CODE 
--------------------------------------------------- 
UPDATE A SET QTY=(SELECT QTY FROM B WHERE B.CODE=A.CODE) 
說明 這兩道題在語法上SQL與ORACLE沒有發別,只不過是兩種思路而已。 


31、有一個商品銷售表,記載了某月商品的銷售數量,現在要爲所有商品排名次,放到一個單獨的字段中,就是說達到右邊顯示的效果,如何作? 
BU1032 5 NULL BU1032 5 2 
PS2091 3 NULL PS2092 3 3 
PC8888 50 NULL PC8888 50 1 
UPDATE X SET ORD=(SELECT COUNT(*)+1 FROM X B WHERE B.QTY>X.QTY) 
---------------------------------------------------------------- 
SELECT CODE,QTY,RANK() OVER (ORDER BY QTY) ORD FROM A_TEST 
說明 SQL中的排序是通過UPDATE更新,然後再顯示出來,而ORACLE使用了RANK OVER函數,直接將數據集顯示出來,而且RANK OVER函數還可以通過PARTITION BY對分組中的數據進行排序。 


32、SQL與ORACLE的文件結構 
SQL文件被格式化爲8K爲單位的頁,每8個相鄰的頁稱爲盤區(64K),若該盤區分配給一個對象,稱爲一致盤區,若分配給多個對象等爲混合盤區,SQL有全局分配頁面、數據頁面、索引頁頁、BLOB頁面、TEXT頁面。ORACLE的文件最小邏輯單位是由INIT.ORA中的BLOCK_SIZE的值決定的,可以取2K、4K、6K、8K、16K、32K等,ORACLE的盤區是由一些塊組成的,ORACLE的段是由盤區組成的,ORACLE有數?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章