A. Oraclesql精妙SQL語句講解
行列轉換 行轉列
DROP TABLE t_change_lc;
CREATE TABLE t_change_lc (card_code VARCHAR ( ) q NUMBER bal NUMBER);
INSERT INTO t_change_lc
SELECT card_code ROWNUM q trunc(dbms_random VALUE * ) bal FROM al CONNECT BY ROWNUM <=
UNION
SELECT card_code ROWNUM q trunc(dbms_random VALUE * ) bal FROM al CONNECT BY ROWNUM <= ;
SELECT * FROM t_change_lc;
SELECT a card_code
SUM(decode(a q a bal )) q
SUM(decode(a q a bal )) q
SUM(decode(a q a bal )) q
SUM(decode(a q a bal )) q
FROM t_change_lc a
GROUP BY a card_code
ORDER BY ;
行列轉換 列轉行
DROP TABLE t_change_cl;
CREATE TABLE t_change_cl AS
SELECT a card_code
SUM(decode(a q a bal )) q
SUM(decode(a q a bal )) q
SUM(decode(a q a bal )) q
SUM(decode(a q a bal )) q
FROM t_change_lc a
GROUP BY a card_code
ORDER BY ;
SELECT * FROM t_change_cl;
SELECT t card_code
t rn q
decode(t rn t q t q t q t q ) bal
FROM (SELECT a * b rn
FROM t_change_cl a
(SELECT ROWNUM rn FROM al CONNECT BY ROWNUM <= ) b) t
ORDER BY ;
行列轉換 行轉列 合並
DROP TABLE t_change_lc_ma;
核局陪CREATE TABLE t_change_lc_ma AS SELECT card_code quarter_ ||q AS q FROM t_change_lc;
SELECT * FROM t_change_lc_ma;
SELECT t card_code substr(MAX(sys_connect_by_path(t q ; )) ) q
FROM (SELECT a card_code
a q
row_number() over(PARTITION BY a card_code ORDER BY a q) rn
FROM t_change_lc_ma a) t
START WITH t rn =
CONNECT BY t card_code = PRIOR t card_code
AND t rn = PRIOR t rn
GROUP BY t card_code;
行列轉換 列轉行 分割
DROP TABLE t_change_cl_ma;
CREATE TABLE t_change_cl_ma AS
SELECT t card_code substr(MAX(sys_connect_by_path(t q ; )) ) q
FROM (SELECT a card_code
a q
臘歷改蠢row_number() over(PARTITION BY a card_code ORDER BY a q) rn
FROM t_change_lc_ma a) t
START WITH t rn =
CONNECT BY t card_code = PRIOR t card_code
AND t rn = PRIOR t rn
GROUP BY t card_code;
SELECT * FROM t_change_cl_ma;
SELECT t card_code
substr(t q
instr( ; || t q ; rn)
instr(t q || ; ; rn) instr( ; || t q ; rn)) q
FROM (SELECT a card_code a q b rn
FROM t_change_cl_ma a
(SELECT ROWNUM rn FROM al CONNECT BY ROWNUM <= ) b
WHERE instr( ; || a q ; rn) > ) t
ORDER BY ;
實現一條記錄根據條件多表插入
DROP TABLE t_ia_src;
CREATE TABLE t_ia_src AS SELECT a ||ROWNUM c b ||ROWNUM c FROM al CONNECT BY ROWNUM<= ;
DROP TABLE t_ia_dest_ ;
CREATE TABLE t_ia_dest_ (flag VARCHAR ( ) c VARCHAR ( ));
DROP TABLE t_ia_dest_ ;
CREATE TABLE t_ia_dest_ (flag VARCHAR ( ) c VARCHAR ( ));
DROP TABLE t_ia_dest_ ;
CREATE TABLE t_ia_dest_ (flag VARCHAR ( ) c VARCHAR ( ));
SELECT * FROM t_ia_src;
SELECT * FROM t_ia_dest_ ;
SELECT * FROM t_ia_dest_ ;
SELECT * FROM t_ia_dest_ ;
INSERT ALL
WHEN (c IN ( a a )) THEN
INTO t_ia_dest_ (flag c) VALUES(flag c )
WHEN (c IN ( a a )) THEN
INTO t_ia_dest_ (flag c) VALUES(flag c )
ELSE
INTO t_ia_dest_ (flag c) VALUES(flag ||flag c ||c )
SELECT c c f flag f flag FROM t_ia_src;
如果存在就更新 不存在就插入用一個語句實現
DROP TABLE t_mg;
CREATE TABLE t_mg(code VARCHAR ( ) NAME VARCHAR ( ));
SELECT * FROM t_mg;
MERGE INTO t_mg a
USING (SELECT the code code the name NAME FROM al) b
ON (de = de)
WHEN MATCHED THEN
UPDATE SET a NAME = b NAME
WHEN NOT MATCHED THEN
INSERT (code NAME) VALUES (de b NAME);
抽取/刪除重復記錄
DROP TABLE t_p;
CREATE TABLE t_p AS SELECT code_ ||ROWNUM code dbms_random string( z ) NAME FROM al CONNECT BY ROWNUM<= ;
INSERT INTO t_p SELECT code_ ||ROWNUM code dbms_random string( z ) NAME FROM al CONNECT BY ROWNUM<= ;
SELECT * FROM t_p;
SELECT * FROM t_p a WHERE a ROWID <> (SELECT MIN(b ROWID) FROM t_p b WHERE de=de);
SELECT de b NAME
FROM (SELECT de
a NAME
row_number() over(PARTITION BY de ORDER BY a ROWID) rn
FROM t_p a) b
WHERE b rn > ;
IN/EXISTS的不同適用環境
t_orders customer_id有索引
SELECT a *
FROM t_employees a
WHERE a employee_id IN
(SELECT b sales_rep_id FROM t_orders b WHERE b customer_id = );
SELECT a *
FROM t_employees a
WHERE EXISTS (SELECT
FROM t_orders b
WHERE b customer_id =
AND a employee_id = b sales_rep_id);
t_employees department_id有索引
SELECT a *
FROM t_employees a
WHERE a department_id =
AND EXISTS
(SELECT FROM t_orders b WHERE a employee_id = b sales_rep_id);
SELECT a *
FROM t_employees a
WHERE a department_id =
AND a employee_id IN (SELECT b sales_rep_id FROM t_orders b);
FBI
DROP TABLE t_fbi;
CREATE TABLE t_fbi AS
SELECT ROWNUM rn dbms_random STRING( z ) NAME SYSDATE + dbms_random VALUE * dt FROM al
CONNECT BY ROWNUM <= ;
CREATE INDEX idx_nonfbi ON t_fbi(dt);
DROP INDEX idx_fbi_ ;
CREATE INDEX idx_fbi_ ON t_fbi(trunc(dt));
SELECT * FROM t_fbi WHERE trunc(dt) = to_date( yyyy mm dd ) ;
不建議使用
SELECT * FROM t_fbi WHERE to_char(dt yyyy mm dd ) = ;
LOOP中的MIT/ROLLBACK
DROP TABLE t_loop PURGE;
create TABLE t_loop AS SELECT * FROM user_objects WHERE = ;
SELECT * FROM t_loop;
逐行提交
DECLARE
BEGIN
FOR cur IN (SELECT * FROM user_objects) LOOP
INSERT INTO t_loop VALUES cur;
MIT;
END LOOP;
END;
模擬批量提交
DECLARE
v_count NUMBER;
BEGIN
FOR cur IN (SELECT * FROM user_objects) LOOP
INSERT INTO t_loop VALUES cur;
v_count := v_count + ;
IF v_count >= THEN
MIT;
END IF;
END LOOP;
MIT;
END;
真正的批量提交
DECLARE
CURSOR cur IS
SELECT * FROM user_objects;
TYPE rec IS TABLE OF user_objects%ROWTYPE;
recs rec;
BEGIN
OPEN cur;
WHILE (TRUE) LOOP
FETCH cur BULK COLLECT
INTO recs LIMIT ;
forall 實現批量
FORALL i IN recs COUNT
INSERT INTO t_loop VALUES recs (i);
MIT;
EXIT WHEN cur%NOTFOUND;
END LOOP;
CLOSE cur;
END;
悲觀鎖定/樂觀鎖定
DROP TABLE t_lock PURGE;
CREATE TABLE t_lock AS SELECT ID FROM al;
SELECT * FROM t_lock;
常見的實現邏輯 隱含bug
DECLARE
v_cnt NUMBER;
BEGIN
這里有並發性的bug
SELECT MAX(ID) INTO v_cnt FROM t_lock;
here for other operation
v_cnt := v_cnt + ;
INSERT INTO t_lock (ID) VALUES (v_cnt);
MIT;
END;
高並發環境下 安全的實現邏輯
DECLARE
v_cnt NUMBER;
BEGIN
對指定的行取得lock
SELECT ID INTO v_cnt FROM t_lock WHERE ID= FOR UPDATE;
在有lock的情況下繼續下面的操作
SELECT MAX(ID) INTO v_cnt FROM t_lock;
here for other operation
v_cnt := v_cnt + ;
INSERT INTO t_lock (ID) VALUES (v_cnt);
MIT; 提交並且釋放lock
END;
硬解析/軟解析
DROP TABLE t_hard PURGE;
CREATE TABLE t_hard (ID INT);
SELECT * FROM t_hard;
DECLARE
sql_ VARCHAR ( );
BEGIN
hard parse
java中的同等語句是 Statement execute()
FOR i IN LOOP
sql_ := insert into t_hard(id) values( || i || ) ;
EXECUTE IMMEDIATE sql_ ;
END LOOP;
MIT;
soft parse
java中的同等語句是 PreparedStatement execute()
sql_ := insert into t_hard(id) values(:id) ;
FOR i IN LOOP
EXECUTE IMMEDIATE sql_
USING i;
END LOOP;
MIT;
END;
正確的分頁演算法
SELECT *
FROM (SELECT a * ROWNUM rn
FROM (SELECT * FROM t_employees ORDER BY first_name) a
WHERE ROWNUM <= )
WHERE rn > ;
分頁演算法(why not this one)
SELECT a * ROWNUM rn
FROM (SELECT * FROM t_employees ORDER BY first_name) a
WHERE ROWNUM <= AND ROWNUM > ;
分頁演算法(why not this one)
SELECT b *
FROM (SELECT a * ROWNUM rn
FROM t_employees a
WHERE ROWNUM < =
ORDER BY first_name) b
WHERE b rn > ;
OLAP
小計合計
SELECT CASE
WHEN a deptno IS NULL THEN
合計
WHEN a deptno IS NOT NULL AND a empno IS NULL THEN
小計
ELSE
|| a deptno
END deptno
a empno
a ename
SUM(a sal) total_sal
FROM scott emp a
GROUP BY GROUPING SETS((a deptno) (a deptno a empno a ename) ());
分組排序
SELECT a deptno
a empno
a ename
a sal
可跳躍的rank
rank() over(PARTITION BY a deptno ORDER BY a sal DESC) r
密集型rank
dense_rank() over(PARTITION BY a deptno ORDER BY a sal DESC) r
不分組排序
rank() over(ORDER BY sal DESC) r
FROM scott emp a
ORDER BY a deptno a sal DESC;
當前行數據和前/後n行的數據比較
SELECT a empno
a ename
a sal
上面一行
lag(a sal) over(ORDER BY a sal DESC) lag_
下面三行
lead(a sal ) over(ORDER BY a sal DESC) lead_
FROM scott emp a
lishixin/Article/program/Oracle/201311/16728
B. oracle 怎麼分析sql效率 sql語句
查詢一和二都是全表內查詢,一中嵌套子查詢,還是用的In操作符,困鋒效率較低。像單表的這種查詢二是衡寬最快的,大部分情咐尺亮況oracle內置的東西,效率都不低的,如果還想提交效率,可在fclass加個索引
C. 請問,在ORACLE里,如何判斷一個SQL的性能如何有沒有好用的工具
explain plan 是一個很好的分析sql語句的工具,它甚至可以在不執行sql的情況下分析語句. 通過分析,我們就可以知道oracle是怎麼樣連接表,使用什麼方式掃描表(索引掃描或全表掃描)以及使用到的索引名稱.
你需要按照從里到外,從上到下的次序解讀分析的結果. explain plan分析的結果是用縮進的格式排列的, 最內部的操作將被最先解讀, 如果兩個操作處於同一層中,帶有最小操作號的將被首先執行.
nested loop是少數不按照上述規則處理的操作, 正確的執行路徑是檢查對nested loop提供數據的操作,其中操作號最小的將被最先處理.
譯者按:
通過實踐, 感到還是用sqlplus中的set trace 功能比較方便.
舉例:
sql> list
1 select *
2 from dept, emp
3* where emp.deptno = dept.deptno
sql> set autotrace traceonly /*traceonly 可以不顯示執行結果*/
sql> /
14 rows selected.
execution plan
----------------------------------------------------------
0 select statement optimizer=choose
1 0 nested loops
自己往後看吧
D. 在oracle存儲過程中sql語句想分析該語句,卻看不見執行計劃,我該怎麼辦請高手指點!謝謝!
按執行結果來看,是和字元有關,與執行計劃有什麼關系?!
count(1)可以直接賦值啊:改成下面的再試一下
把iv_specialtag定義成INT類型
SELECT count(1) INTO iv_specialtag
FROM uop_act1.tf_f_user_highvalue
WHERE user_id = iv_user_id
AND partition_id = mod(iv_user_id,10000);
IF iv_specialtag=1 THEN
GOTO LABEL_NEXTUSER;
END IF;
想查執行效率,直接用樓上的SELECT部分語句
E. oracle sql執行計劃怎麼分析
在發現一個語句的執行計劃有異常的時候,通常會生成一個sqlrpt看看使用的執行計劃是否正確,如何來判斷執行計劃是否正確,將通過以下幾個步驟來判斷:
1.先查看sql語句的結構,看語句中連接是union,還是等值連接還是左、右連接,再看連接中的表數量。
2.查看執行計劃中出現異常的部分。
3.查看各表的索引情況及表是否是分區的,在where條件上使用的索引列是否正確,看統計分析表中對表的分析結果是否正確
4.分析表的用途,表的數據日增長量。
5.分析為什麼會出現異常的執行計劃。
跟蹤執行計劃的方法:
(1) set autotrace on explain 只顯示查詢結果和執行計劃
set autotrace on statistic 只顯示查詢結果統計信息
set autotrace on 顯示前兩者
set autotrace traceonly 不顯示查詢結果,只顯示執行計劃和統計信息
set autotrace off 關閉跟蹤
要使用autotrace,必須在sqlplus裡面使用,且使用的是sys用戶。
(2)可以使用explain plan for select * from c_cons 可以解析執行計劃,然後通過select * from table(dbms_xplain.display(null,null,』outline』,null));來顯示執行計劃。
(3)使用工具Toad for oracle使用sql_id來生成執行計劃
F. 【基於ORACLE資料庫的SQL語句優化分析】 資料庫查詢語句的優化
【摘要】隨著資料庫應用范圍及規模的不斷擴大,資料庫的性能問題逐漸顯現,優化資料庫有助於維持系統的穩定性以及運行的高效性。本文主要依據筆者在實際工作中的精坦敏拍英,對SQL語句優化的目的、SQL語句優化技術及原則進行全面分析和闡述。
【關鍵詞】ORACLE資料庫;SQL語句;優化
1前言
隨著現代化信息技術的迅猛發展,互聯網應用的日益普及,資料庫技術的影響力越來越大。作為信息系統管理的核心,資料庫的主要操作就是查詢,資料庫的應用效率在很大程度上是由查詢速度決定的,特別是對於規模較大的資料庫而言,查詢速度十分關鍵。查詢速度在SQL語句中佔有很大比重,所以,通過對查詢語句進行優化有助於促進應用系統性能及效率的進一步提升。
2SQL語句優化分析
2.1SQL語句優化的目的
對於一個資料庫而言,在確保設計無誤的前提下,要想避免出現性能問題必須確保其擁有合理的SQL語句拿喚結構。最簡單的資料庫尋找數據路徑是對SQL語句進行調整,ORACLE資料庫性能提升的主要途徑就是對SQL語句進行適當的調整。從本質上講,SQL語句優化就是確保所使用的語句可以被優化器識別,對索引進行有效利用以便控製表掃描的I/O次數,有效防止出現表搜索。用高性能的SQL語句替代低性能的SQL語句,確定最佳的數據查找路徑,盡可能使CPU時間與I/O時間保持平衡是進行優化的主要目的。在對SQL語句進行優化的過程中,以系統需求為依據確定最有可能實現性能提升的語句並進行優化。
2.2SQL語句優化技術及原則
當數據量積累到一定程度之後,對於資料庫全表SQL語句進行一次掃描,若查詢策略較好,一般只用幾秒鍾,但如果SQL語句性能較低,就需要用幾分鍾甚至更多時間。從這點不難看出,SQL語句性能對於查詢速度具有極大的影響,所以,對於應用系統而言,不僅能滿足功能的實現,還要保證SQL語句的質量。
(1)採取適宜的索引。為達到優化查詢的目的,一項重要工作就是確定相適應的索引,並嚴格依照原則加以使用,與此同時,為有效控制I/O競爭,不可以在同一個磁碟中同時建立索引和用戶表空間。
語句1:SELECT CUS_NO, CUS_NAME FROM CUSTOMER WHERE CUS_NO NOT IN
(SELECT CUS_NO FROM SERVICE);
語句2: SELECT CUS_NO, CUS_NAME FROM CUSTOMER WHERE NOT EXISTS
(SELECT * FROM SERVICE WHERE SERVICE.CUS_NO=CUSTOMER.CUS_NO);
上述兩個語句可以達到一致的查詢結果,對二者進行對比,當執行語句1時,由於ORACLE未利用CUSTOMER 表上CUS_NO索引,所以就會掃描整表,在執行語句2的過讓羨程中,ORACLE所掃描的只是CUSTOMER 表子查詢中的聯合查詢,並且使用了CUS_NO索引,因此,在執行效率方面明顯優於前者。
(2)避免在SELECT子句中出現「*」。ORACLE在進行解析時,需要按照一定順序對「*」進行轉換,該項轉換工作的進行需要對資料庫的數據字典進行查詢,勢必需要花費較多的時間,這樣就會導致較低的效率,所以,要避免在SELECT子句中出現「*」。
(3)如果必要可以利用COMMIT提交事務。ORACLE能夠自動提交DDL語句,而諸如DML等類型的語句的提交則是通過手動方式或者回滾事務實現的。在編寫應用程序的過程中,在操作諸如insert、delete以及update 等較為復雜的語境的時候,利用COMMIT提交事務可以講會話中持有的鎖加以釋放,將存在於緩存中的未經修改的數據塊進行清除,進而將系統資源予以釋放,促進系統性能的進一步提升,因此,如果有必要,可以利用COMMIT對相關事務進行提交。
(4)聯合查詢連接順序的確定。如果查詢操作涉及到多個表,基礎表應當是交叉表,所謂交叉表具體是指被其他表引用的表。連接執行效果在很大程度上受到FROM語句中表的順序的影響,對於FROM中所包含的表,ORACLE解析器進行處理的順序是由右至左,SQL語句中所選擇的基礎表會因優化器的不同而有所區別,在使用CBO的情況下,優化器會對SQL語句中各個表的物理大小以及索引狀態進行檢查,在此基礎上確定一個花費最小的執行路徑;在使用RBO的情況下,如果全部的連接條件均有索引與之相對應,那麼,FROM子句中位置最後面的表就是基礎表。
(5)IN用EXISTS取代。在對數個基礎表查詢過程中,一般需要進行表的連接。因為利用IN的子查詢過程中,ORACLE的掃描對象是全表,因此,出於提高查詢效率目的的考慮,應當將IN用EXISTS取代。
(6)在索引列中不使用計算。當通過對函數進行引用在WHERE子句中進行計算的時候,假如索引列只是函數的一部分,優化器就會針對全表進行掃描,而不會使用索引,所以,在索引列中不能使用函數。
3結語
綜上所述,隨著現代化信息技術的迅猛發展,互聯網應用的日益普及,資料庫技術的影響力越來越大。在信息量迅速激增的形勢下,資料庫優化調整成為當前所面臨的一大關鍵性問題,特別是對規模較大的資料庫而言,及時進行優化的意義更加倍重大。對於資料庫的運行性能而言,最主要的影響因素主要體現在以下幾點:資料庫系統架構的設計是否合理,資源配置是否科學以及SQL語句編寫效率等。筆者從事的是電信企業的運營分析工作,每天都要從資料庫取各種數據,可以說是離不開資料庫,所以在實踐中,我覺得嚴格遵守SQL語句優化原則及方法,並在實踐中及時總結經驗教訓,可以實現對系統響應時間的有效控制,促進運行效率的提升。
參考文獻
[1] 許開宇,胡文驊. 如何提高ORACLE資料庫應用程序的性能[J]. 計算機應用與軟體. 2002(10)
[2] 鄭耀,吳建嵐. 基於Oracle資料庫的語句優化策略[J]. 信息與電腦(理論版). 2011(07)
[3] 高攀,施蔚然. 基於Oracle資料庫的SQL語句優化[J]. 電腦編程技巧與維護. 2010(22)
[4] 鍾小權,葉猛. Oracle資料庫的SQL語句優化[J]. 計算機與現代化. 2011(03)
作者簡介:
王勇軍,男,(1981.1-),吉林通化人,就職於中國聯合網路通信有限公司長春市分公司,通信工程師,本科,研究方向:SQL使用
(作者單位:中國聯合網路通信有限公司長春市分公司)
G. 如何對一個oracle11gsql語句進行統計分析
可以通過district來取出欄位,之後通過count計算總數量。
sql:select count(district id) from tablename;
如果id欄位沒有空值的話,可以通過count統計欄位的總數量(欄位內容可能重復)。
sql:select count(id) from tablename;
H. oraclesql條件語句
1. oracle SQL查詢中,如何在where中用條件語句,判斷不同情況,追加不同的And條件
1、先創建一個簡單的數據表。
2. oracle資料庫中多條脊碧件查詢語句怎麼寫
1、首先需要打開一個oracle資料庫界面。
3. oracle sql條件查詢
update tb
set studystatus = '002'
where exsist (
select c.courseid
from tb c
where c.courseid = tb.courseid and c.studystatus = '002'
) and studystatus != '002';
說明: 使用exists做條件, 如果有courseid值相同的, 且studystatus為002的, 則將studystatus更新為002, 條件studystatus != '002'則是限制已經為002的記錄不需要更新.
你是要修改查詢到的結果? 可以在查詢語句中使用case when來根據條件得到不同的值:
select s.courseid, case when exists (select c.courseid from tb c where c.courseid = s.courseid and c.studystatus = '002' and rownum < 2) then '002' else s.studystatus end as studystatus
from tb s;
這個是不是你想要的?
4. oracle sql語句時間條件
where time beeen '08:00' and '18:00'
以上是大概意思,具體時間的表示方法要根據資料庫時間欄位的類型和格式來。
5. ORACLE sql 裡面可以用if 語句嗎語法是什麼
insert 語句中值的順序如果和表結構一致可以省略列名列表。
這個物野冊SQL的意思沒看懂,我給分析一下看對不對,
你是不是想表達這個意思:
如果在yangao這個表中存在age3=4的數據,那麼,就向yangao中插入一行數據,行數據的內容是罩宏(4,NULL,1).
如果是這樣的話,那麼IF用的是不對的。
在SQL裡面條件的關鍵字是WHERE。
insert into yangao values(4,NULL,1)
where exists (select * from yangao where(AGE3=4));
mit;
但如果你想表達的是:
在yangao表中插入一條數據,如果存在(select * from yangao where(AGE3=4)) 這樣的數據就提交的話,那麼應該這么寫:
insert into yangao values (4, NULL, 1);
select count(*) into n_count from yangao where (AGE3 = 4);
if n_count > 0 then
mit;
end if;
6. vc 中Oracle sql多條件查詢語句怎麼寫
where1=1--這個你寫在後台
and條件1--其他的你就按這種方式來拼就行了,其他的條件不輸入也不影響你前邊的執行
and條件2
and條件3
and條件4
能按懂吧?
7. oracle資料庫條件判斷的查詢語句怎麼寫
建表,測試數據:
createtabletest
(收款標志int)
insertintotestvalues(1);
insertintotestvalues(1);
insertintotestvalues(1);
mit;
執行:
selectcase
whena.cnt=b.cntthen
'未收款'
whena.cnt=d.cntthen
'已收款'
whenc.cnt<>0then
'部分收款'
end收款狀態
from(selectcount(*)cntfromtest)a,
(selectcount(*)cntfromteshere收款標志=1)b,
(selectcount(*)cntfromteshere收款標志=2)c,
(selectcount(*)cntfromteshere收款標志=3)d
結果:
然後你自己換點其他數據測試一下吧,思路就這么個思路了。
8. 如何在Oracle的Where語句中添加條件判斷
*******************
plsql寫法:
*******************
1、在sqlplus 中定義一個 游標變數
var p_cursor refcursor
2、寫一個plsql過程塊
declare
sql_str varchar(1000) := ' ';
begin
if 2 > 1 then
sql_str := 'select * from student where Name=''小王''';
else
sql_str := 'select * from student where Name=''小李''';
end if;
open :p_cursor for sql_str;
end;
3、在sqlplus中列印輸出結果
print p_cursor;
***************
補充:有點錯誤修正了下
***************
---
以上,希望對你有所幫助。
9. Oracle sql查詢 in 條件語句
你這樣的語句本身應該是有問題的吧,你是想要實現什麼樣的效果,如果只是想找出tableName表中不同的id,可以這樣查:
select distinct id from tableName;
10. Oracle SQL語句實現按條件表達式更新列數據
update .. set col_length=(length(col_number)-4)/2+1
I. 幫我整體分析和講解下以下 SQL語句(ORACLE中的),給50分~~~
select:
查詢
c.dsc
訂貨方式:
c表的dsc欄位
顯示欄位名字為
訂貨方式
count():聚合函數
統計數量的
distinct
:消除重復的
from
orderhist
a,names
c,
orderdet
y:要查詢的坦伏表
orderhist表在這條語虛晌句中命名為a
where
:條讓譽攜件
between
and
:在這2個時間內
x.soldwith
in
('1','2','3'):x表soldwith
欄位的值是1
2
3的
group
by
:分組顯示
sum():聚合函數
欄位的值的和
J. oracle sql是怎麼解析的
導讀:Oracle的後台運作原理是什麼?我們的一條命令是如何被執行的?今天我們就從一條簡單的Select語句開始,看看Oracle資料庫後台的運作機制。
Select語句可以說是DBA和資料庫開發者在工作中使用最多的語句之一,但這條語句是如何執行?在Oracle資料庫中又是如何運作的呢?今天我們就從一條簡單的Select語句開始,看看Oracle資料庫後台的運作機制。這對於我們之後的系統管理與故障排除非常有幫助。
第一步:客戶端把語句發給伺服器端執行
當我們在客戶端執行select語句時,客戶端會把這條SQL語句發送給伺服器端,讓伺服器端的進程來處理這語句。也就是說,Oracle客戶端是不會做任何的操作,他的主要任務就是把客戶端產生的一些SQL語句發送給伺服器端。雖然在客戶端也有一個資料庫進程,但是,這個進程的作用跟伺服器上的進程作用事不相同的。伺服器上的資料庫進程才會對SQL語句進行相關的處理。不過,有個問題需要說明,就是客戶端的進程跟伺服器的進程是一一對應的。也就是說,在客戶端連接上伺服器後,在客戶端與伺服器端都會形成一個進程,客戶端上的我們叫做客戶端進程;而伺服器上的我們叫做伺服器進程。所以,由於所有的SQL語句都是伺服器進程執行的,所以,有些人把伺服器進程形象地比喻成客戶端進程的「影子」。
第二步:語句解析
當客戶端把SQL語句傳送到伺服器後,伺服器進程會對該語句進行解析。同理,這個解析的工作,也是在伺服器端所進行的。雖然這只是一個解析的動作,但是,其會做很多「小動作」。
1. 查詢高速緩存。伺服器進程在接到客戶端傳送過來的SQL語句時,不會直接去資料庫查詢。而是會先在資料庫的高速緩存中去查找,是否存在相同語句的執行計劃。如果在數據高速緩存中,剛好有其他人使用這個查詢語句的話,則伺服器進程就會直接執行這個SQL語句,省去後續的工作。所以,採用高速數據緩存的話,可以提高SQL語句的查詢效率。一方面是從內存中讀取數據要比從硬碟中的數據文件中讀取數據效率要高,另一方面,也是因為這個語句解析的原因。
不過這里要注意一點,這個數據緩存跟有些客戶端軟體的數據緩存是兩碼事。有些客戶端軟體為了提高查詢效率,會在應用軟體的客戶端設置數據緩存。由於這些數據緩存的存在,可以提高客戶端應用軟體的查詢效率。但是,若其他人在伺服器進行了相關的修改,由於應用軟體數據緩存的存在,導致修改的數據不能及時反映到客戶端上。從這也可以看出,應用軟體的數據緩存跟資料庫伺服器的高速數據緩存不是一碼事。
2. 語句合法性檢查。當在高速緩存中找不到對應的SQL語句時,則資料庫伺服器進程就會開始檢查這條語句的合法性。這里主要是對SQL語句的語法進行檢查,看看其是否合乎語法規則。如果伺服器進程認為這條SQL語句不符合語法規則的時候,就會把這個錯誤信息,反饋給客戶端。在這個語法檢查的過程中,不會對SQL語句中所包含的表名、列名等等進行SQL他只是語法上的檢查。
3. 語言含義檢查。若SQL語句符合語法上的定義的話,則伺服器進程接下去會對語句中的欄位、表等內容進行檢查。看看這些欄位、表是否在資料庫中。如果表名與列名不準確的話,則資料庫會就會反饋錯誤信息給客戶端。
所以,有時候我們寫select語句的時候,若語法與表名或者列名同時寫錯的話,則系統是先提示說語法錯誤,等到語法完全正確後,再提示說列名或表名錯誤。若能夠掌握這個順序的話,則在應用程序排錯的時候,可以節省時間。
4. 獲得對象解析鎖。當語法、語義都正確後,系統就會對我們需要查詢的對象加鎖。這主要是為了保障數據的一致性,防止我們在查詢的過程中,其他用戶對這個對象的結構發生改變。對於加鎖的原理與方法,我在其他文章中已經有專門敘述,在這里就略過不談了。
5. 數據訪問許可權的核對。當語法、語義通過檢查之後,客戶端還不一定能夠取得數據。伺服器進程還會檢查,你所連接的用戶是否有這個數據訪問的許可權。若你連接上伺服器的用戶不具有數據訪問許可權的話,則客戶端就不能夠取得這些數據。故,有時候我們查詢數據的時候,辛辛苦苦地把SQL語句寫好、編譯通過,但是,最後系統返回個 「沒有許可權訪問數據」的錯誤信息,讓我們氣半死。這在前端應用軟體開發調試的過程中,可能會碰到。所以,要注意這個問題,資料庫伺服器進程先檢查語法與語義,然後才會檢查訪問許可權。
6. 確定最佳執行計劃。當語句與語法都沒有問題,許可權也匹配的話,伺服器進程還是不會直接對資料庫文件進行查詢。伺服器進程會根據一定的規則,對這條語句進行優化。不過要注意,這個優化是有限的。一般在應用軟體開發的過程中,需要對資料庫的sql語言進行優化,這個優化的作用要大大地大於伺服器進程的自我優化。所以,一般在應用軟體開發的時候,資料庫的優化是少不了的。
當伺服器進程的優化器確定這條查詢語句的最佳執行計劃後,就會將這條SQL語句與執行計劃保存到數據高速緩存。如此的話,等以後還有這個查詢時,就會省略以上的語法、語義與許可權檢查的步驟,而直接執行SQL語句,提高SQL語句處理效率。
第三步:語句執行
語句解析只是對SQL語句的語法進行解析,以確保伺服器能夠知道這條語句到底表達的是什麼意思。等到語句解析完成之後,資料庫伺服器進程才會真正的執行這條SQL語句。
這個語句執行也分兩種情況。一是若被選擇行所在的數據塊已經被讀取到數據緩沖區的話,則伺服器進程會直接把這個數據傳遞給客戶端,而不是從資料庫文件中去查詢數據。若數據不在緩沖區中,則伺服器進程將從資料庫文件中查詢相關數據,並把這些數據放入到數據緩沖區中。
這里仍然要注意一點,就是Oracle資料庫中,定義了很多種類的高速緩存。像上面所說的SQL語句緩存與現在講的數據緩存。我們在學習資料庫的時候,需要對這些緩存有一個清晰的認識,並了解各個種類緩存的作用。這對於我們後續資料庫維護與資料庫優化是非常有用的。
第四步:提取數據
當語句執行完成之後,查詢到的數據還是在伺服器進程中,還沒有被傳送到客戶端的用戶進程。所以,在伺服器端的進程中,有一個專門負責數據提取的一段代碼。他的作用就是把查詢到的數據結果返回給用戶端進程,從而完成整個查詢動作。
從這整個查詢處理過程中,我們在資料庫開發或者應用軟體開發過程中,需要注意以下幾點:
一是要了解資料庫緩存跟應用軟體緩存是兩碼事情。資料庫緩存只有在資料庫伺服器端才存在,在客戶端是不存在的。只有如此,才能夠保證資料庫緩存中的內容跟資料庫文件的內容一致。才能夠根據相關的規則,防止數據臟讀、錯讀的發生。而應用軟體所涉及的數據緩存,由於跟資料庫緩存不是一碼事情,所以,應用軟體的數據緩存雖然可以提高數據的查詢效率,但是,卻打破了數據一致性的要求,有時候會發生臟讀、錯讀等情況的發生。所以,有時候,在應用軟體上有專門一個功能,用來在必要的時候清除數據緩存。不過,這個數據緩存的清除,也只是清除本機上的數據緩存,或者說,只是清除這個應用程序的數據緩存,而不會清除資料庫的數據緩存。
二是絕大部分SQL語句都是按照這個處理過程處理的。我們DBA或者基於Oracle資料庫的開發人員了解這些語句的處理過程,對於我們進行涉及到SQL語句的開發與調試,是非常有幫助的。有時候,掌握這些處理原則,可以減少我們排錯的時間。特別要注意,資料庫是把數據查詢許可權的審查放在語法語義的後面進行檢查的。所以,有時會若光用資料庫的許可權控制原則,可能還不能滿足應用軟體許可權控制的需要。此時,就需要應用軟體的前台設置,實現許可權管理的要求。而且,有時應用資料庫的許可權管理,也有點顯得繁瑣,會增加伺服器處理的工作量。因此,對於記錄、欄位等的查詢許可權控制,大部分程序涉及人員喜歡在應用程序中實現,而不是在資料庫上實現。