五月天久久久,国产精品成人播放,偷拍亚洲精品http://www.aygfsteel.com/xcp/category/41972.html茍有恒,何必三更起五更眠;<br/>最無益,只怕一日曝十日寒.zh-cnMon, 02 May 2016 16:34:23 GMTMon, 02 May 2016 16:34:23 GMT60oracle 反向索引http://www.aygfsteel.com/xcp/archive/2013/04/27/398512.htmlxcpxcpSat, 27 Apr 2013 09:05:00 GMThttp://www.aygfsteel.com/xcp/archive/2013/04/27/398512.htmlcreate index I_INFO_CLASSID_REVERSE on b_info(reverse(CLASSID));
analyze table b_info compute statistics for table for all indexes;
--都使用索引
select * from b_info where classid like '1E92C5409E99484%';
--都使用索引
select * from b_info where reverse(classid) like reverse('%33B27');

xcp 2013-04-27 17:05 發(fā)表評論
]]>
Oracle中的動態(tài)SQLhttp://www.aygfsteel.com/xcp/archive/2013/04/02/397279.htmlxcpxcpTue, 02 Apr 2013 05:20:00 GMThttp://www.aygfsteel.com/xcp/archive/2013/04/02/397279.htmlhttp://www.cnblogs.com/gaolonglong/archive/2011/05/31/2064790.html
http://www.aygfsteel.com/cheneyfree/archive/2007/12/17/168272.html


記?。簊elect的時候就不需要returning 
例:
 execute immediate T_SQL into T_COUNT;


xcp 2013-04-02 13:20 發(fā)表評論
]]>
oracle查詢所有用戶表的表名、主鍵名稱、索引、外鍵等http://www.aygfsteel.com/xcp/archive/2013/04/02/397265.htmlxcpxcpTue, 02 Apr 2013 01:53:00 GMThttp://www.aygfsteel.com/xcp/archive/2013/04/02/397265.htmlhttp://www.aygfsteel.com/xcp/comments/397265.htmlhttp://www.aygfsteel.com/xcp/archive/2013/04/02/397265.html#Feedback0http://www.aygfsteel.com/xcp/comments/commentRss/397265.htmlhttp://www.aygfsteel.com/xcp/services/trackbacks/397265.html
select t.*,i.index_type from user_ind_columns t,user_indexes i where t.index_name = i.index_name and t.table_name = i.table_name and t.table_name = 要查詢的表 
2、查找表的主鍵(包括名稱,構(gòu)成列):
select cu.* from user_cons_columns cu, user_constraints au where cu.constraint_name = au.constraint_name and au.constraint_type = 'P' and au.table_name = 要查詢的表 
3、查找表的唯一性約束(包括名稱,構(gòu)成列): 
select column_name from user_cons_columns cu, user_constraints au where cu.constraint_name = au.constraint_name and au.constraint_type = 'U' and au.table_name = 要查詢的表 
4、查找表的外鍵(包括名稱,引用表的表名和對應(yīng)的鍵名,下面是分成多步查詢): 
select * from user_constraints c where c.constraint_type = 'R' and c.table_name = 要查詢的表 
5、查詢外鍵約束的列名:
select * from user_cons_columns cl where cl.constraint_name = 外鍵名稱 
6、查詢引用表的鍵的列名:
select * from user_cons_columns cl where cl.constraint_name = 外鍵引用表的鍵名      

實例:
7、查詢沒有建立主鍵的表 
select u.table_name, u.num_rows
  from user_tables u
 where not exists (select cu.table_name
          from user_cons_columns cu, user_constraints au
         where cu.constraint_name = au.constraint_name
           and au.constraint_type = 'P'
           and au.table_name = u.table_name)
   and u.num_rows is not null
 order by u.num_rows desc;
8、查詢表記錄中有空值的索引字段
-- Create table
create table TEMP_INDEX
(
  ID          VARCHAR2(32),
  TABLE_NAME  VARCHAR2(100),
  COLUMN_NAME VARCHAR2(100),
  INDEX_NAME  VARCHAR2(100),
  SCSJ        DATE
)
tablespace JG_ZFGFH
  pctfree 10
  initrans 1
  maxtrans 255
  storage
  (
    initial 16
    minextents 1
    maxextents unlimited
  );
-- Add comments to the table 
comment on table TEMP_INDEX
  is '放入索引值有空的表和列';
-- Add comments to the columns 
comment on column TEMP_INDEX.ID
  is '自動生成';
comment on column TEMP_INDEX.TABLE_NAME
  is '表名';
comment on column TEMP_INDEX.COLUMN_NAME
  is '字段名稱';
comment on column TEMP_INDEX.INDEX_NAME
  is '索引名稱';
comment on column TEMP_INDEX.SCSJ
  is '生成時間';

create or replace procedure P_PROCESS_INDEX
/*********************************************************************************
         -----------功能:得到表索引字段中有空值字段
         -----------作者: Xcp
         -----------創(chuàng)建日期:2013-02-20
         -----------版本 v1.0
  ******************************************************************************
*/
 is
  cursor T_INDEX_CURSOR is
    select i.table_name, t.column_name, t.index_name
      from user_ind_columns t, user_indexes i, user_tab_cols c
     where t.index_name = i.index_name
       and t.column_name = c.column_name
       and t.table_name = i.table_name
       and c.table_name = i.table_name
     order by c.column_id;
  T_COUNT number:=0;
  T_SQL   varchar2(1000);
  T_PRE_TABLE_NAME varchar2(100);
begin
  --清空記錄保存表
  delete from TEMP_INDEX;
  commit;
  
  --重新清理
  for T_INDEX in T_INDEX_CURSOR loop
     --事務(wù)控制,每個表提交一次
     if T_PRE_TABLE_NAME is null then
       T_PRE_TABLE_NAME:=T_INDEX.Table_Name;
     elsif T_PRE_TABLE_NAME<>T_INDEX.Table_Name then
       commit
     end if;
     
     --求是該索引字段是否有空
     begin
       T_SQL:='select count(1)  from '||T_INDEX.TABLE_NAME||' where '||T_INDEX.Column_Name||' is null ' ;
       --dbms_output.put_line(T_SQL);
       execute immediate T_SQL into T_COUNT;
       --dbms_output.put_line(T_COUNT) ;  
       if T_COUNT>0 then
         insert into TEMP_INDEX values(sys_guid(),T_INDEX.Table_Name,T_INDEX.COLUMN_NAME,T_INDEX.Index_Name,sysdate);
       end if;
     exception
       when others then dbms_output.put_line('NO DATA FOUND!');
     end;
  end loop;  
  
  --事務(wù)控制,最后一個表的事務(wù)
  if T_INDEX_CURSOR%NOTFOUND then
    commit;
  end if;
end P_PROCESS_INDEX;


xcp 2013-04-02 09:53 發(fā)表評論
]]>
FORALL語句、FORALL語句自動回滾http://www.aygfsteel.com/xcp/archive/2011/12/31/367652.htmlxcpxcpSat, 31 Dec 2011 07:46:00 GMThttp://www.aygfsteel.com/xcp/archive/2011/12/31/367652.htmlhttp://www.aygfsteel.com/xcp/comments/367652.htmlhttp://www.aygfsteel.com/xcp/archive/2011/12/31/367652.html#Feedback0http://www.aygfsteel.com/xcp/comments/commentRss/367652.htmlhttp://www.aygfsteel.com/xcp/services/trackbacks/367652.html

FORALL語句

FORALL語句的一個關(guān)鍵性改進(jìn),它可大大簡化代碼,并且對于那些要在PL/SQL程序中更新很多行數(shù)據(jù)的程序來說,它可顯著提高其性能。

 

1:

FORALL來增強(qiáng)DML的處理能力

OracleOracle8i中的PL/SQL引入了兩個新的數(shù)據(jù)操縱語言(DML)語句:BULK COLLECTFORALL。這兩個語句在PL/SQL內(nèi)部進(jìn)行一種數(shù)組處理

 

;BULK COLLECT提供對數(shù)據(jù)的高速檢索,FORALL可大大改進(jìn)INSERT、UPDATEDELETE操作的性能。Oracle數(shù)據(jù)庫使用這些語句大大減少了

 

PL/SQLSQL語句執(zhí)行引擎的環(huán)境切換次數(shù),從而使其性能有了顯著提高。

 

 

使用BULK COLLECT,你可以將多個行引入一個或多個集合中,而不是單獨變量或記錄中。下面這個BULK COLLECT的實例是將標(biāo)題中包含

 

"PL/SQL"的所有書籍檢索出來并置于記錄的一個關(guān)聯(lián)數(shù)組中,它們都位于通向該數(shù)據(jù)庫的單一通道中。

DECLARE

   TYPE books_aat

 

      IS TABLE OF book%ROWTYPE

      INDEX BY PLS_INTEGER;

   books books_aat;

BEGIN

   SELECT *

     BULK COLLECT INTO book

     FROM books

    WHERE title LIKE '%PL/SQL%';

   ...

END;

 

 

類似地,FORALL將數(shù)據(jù)從一個PL/SQL集合傳送給指定的使用集合的表。下面的代碼實例給出一個過程,即接收書籍信息的一個嵌套表,并將該

 

集合(綁定數(shù)組)的全部內(nèi)容插入該書籍表中。注意,這個例子還利用了Oracle9iFORALL的增強(qiáng)功能,可以將一條記錄直接插入到表中。

 

BULK COLLECTFORALL都非常有用,它們不僅提高了性能,而且還簡化了為PL/SQL中的SQL操作所編寫的代碼。下面的多行FORALL INSERT相當(dāng)

 

清楚地說明了為什么PL/SQL被認(rèn)為是Oracle數(shù)據(jù)庫的最佳編程語言。

CREATE TYPE books_nt

IS TABLE OF book%ROWTYPE;

/

CREATE OR REPLACE PROCEDURE add_books (

 

books_in IN books_nt)

IS

BEGIN

FORALL book_index

    IN books_in.FIRST .. books_in.LAST

    INSERT INTO book

       VALUES books_in(book_index);

   ...

END;

 

 

不過在Oracle數(shù)據(jù)庫10g之前,以FORAll方式使用集合有一個重要的限制:該數(shù)據(jù)庫從IN范圍子句中的第一行到最后一行,依次讀取集合的內(nèi)容

 

。如果在該范圍內(nèi)遇到一個未定義的行,Oracle數(shù)據(jù)庫將引發(fā)ORA-22160異常事件:

 

 

ORA-22160: element at index [N] does not exist

 

 

對于FORALL的簡單應(yīng)用,這一規(guī)則不會引起任何麻煩。但是,如果想盡可能地充分利用FORALL,那么要求任意FORALL驅(qū)動數(shù)組都要依次填充可

 

能會增加程序的復(fù)雜性并降低性能。

 

Oracle數(shù)據(jù)庫10g中,PL/SQL現(xiàn)在在FORALL語句中提供了兩個新子句:INDICES OFVALUES OF,它們使你能夠仔細(xì)選擇驅(qū)動數(shù)組中該由擴(kuò)展

 

DML語句來處理的行。

當(dāng)綁定數(shù)組為稀疏數(shù)組或者包含有間隙時,INDICES OF會非常有用。該語句的語法結(jié)構(gòu)為:

FORALL indx IN INDICES

 

OF sparse_collection

INSERT INTO my_table

VALUES sparse_collection (indx);

 

VALUES OF用于一種不同的情況:綁定數(shù)組可以是稀疏數(shù)組,也可以不是,但我只想使用該數(shù)組中元素的一個子集。那么我就可以使用VALUES

 

OF來指向我希望在DML操作中使用的值。該語句的語法結(jié)構(gòu)為:

FORALL indx IN VALUES OF pointer_array

INSERT INTO my_table

VALUES binding_array (indx);

 

不用FOR循環(huán)而改用FORALL

假定我需要編寫一個程序,對合格員工(由comp_analysis.is_eligible函數(shù)確定)加薪,編寫關(guān)于不符合加薪條件的員工的報告并寫入

 

employee_history表。我在一個非常大的公司工作;我們的員工非常非常多。

 

對于一位PL/SQL開發(fā)人員來說,這并不是一項十分困難的工作。我甚至不需要使用BULK COLLECTFORALL就可以完成這項工作,如清單 1所示

 

,我使用一個CURSOR FOR循環(huán)和單獨的INSERTUPDATE語句。這樣的代碼簡潔明了;不幸地是,我花了10分鐘來運(yùn)行此代碼,我的"老式"方法

 

要運(yùn)行30分鐘或更長時間。

清單 1:

CREATE OR REPLACE PROCEDURE give_raises_in_department (

        dept_in IN employee.department_id%TYPE

      , newsal IN employee.salary%TYPE

     )

     IS

        CURSOR emp_cur

        IS

           SELECT employee_id, salary, hire_date

             FROM employee

            WHERE department_id = dept_in;

     BEGIN

        FOR emp_rec IN emp_cur

        LOOP

           IF comp_analysis.is_eligible (emp_rec.employee_id)

           THEN

              UPDATE employee

                 SET salary = newsal

               WHERE employee_id = emp_rec.employee_id;

           ELSE

              INSERT INTO employee_history

                          (employee_id, salary

                         , hire_date, activity

                          )

                   VALUES (emp_rec.employee_id, emp_rec.salary

                         , emp_rec.hire_date, 'RAISE DENIED'

                          );

           END IF;

        END LOOP;

     END give_raises_in_department;

 

 

好在我公司的數(shù)據(jù)庫升級到了Oracle9i,而且更幸運(yùn)的是,在最近的Oracle研討會上(以及Oracle技術(shù)網(wǎng)站提供的非常不錯的演示中)我了解

 

到了批量處理方法。所以我決定使用集合與批量處理方法重新編寫程序。寫好的程序如清單 2所示。

清單 2:

1 CREATE OR REPLACE PROCEDURE give_raises_in_department (

2     dept_in IN employee.department_id%TYPE

3   , newsal IN employee.salary%TYPE

4 )

5 IS

6     TYPE employee_aat IS TABLE OF employee.employee_id%TYPE

7        INDEX BY PLS_INTEGER;

8     TYPE salary_aat IS TABLE OF employee.salary%TYPE

9        INDEX BY PLS_INTEGER;

10     TYPE hire_date_aat IS TABLE OF employee.hire_date%TYPE

11        INDEX BY PLS_INTEGER;

12

13     employee_ids employee_aat;

14     salaries salary_aat;

15     hire_dates hire_date_aat;

16

17     approved_employee_ids employee_aat;

18

19     denied_employee_ids employee_aat;

20     denied_salaries salary_aat;

21     denied_hire_dates hire_date_aat;

22

23     PROCEDURE retrieve_employee_info

24     IS

25     BEGIN

26        SELECT employee_id, salary, hire_date

27        BULK COLLECT INTO employee_ids, salaries, hire_dates

28          FROM employee

29         WHERE department_id = dept_in;

30     END;

31

32     PROCEDURE partition_by_eligibility

33     IS

34     BEGIN

35        FOR indx IN employee_ids.FIRST .. employee_ids.LAST

36        LOOP

37           IF comp_analysis.is_eligible (employee_ids (indx))

38           THEN

39              approved_employee_ids (indx) := employee_ids (indx);

40           ELSE

41              denied_employee_ids (indx) := employee_ids (indx);

42              denied_salaries (indx) := salaries (indx);

43              denied_hire_dates (indx) := hire_dates (indx);

44           END IF;

45        END LOOP;

46     END;

47

48     PROCEDURE add_to_history

49     IS

50     BEGIN

51        FORALL indx IN denied_employee_ids.FIRST .. denied_employee_ids.LAST

52           INSERT INTO employee_history

53                       (employee_id

54                      , salary

55                      , hire_date, activity

56                       )

57                VALUES (denied_employee_ids (indx)

58                      , denied_salaries (indx)

59                      , denied_hire_dates (indx), 'RAISE DENIED'

60                       );

61     END;

62

63     PROCEDURE give_the_raise

64     IS

65     BEGIN

66        FORALL indx IN approved_employee_ids.FIRST .. approved_employee_ids.LAST

67           UPDATE employee

68              SET salary = newsal

69            WHERE employee_id = approved_employee_ids (indx);

70     END;

71 BEGIN

72     retrieve_employee_info;

73     partition_by_eligibility;

74     add_to_history;

75     give_the_raise;

76 END give_raises_in_department;

 

掃一眼清單1 和清單2 就會清楚地認(rèn)識到:改用集合和批量處理方法將增加代碼量和復(fù)雜性。但是,如果你需要大幅度提升性能,這還是值得

 

的。下面,我們不看這些代碼,我們來看一看當(dāng)使用FORALL時,用什么來處理CURSOR FOR循環(huán)內(nèi)的條件邏輯。

 

定義集合類型與集合

 

在清單 2中,聲明段的第一部分(第6行至第11行)定義了幾種不同的集合類型,與我將從員工表檢索出的列相對應(yīng)。我更喜歡基于employee%

 

ROWTYPE來聲明一個集合類型,但是FORALL還不支持對某些記錄集合的操作,在這樣的記錄中,我將引用個別字段。所以,我還必須為員工ID、

 

薪金和雇用日期分別聲明其各自的集合。

 

接下來為每一列聲明所需的集合(第13行至第21行)。首先定義與所查詢列相對應(yīng)的集合(第13行至第15行):

 

 

employee_ids employee_aat;

salaries salary_aat;

hire_dates hire_date_aat;

 

 

然后我需要一個新的集合,用于存放已被批準(zhǔn)加薪的員工的ID(第17行):

 

 

approved_employee_ids employee_aat;

 

 

最后,我再為每一列聲明一個集合(第19行至第21行),用于記錄沒有加薪資格的員工:

 

 

denied_employee_ids employee_aat;

denied_salaries salary_aat;

denied_hire_dates hire_date_aat;

 

深入了解代碼

 

數(shù)據(jù)結(jié)構(gòu)確定后,我們現(xiàn)在跳過該程序的執(zhí)行部分(第72行至第75行),了解如何使用這些集合來加速進(jìn)程。

 

 

retrieve_employee_info;

partition_by_eligibility;

add_to_history;

give_the_raise;

 

 

我編寫此程序使用了逐步細(xì)化法(也被稱為"自頂向下設(shè)計")。所以執(zhí)行部分不是很長,也不難理解,只有四行,按名稱對過程中的每一步進(jìn)

 

行了描述。首先檢索員工信息(指定部門的所有員工)。然后進(jìn)行劃分,將要加薪和不予加薪的員工區(qū)分出來。完成之后,我就可以將那些不

 

予加薪的員工添加至員工歷史表中,對其他員工進(jìn)行加薪。

 

以這種方式編寫代碼使最終結(jié)果的可讀性大大增強(qiáng)。因而我可以深入到該程序中對我有意義的任何部分。

 

有了已聲明的集合,我現(xiàn)在就可以使用BULK COLLECT來檢索員工信息(第23行至第30行)。這一部分有效地替代了CURSOR FOR循環(huán)。至此,數(shù)

 

據(jù)被加載到集合中。

 

劃分邏輯(第32行至第46行)要求對剛剛填充的集合中的每一行進(jìn)行檢查,看其是否符合加薪條件。如果符合,我就將該員工ID從查詢填充的

 

集合復(fù)制到符合條件的員工的集合。如果不符合,則復(fù)制該員工ID、薪金和雇用日期,因為這些都需要插入到employee_history表中。

 

初始數(shù)據(jù)現(xiàn)在已被分為兩個集合,可以將其分別用作兩個不同的FORALL語句(分別從第51行和第66行開始)的驅(qū)動器。我將不合格員工的集合

 

中的數(shù)據(jù)批量插入到employee_historyadd_to_history)表中,并通過give_the_raise過程,在employee表中批量更新合格員工的信息。

 

最后再仔細(xì)地看一看add_to_history(第48行至第61行),以此來結(jié)束對這個重新編寫的程序的分析。FORALL語句(第51行)包含一個IN子句

 

,它指定了要用于批量INSERT的行號范圍。在對程序進(jìn)行第二次重寫的說明中,我將把用于定義范圍的集合稱為"驅(qū)動集合"。但在

 

add_to_history的這一版本中,我簡單地假定: 使用在denied_employee_ids中定義的所有行。在INSERT自身內(nèi)部,關(guān)于不合格員工的三個集

 

合都會被用到;我將把這些集合稱為"數(shù)據(jù)集合"??梢钥吹?,驅(qū)動集合與數(shù)據(jù)集合無需匹配。在學(xué)習(xí)Oracle數(shù)據(jù)庫10g的新特性時,這是一個關(guān)

 

鍵點。

 

結(jié)果,清單 2 的行數(shù)大約是清單 1行數(shù)的2倍,但是清單 2 中的代碼會在要求的時間內(nèi)運(yùn)行。在使用Oracle數(shù)據(jù)庫10g之前,在這種情況下,

 

我只會對能夠在這一時間內(nèi)運(yùn)行代碼并開始下一個任務(wù)這一點感到高興。

 

不過,有了Oracle數(shù)據(jù)庫10g中最新版的PL/SQL,現(xiàn)在我就可以在性能、可讀性和代碼量方面作出更多的改進(jìn)。

VALUES OF用于此過程

 

Oracle數(shù)據(jù)庫10g中,可以指定FORALL語句使用的驅(qū)動集合中的行的子集??梢允褂靡韵聝煞N方法之一來定義該子集:

 

 

將數(shù)據(jù)集合中的行號與驅(qū)動集合中的行號進(jìn)行匹配。你需要使用INDICES OF子句。

將數(shù)據(jù)集合中的行號與驅(qū)動集合中所定義行中找到的值進(jìn)行匹配。這需要使用VALUES OF子句。

在對give_raises_in_department進(jìn)行第二次和最后一次改寫中我將使用VALUES OF子句。清單 3 包含這個版本的全部代碼。我將略過這一程序

 

中與前一版本相同的部分。

 

從聲明集合開始,請注意我不再另外定義集合來存放合格的和不合格的員工信息,而是在清單 3 (第17行至第21行)中聲明兩個"引導(dǎo)"集合:

 

一個用于符合加薪要求的員工,另一個用于不符合加薪要求的員工。這兩個集合的數(shù)據(jù)類型都是布爾型;不久將會看到,這些集合的數(shù)據(jù)類型

 

FORALL語句毫無關(guān)系。FORALL語句只關(guān)心定義了哪些行。 在員工表中擁有50 000行信息的give_raises_in_department的三種執(zhí)行方法的占

 

用時間 執(zhí)行方法 用時

CURSOR FOR循環(huán) 00:00:38.01

Oracle數(shù)據(jù)庫10g之前的批量處理 00:00:06.09

Oracle數(shù)據(jù)庫10g的批量處理 00:00:02.06

 

在員工表中擁有100,000行數(shù)據(jù)的give_raises_in_department的三種執(zhí)行方法的占用時間 執(zhí)行方法 用時

CURSOR FOR循環(huán) 00:00:58.01

Oracle數(shù)據(jù)庫10g之前的批量處理 00:00:12.00

Oracle數(shù)據(jù)庫10g的批量處理 00:00:05.05

 

 

1:處理50,000行和100,000行數(shù)據(jù)的用時測試結(jié)果

 

retrieve_employee_info子程序與前面的相同,但是對數(shù)據(jù)進(jìn)行劃分的方式完全不同(第32行至第44行)。我沒有將記錄從一個集合復(fù)制到另

 

一個集合(這個操作相對較慢),而只是確定與員工ID集合中的行號相匹配的相應(yīng)引導(dǎo)集合中的行(通過為其指定一個TRUE值)。

 

現(xiàn)在可以在兩個不同FORALL語句(由第49行和第65行開始)中,將approved_listdenied_list集合用作驅(qū)動集合。

 

為了插入到employee_history表中,我使用了如下語句:

 

 

FORALL indx IN VALUES OF denied_list

 

 

為了進(jìn)行更新(給員工進(jìn)行加薪),我使用這一格式:

 

 

FORALL indx IN VALUES OF approved_list

 

 

在這兩個DML語句中,數(shù)據(jù)集合是在BULK COLLECT 檢索步驟中填充的最初的集合;沒有進(jìn)行過復(fù)制。利用VALUES OF,Oracle數(shù)據(jù)庫在這些數(shù)據(jù)

 

集合的行中進(jìn)行篩選,僅使用行號與驅(qū)動集合中行號相匹配的行

利用本程序中的VALUES OF,可以避免復(fù)制對全部記錄進(jìn)行復(fù)制,而是用行號的一個簡單列表來替換它們。對于大型數(shù)組,進(jìn)行這些復(fù)制的開銷

 

是非??捎^的。為了測試Oracle數(shù)據(jù)庫10g的優(yōu)越性,我裝入employee表并對50,000行和100,000行的數(shù)據(jù)運(yùn)行測試。為了模擬更多的現(xiàn)實情況

 

,我將Oracle數(shù)據(jù)庫10g之前的批量處理的執(zhí)行方法作了修改以進(jìn)行集合內(nèi)容的多次復(fù)制。然后我使用SQL*Plus SET TIMING ON來顯示運(yùn)行各個

 

不同的執(zhí)行方法所用的時間。表 1 給出了結(jié)果。

 

從這些時間測定得到的結(jié)論非常清楚:由單個DML語句變?yōu)榕刻幚韺⒋蠓s短耗用時間,數(shù)據(jù)為50,000行時的用時由38秒減為6秒,數(shù)據(jù)為

 

100,000行時的用時由58秒減為12秒。而且,通過使用VALUES OF來避免復(fù)制數(shù)據(jù),我可以將用時縮短一半左右。

 

即使沒有性能上的改進(jìn),VALUES OF及其同類子句--INDICES OF也提高了PL/SQL語言的靈活性,使開發(fā)人員能夠更輕松地編寫出更直觀和更容易

 

維護(hù)的代碼。

 

在產(chǎn)品壽命這一點上,PL/SQL是一種成熟且功能強(qiáng)大的語言。因而,其很多新特性都是逐漸增加和改進(jìn)而成的。不過,這些新特性還是使應(yīng)用

 

程序的性能和開發(fā)人員的開發(fā)效率有了重大改變。VALUES OF就是這種特性的一個很好的例子。

 



xcp 2011-12-31 15:46 發(fā)表評論
]]>
使用Bulk Collect提高Oracle查詢效率http://www.aygfsteel.com/xcp/archive/2011/12/31/367650.htmlxcpxcpSat, 31 Dec 2011 07:03:00 GMThttp://www.aygfsteel.com/xcp/archive/2011/12/31/367650.htmlhttp://www.aygfsteel.com/xcp/comments/367650.htmlhttp://www.aygfsteel.com/xcp/archive/2011/12/31/367650.html#Feedback0http://www.aygfsteel.com/xcp/comments/commentRss/367650.htmlhttp://www.aygfsteel.com/xcp/services/trackbacks/367650.html
使用Bulk Collect提高Oracle查詢效率
Oracle8i中首次引入了Bulk Collect特性,該特性可以讓我們在PL/SQL中能使用批查詢,批查詢在某些情況下能顯著提高查詢效率?,F(xiàn)在,我們對該特性進(jìn)行一些簡單的測試和分析。
一、首先,我們創(chuàng)建一個表,并插入100000條記錄
在SQL/Plus中執(zhí)行下列腳本:
drop table empl_tbl
/
create table empl_tbl(last_name varchar2(20),
first_name varchar2(10),
salary number(10))
/
begin
for i in 30000..1029999 loop
insert into empl_tbl(last_name,first_name,salary) values('carl'||(i-3000),'wu'||(1003000-i),i);
end loop;
end;
/
commit
/
select count(*) from empl_tbl;
/
二、使用三種方法計算表中某一字段含有多少個不重復(fù)值
2.1 使用常規(guī)的Distinct來實現(xiàn)
SQL> select count(distinct last_name) from empl_tbl;
Distinct Last Name
------------------
            1000000
Executed in 1.531 seconds
我們可以看到,常規(guī)方法需要1.531 秒查出該表中有1000000個不重復(fù)的Last_name值。
2.2 使用游標(biāo)來實現(xiàn)
我們執(zhí)行下面語句來統(tǒng)計Last_name字段的不重復(fù)值個數(shù):
CREATE OR REPLACE PROCEDURE tttt IS
  all_rows number(10);
  temp_last_name empl_tbl.last_name%type;
begin
  all_rows:=0;
  temp_last_name:=' ';
  for cur in (select last_name from empl_tbl order by last_name) loop
      if cur.last_name!=temp_last_name then
       all_rows:=all_rows+1;
      end if;
      temp_last_name:=cur.last_name;
  end loop;
  dbms_output.put_line('all_rows are '||all_rows);
end;
請注意上面代碼中的黑體部分使用了一個For Loop游標(biāo),為了提高程序可讀性,我們沒有顯示定義游標(biāo)變量。
執(zhí)行結(jié)果:
all_rows are 1000000
PL/SQL procedure successfully completed
Executed in 10.39 seconds
游標(biāo)需要10.396秒才能查出該表中有1000000個不重復(fù)的Last_name值,所耗時間是Distinct查詢的10倍多。
2.3 使用Bulk Collect批查詢來實現(xiàn)
示例代碼如下:
declare
  all_rows number(10);
  --首先,定義一個Index-by表數(shù)據(jù)類型
  type last_name_tab is table of empl_tbl.last_name%type index by binary_integer;
  last_name_arr last_name_tab;
  --定義一個Index-by表集合變量
  temp_last_name empl_tbl.last_name%type;
 
begin
  all_rows:=0;
  temp_last_name:=' ';
  --使用Bulk Collect批查詢來充填集合變量
  select last_name bulk collect into last_name_arr from empl_tbl;
 
  for i in 1..last_name_arr.count loop
      if temp_last_name!=last_name_arr(i) then
       all_rows:=all_rows+1;
      end if;
      temp_last_name:=last_name_arr(i);
  end loop;
 dbms_output.put_line('all_rows are '||all_rows);
end;
請注意上面代碼中,我們首先定義了一個Index-by表數(shù)據(jù)類型last_name_tab,然后定義了一個該集合數(shù)據(jù)類型的變量last_name_arr,最后我們使用Bulk Collect批查詢來充填last_name_arr,請注意它
的使用語法。
執(zhí)行結(jié)果:
all_rows are 1000000
PL/SQL procedure successfully completed
Executed in 2.343 seconds
從上面執(zhí)行結(jié)果,我們可以看到,Bulk Collect批查詢只需要2.343 秒就能查出該表中有1000000個不重復(fù)的Last_name值,所耗時間只有游標(biāo)查詢的1/2.5。


三. 測試結(jié)果分析
為什么會出現(xiàn)上面的結(jié)果呢?我們可以使用Oracle的SQL_Trace來分析一下結(jié)果。在SQL命令行中,使用alter session set sql_trace=true語句打開Oracle的Trace,然后在命令行中執(zhí)行上面三種查詢并使用TKPROF工具生成Trace報告。
3.1 常規(guī)Distinct查詢結(jié)果分析
3.2 游標(biāo)查詢效率分析
3.3 Bulk Collect的查詢效率分析

四. 結(jié)論
通過上面的測試和分析,我們可以看到Bulk Collect批查詢在某種程度上可以提高查詢效率,它首先將所需數(shù)據(jù)讀入內(nèi)存,然后再統(tǒng)計分析,這樣就可以提高查詢效率。但是,如果Oracle數(shù)據(jù)庫的內(nèi)存較小,Shared Pool Size不足以保存Bulk Collect批查詢結(jié)果,那么該方法需要將Bulk Collect的集合結(jié)果保存在磁盤上,在這種情況下,Bulk Collect方法的效率反而不如其他兩種方法,有興趣的讀者可以進(jìn)一步測試。
另外,除了Bulk Collect批查詢外,我們還可以使用FORALL語句來實現(xiàn)批插入、刪除和更新,這在大批量數(shù)據(jù)操作時可以顯著提高執(zhí)行效率。


xcp 2011-12-31 15:03 發(fā)表評論
]]>
oracle_常用系統(tǒng)表http://www.aygfsteel.com/xcp/archive/2011/12/31/367624.htmlxcpxcpSat, 31 Dec 2011 03:04:00 GMThttp://www.aygfsteel.com/xcp/archive/2011/12/31/367624.htmlhttp://www.aygfsteel.com/xcp/comments/367624.htmlhttp://www.aygfsteel.com/xcp/archive/2011/12/31/367624.html#Feedback0http://www.aygfsteel.com/xcp/comments/commentRss/367624.htmlhttp://www.aygfsteel.com/xcp/services/trackbacks/367624.html

dba_開頭.....

 

   dba_users      數(shù)據(jù)庫用戶信息

 

   dba_segments 表段信息

 

   dba_extents    數(shù)據(jù)區(qū)信息

 

   dba_objects    數(shù)據(jù)庫對象信息

 

   dba_tablespaces   數(shù)據(jù)庫表空間信息

 

   dba_data_files    數(shù)據(jù)文件設(shè)置信息

 

   dba_temp_files   臨時數(shù)據(jù)文件信息

 

   dba_rollback_segs   回滾段信息

 

   dba_ts_quotas   用戶表空間配額信息

 

   dba_free_space 數(shù)據(jù)庫空閑空間信息

 

   dba_profiles   數(shù)據(jù)庫用戶資源限制信息

 

   dba_sys_privs   用戶的系統(tǒng)權(quán)限信息

 

   dba_tab_privs 用戶具有的對象權(quán)限信息

 

   dba_col_privs 用戶具有的列對象權(quán)限信息

 

   dba_role_privs 用戶具有的角色信息

 

   dba_audit_trail 審計跟蹤記錄信息

 

   dba_stmt_audit_opts 審計設(shè)置信息

 

   dba_audit_object   對象審計結(jié)果信息

 

   dba_audit_session 會話審計結(jié)果信息

 

   dba_indexes 用戶模式的索引信息

 

user_開頭

 

   user_objects   用戶對象信息

 

   user_source   數(shù)據(jù)庫用戶的所有資源對象信息

 

   user_segments   用戶的表段信息

 

   user_tables    用戶的表對象信息

 

   user_tab_columns   用戶的表列信息

 

   user_constraints   用戶的對象約束信息

 

   user_sys_privs   當(dāng)前用戶的系統(tǒng)權(quán)限信息

 

   user_tab_privs   當(dāng)前用戶的對象權(quán)限信息

 

   user_col_privs   當(dāng)前用戶的表列權(quán)限信息

 

   user_role_privs   當(dāng)前用戶的角色權(quán)限信息

 

   user_indexes   用戶的索引信息

 

   user_ind_columns 用戶的索引對應(yīng)的表列信息

 

   user_cons_columns   用戶的約束對應(yīng)的表列信息

 

   user_clusters   用戶的所有簇信息

 

   user_clu_columns 用戶的簇所包含的內(nèi)容信息

 

   user_cluster_hash_expressions   散列簇的信息

 

v$開頭

 

   v$database    數(shù)據(jù)庫信息

 

   v$datafile   數(shù)據(jù)文件信息

 

   v$controlfile 控制文件信息

 

   v$logfile   重做日志信息

 

   v$instance   數(shù)據(jù)庫實例信息

 

   v$log   日志組信息

 

   v$loghist 日志歷史信息

 

   v$sga   數(shù)據(jù)庫SGA信息

 

   v$parameter 初始化參數(shù)信息

 

   v$process   數(shù)據(jù)庫服務(wù)器進(jìn)程信息

 

   v$bgprocess   數(shù)據(jù)庫后臺進(jìn)程信息

 

   v$controlfile_record_section   控制文件記載的各部分信息

 

   v$thread   線程信息

 

   v$datafile_header   數(shù)據(jù)文件頭所記載的信息

 

   v$archived_log 歸檔日志信息

 

   v$archive_dest   歸檔日志的設(shè)置信息

 

   v$logmnr_contents   歸檔日志分析的DML DDL結(jié)果信息

 

   v$logmnr_dictionary   日志分析的字典文件信息

 

   v$logmnr_logs   日志分析的日志列表信息

 

   v$tablespace   表空間信息

 

   v$tempfile   臨時文件信息

 

   v$filestat   數(shù)據(jù)文件的I/O統(tǒng)計信息

 

   v$undostat   Undo數(shù)據(jù)信息

 

   v$rollname   在線回滾段信息

 

   v$session   會話信息

 

   v$transaction 事務(wù)信息

 

   v$rollstat    回滾段統(tǒng)計信息

 

   v$pwfile_users   特權(quán)用戶信息

 

   v$sqlarea     當(dāng)前查詢過的sql語句訪問過的資源及相關(guān)的信息

 

   v$sql           v$sqlarea基本相同的相關(guān)信息

 

   v$sysstat    數(shù)據(jù)庫系統(tǒng)狀態(tài)信息

 

all_開頭

 

   all_users   數(shù)據(jù)庫所有用戶的信息

 

   all_objects   數(shù)據(jù)庫所有的對象的信息

 

   all_def_audit_opts   所有默認(rèn)的審計設(shè)置信息

 

   all_tables   所有的表對象信息

 

   all_indexes 所有的數(shù)據(jù)庫對象索引的信息

 

session_開頭

 

   session_roles   會話的角色信息

 

   session_privs   會話的權(quán)限信息

 

index_開頭

 

   index_stats   索引的設(shè)置和存儲信息

 

偽表

 

   dual   系統(tǒng)偽列表信息



xcp 2011-12-31 11:04 發(fā)表評論
]]>
oracle 查看用戶 用戶權(quán)限 用戶表空間 用戶默認(rèn)表空間[轉(zhuǎn)]http://www.aygfsteel.com/xcp/archive/2011/12/31/367623.htmlxcpxcpSat, 31 Dec 2011 02:42:00 GMThttp://www.aygfsteel.com/xcp/archive/2011/12/31/367623.htmlhttp://www.aygfsteel.com/xcp/comments/367623.htmlhttp://www.aygfsteel.com/xcp/archive/2011/12/31/367623.html#Feedback0http://www.aygfsteel.com/xcp/comments/commentRss/367623.htmlhttp://www.aygfsteel.com/xcp/services/trackbacks/367623.html
1、查看所有用戶
select * from dba_users;//dba
select * from all_users;//all
select * from user_users;//當(dāng)前
2、查看當(dāng)前用戶連接:
select * from v$Session;
3、查看當(dāng)前用戶權(quán)限:
select * from session_privs;
4、查看所有用戶系統(tǒng)權(quán)限
select * from dba_sys_privs;
select * from user_sys_privs;
5、查看所有用戶對象權(quán)限
select * from dab_tab_privs;
select * from all_tab_privs;
select * from user_tab_privs;
6、查看所有角色
select * from dba_roles;
select * from dba_role_privs;
select * from user_role_privs;
7、查看所有表空間、臨時表空間等信息
select tablespace_name,file_name,bytes file_size,autoextensible from dba_data_files;
select tablespace_name,file_name,bytes file_size,autoextensible from dba_temp_files;
8、查看用戶表空間使用情況:
select 
  a.file_id "FileNo",a.tablespace_name "Tablespace_name",
  a.bytes "Bytes",a.bytes-sum(nvl(b.bytes,0)) "Used", sum(nvl(b.bytes,0)) "Free",sum(nvl(b.bytes,0))/a.bytes*100 "%free" 
from dba_data_files a,dba_free_space b 
where a.file_id=b.file_id(+
group by a.tablespace_name , a.file_id,a.bytes 
order by a.tablespace_name; 
9、查看用戶所有對象
select table_name,num_rows from user_tables;
select * from all_tables;
10、詢所有函數(shù)和存儲過程
select * from dba_source;
select * from user_source;


xcp 2011-12-31 10:42 發(fā)表評論
]]>
oracle數(shù)據(jù)恢復(fù)http://www.aygfsteel.com/xcp/archive/2011/12/23/367052.htmlxcpxcpFri, 23 Dec 2011 02:33:00 GMThttp://www.aygfsteel.com/xcp/archive/2011/12/23/367052.htmlhttp://www.aygfsteel.com/xcp/comments/367052.htmlhttp://www.aygfsteel.com/xcp/archive/2011/12/23/367052.html#Feedback2http://www.aygfsteel.com/xcp/comments/commentRss/367052.htmlhttp://www.aygfsteel.com/xcp/services/trackbacks/367052.html1.
表查詢閃回
create table xcp as (select * from b_za_bzdzkxx);
select * from xcp;
select count(1) from xcp;--22001
select count(1) from xcp t where t.dzbh like '510521%';--7011
delete from xcp t where t.dzbh like '510521%';
select count(1) from xcp;--14990
--查找指定時間點前的數(shù)據(jù)
select count(1) from xcp as of timestamp to_timestamp('2011-12-23 10:49:30','yyyy-MM-dd hh24:mi:ss');--22001

select * from xcp for update;--添加一條記錄
select count(1) from xcp;--14991

--恢復(fù)指定時間點的前delete數(shù)據(jù)(將刪除恢復(fù)時間點后面的數(shù)據(jù))

alter table xcp enable row movement;--啟動的行移動功能
flashback table xcp to timestamp to_timestamp('2011-12-23 10:49:30','yyyy-MM-dd hh24:mi:ss');
select count(1) from xcp;--22001

--恢復(fù)指定時間點的前delete數(shù)據(jù),并保留恢復(fù)時間點后面的數(shù)據(jù)

create table xcp2 as (select * from xcp t where t.createdtime>to_timestamp('2011-12-23 10:49:30','yyyy-MM-dd hh24:mi:ss'));
select * from xcp2;--臨時表
alter table xcp enable row movement;--啟動的行移動功能
flashback table xcp to timestamp to_timestamp('2011-12-23 10:49:30,'yyyy-MM-dd hh24:mi:ss');
select count(1) from xcp;--22001
insert into xcp select * from xcp2 --將臨時表的數(shù)據(jù)再插入到源表
select count(1) from xcp;--22002


2.刪除
閃回[10g+]
    刪除閃回為刪除oracle 10G提供了一個數(shù)據(jù)庫安全機(jī)制,當(dāng)用戶刪除一個表時,oracle 10G會將該表放到回收站中,回收站中的對象一直會保留,直到用戶決定永久刪除它們或出現(xiàn)表空間的空間不足時才會被刪除?;厥照臼且粋€虛擬容器,用于存儲所有被刪除的對象。數(shù)據(jù)字典user_tables中的列dropped表示被刪除的表,查詢方法如下:
select table_name,dropped from user_tables;
--設(shè)置數(shù)據(jù)庫是否啟用回收站
alert session set recyclebin = off;
--查詢回收站對象
select * from recyclebin;
select * from user_recyclebin;
select * from dba_recyclebin;


drop table xcp;
select count(1) from xcp;--0
--恢復(fù)drop的表
flashback table xcp to before drop;
select count(1) from xcp;--22001

如果不知道原表名,可以直接使用回收站中的名稱進(jìn)行閃回..
flashback table "BIN$JiXyAUO4R+u3qNVfQK/Kiw==$0" to before drop;
在回收的同時可以修改表名
flashback table "
BIN$JiXyAUO4R+u3qNVfQK/Kiw==$0" to before drop rename to xcp1;

--真正刪除一個表,而不進(jìn)入回收站,可以在刪除表時增加purge選項
drop table xcp1 purge;
--也可以從回收站永久性刪除表
purge table xcp1;
--刪除當(dāng)前用戶回收站
purge recyclebin
--刪除全體用戶在回收站的資源
purge dba_resyclebin



3.數(shù)據(jù)庫閃口
[10g+]
    使用數(shù)據(jù)庫閃回功能,可以使數(shù)據(jù)庫回到過去某一狀態(tài),語法如下:
        sql: alter database flashback on;
        sql: flashback database to scn 46963;
        sql: flashback database to timestamp to_timestamp('2007-2-12 12:00:00','yyyy-MM-dd hh24:mi:ss');



注:表結(jié)構(gòu)修改后不能直接恢復(fù)
http://blog.csdn.net/colin_liu2009/article/details/6906548

http://www.xifenfei.com/2012/06/%E5%88%A9%E7%94%A8flashback-database%E5%AE%9E%E7%8E%B0%E9%83%A8%E5%88%86%E5%AF%B9%E8%B1%A1%E5%9B%9E%E6%BB%9A.html


xcp 2011-12-23 10:33 發(fā)表評論
]]>
oracle 取得表字段注釋http://www.aygfsteel.com/xcp/archive/2011/12/09/365961.htmlxcpxcpFri, 09 Dec 2011 07:27:00 GMThttp://www.aygfsteel.com/xcp/archive/2011/12/09/365961.htmlhttp://www.aygfsteel.com/xcp/comments/365961.htmlhttp://www.aygfsteel.com/xcp/archive/2011/12/09/365961.html#Feedback1http://www.aygfsteel.com/xcp/comments/commentRss/365961.htmlhttp://www.aygfsteel.com/xcp/services/trackbacks/365961.htmlselect * from user_tab_cols b where b.table_name='B_ZA_CZRKXX' ORDER BY b.internal_column_id;
--USER_TAB_COLUMNS,以避免獲取到oracle自行添加的隱藏字段
select * from user_tab_columns b where b.TABLE_NAME='B_ZA_CZRKXX';
select * from user_tab_comments b where b.TABLE_NAME='B_ZA_CZRKXX';
select * from user_col_comments b where b.TABLE_NAME='B_ZA_CZRKXX';


select col.COLUMN_NAME ,com.comments,col.DATA_TYPE
from user_tab_columns col
inner join user_col_comments com
on col.TABLE_NAME='B_ZA_CZRKXX' and
   col.TABLE_NAME=com.TABLE_NAME and
   col.COLUMN_NAME=com.COLUMN_NAME
order by col.COLUMN_ID



xcp 2011-12-09 15:27 發(fā)表評論
]]>
Oracle SQL優(yōu)化 http://www.aygfsteel.com/xcp/archive/2011/09/29/359791.htmlxcpxcpThu, 29 Sep 2011 07:47:00 GMThttp://www.aygfsteel.com/xcp/archive/2011/09/29/359791.htmlhttp://www.aygfsteel.com/xcp/comments/359791.htmlhttp://www.aygfsteel.com/xcp/archive/2011/09/29/359791.html#Feedback0http://www.aygfsteel.com/xcp/comments/commentRss/359791.htmlhttp://www.aygfsteel.com/xcp/services/trackbacks/359791.html
  • 盡量少用IN操作符,基本上所有的IN操作符都可以用EXISTS代替
  •         用IN寫出來的SQL的優(yōu)點是比較容易寫及清晰易懂,但是用IN的SQL性能總是比較低的,從ORACLE執(zhí)行的步驟來分析用IN的SQL與不用IN的SQL有以下區(qū)別:
           ORACLE 試圖將其轉(zhuǎn)換成多個表的連接,如果轉(zhuǎn)換不成功則先執(zhí)行IN里面的子查詢,再查詢外層的表記錄,如果轉(zhuǎn)換成功則直接采用多個表的連接方式查詢。由此可見用 IN的SQL至少多了一個轉(zhuǎn)換的過程。一般的SQL都可以轉(zhuǎn)換成功,但對于含有分組統(tǒng)計等方面的SQL就不能轉(zhuǎn)換了。

            Oracle在執(zhí)行IN子查詢時,首先執(zhí)行子查詢,將查詢結(jié)果放入臨時表再執(zhí)行主查詢。而EXIST則是首先檢查主查詢,然后運(yùn)行子查詢直到找到第一個匹配項。NOT EXISTS比NOT IN效率稍高。但具體在選擇IN或EXIST操作時,要根據(jù)主子表數(shù)據(jù)量大小來具體考慮。
               

            SELECT * FROM  EMP  WHERE  EMPNO > 0  AND  EXISTS (SELECT ‘X'  FROM DEPT  WHERE  DEPT.DEPTNO = EMP.DEPTNO  AND  LOC = ‘MELB')
            SELECT  * FROM  EMP  WHERE  EMPNO > 0  AND  DEPTNO IN(SELECT DEPTNO  FROM  DEPT  WHERE  LOC = ‘MELB')


            推薦方案:在業(yè)務(wù)密集的SQL當(dāng)中盡量不采用IN操作符。


    • 不用NOT IN操作符,可以用NOT EXISTS或者外連接+替代
            此操作是強(qiáng)列推薦不使用的,因為它不能應(yīng)用表的索引。

            推薦方案:用NOT EXISTS 或(外連接+判斷為空)方案代替


    • 不用“<>”或者“!=”操作符。對不等于操作符的處理會造成全表掃描,可以用“<” or “>”代替

            不等于操作符是永遠(yuǎn)不會用到索引的,因此對它的處理只會產(chǎn)生全表掃描。

            推薦方案:用其它相同功能的操作運(yùn)算代替,如:
            1)a<>0 改為 a>0 or a<0
            2)a<>’’ 改為 a>’’

    • Where子句中出現(xiàn)IS NULL或者IS NOT NULL時,Oracle會停止使用索引而執(zhí)行全表掃描。可以考慮在設(shè)計表時,對索引列設(shè)置為NOT NULL。這樣就可以用其他操作來取代判斷NULL的操作

            IS NULL 或IS NOT NULL操作(判斷字段是否為空)
            判斷字段是否為空一般是不會應(yīng)用索引的,因為B樹索引是不索引空值的。

            推薦方案:
            用其它相同功能的操作運(yùn)算代替,如:
            1)a is not null 改為 a>0 或a>’’等。
            2)不允許字段為空,而用一個缺省值代替空值,如業(yè)擴(kuò)申請中狀態(tài)字段不允許為空,缺省為申請。
            3) 建立位圖索引(有分區(qū)的表不能建,位圖索引比較難控制,如字段值太多索引會使性能下降,多人更新操作會增加數(shù)據(jù)塊鎖的現(xiàn)象)

        
            當(dāng)通配符“%”或者“_”作為查詢字符串的第一個字符時,索引不會被使用
           

            對于有連接的列“||”,最后一個連接列索引會無效。盡量避免連接,可以分開連接或者使用不作用在列上的函數(shù)替代。


            如果索引不是基于函數(shù)的,那么當(dāng)在Where子句中對索引列使用函數(shù)時,索引不再起作用。
            Where子句中避免在索引列上使用計算,否則將導(dǎo)致索引失效而進(jìn)行全表掃描。
            對數(shù)據(jù)類型不同的列進(jìn)行比較時,會使索引失效。


          

  •     > 及 < 操作符(大于或小于操作符)
  •        大于或小于操作符一般情況下是不用調(diào)整的,因為它有索引就會采用索引查找,但有的情況下可以對它進(jìn)行優(yōu)化,如一個表有100萬記錄,一個數(shù)值型字段A, 30萬記錄的A=0,30萬記錄的A=1,39萬記錄的A=2,1萬記錄的A=3。那么執(zhí)行A>2與A>=3的效果就有很大的區(qū)別了,因為 A>2時ORACLE會先找出為2的記錄索引再進(jìn)行比較,而A>=3時ORACLE則直接找到=3的記錄索引。

           推薦方案:用“>=”替代“>”。
            例: A>2 改為 A>=3
                   A<2 改為 A<=1


    • UNION操作符

           UNION在進(jìn)行表鏈接后會篩選掉重復(fù)的記錄,所以在表鏈接后會對所產(chǎn)生的結(jié)果集進(jìn)行排序運(yùn)算,刪除重復(fù)的記錄再返回結(jié)果。實際大部分應(yīng)用中是不會產(chǎn)生重復(fù)的記錄,最常見的是過程表與歷史表UNION。如:

        select * from gc_dfys
        union
        select * from ls_jg_dfys

        這個SQL在運(yùn)行時先取出兩個表的結(jié)果,再用排序空間進(jìn)行排序刪除重復(fù)的記錄,最后返回結(jié)果集,如果表數(shù)據(jù)量大的話可能會導(dǎo)致用磁盤進(jìn)行排序。

        推薦方案:采用UNION ALL操作符替代UNION,因為UNION ALL操作只是簡單的將兩個結(jié)果合并后就返回。

        select * from gc_dfys
        union all
        select * from ls_jg_dfys


     

    • LIKE操作符

            LIKE 操作符可以應(yīng)用通配符查詢,里面的通配符組合可能達(dá)到幾乎是任意的查詢,但是如果用得不好則會產(chǎn)生性能上的問題,如LIKE ‘%5400%’ 這種查詢不會引用索引,而LIKE ‘X5400%’則會引用范圍索引。一個實際例子:用YW_YHJBQK表中營業(yè)編號后面的戶標(biāo)識號可來查詢營業(yè)編號 YY_BH LIKE ‘%5400%’ 這個條件會產(chǎn)生全表掃描,如果改成YY_BH LIKE ’X5400%’ OR YY_BH LIKE ’B5400%’ 則會利用YY_BH的索引進(jìn)行兩個范圍的查詢,性能肯定大大提高。



    • SQL書寫的影響(共享SQL語句可以提高操作效率)

        同一功能同一性能不同寫法SQL的影響

        如一個SQL在A程序員寫的為
        Select * from zl_yhjbqk

        B程序員寫的為
        Select * from dlyx.zl_yhjbqk(帶表所有者的前綴)

        C程序員寫的為
        Select * from DLYX.ZLYHJBQK(大寫表名)

        D程序員寫的為
        Select *  from DLYX.ZLYHJBQK(中間多了空格)

         以上四個SQL在ORACLE分析整理之后產(chǎn)生的結(jié)果及執(zhí)行的時間是一樣的,但是從ORACLE共享內(nèi)存SGA的原理,可以得出ORACLE對每個SQL 都會對其進(jìn)行一次分析,并且占用共享內(nèi)存,如果將SQL的字符串及格式寫得完全相同則ORACLE只會分析一次,共享內(nèi)存也只會留下一次的分析結(jié)果,這不僅可以減少分析SQL的時間,而且可以減少共享內(nèi)存重復(fù)的信息,ORACLE也可以準(zhǔn)確統(tǒng)計SQL的執(zhí)行頻率。

        推薦方案:不同區(qū)域出現(xiàn)的相同的Sql語句,要保證查詢字符完全相同,以利用SGA共享池,防止相同的Sql語句被多次分析。




     

    • WHERE后面的條件順序影響

           Oracle從下到上處理Where子句中多個查詢條件,所以表連接語句應(yīng)寫在其他Where條件前,可以過濾掉最大數(shù)量記錄的條件必須寫在Where子句的末尾。
          
           WHERE子句后面的條件順序?qū)Υ髷?shù)據(jù)量表的查詢會產(chǎn)生直接的影響,如

        Select * from zl_yhjbqk where dy_dj = '1KV以下' and xh_bz=1

        Select * from zl_yhjbqk where xh_bz=1  and dy_dj = '1KV以下'

        以上兩個SQL中dy_dj(電壓等級)及xh_bz(銷戶標(biāo)志)兩個字段都沒進(jìn)行索引,所以執(zhí)行的時候都是全表掃描,第一條SQL的dy_dj = '1KV以下'條件在記錄集內(nèi)比率為99%,而xh_bz=1的比率只為0.5%,在進(jìn)行第一條SQL的時候99%條記錄都進(jìn)行dy_dj及xh_bz的比較,而在進(jìn)行第二條SQL的時候0.5%條記錄都進(jìn)行dy_dj及xh_bz的比較,以此可以得出第二條SQL的CPU占用率明顯比第一條低。

    • 查詢表順序的影響

           Oracle從右到左處理From子句中的表名,所以在From子句中包含多個表的情況下,將記錄最少的表放在最后。(只在采用RBO優(yōu)化時有效)

           在FROM后面的表中的列表順序會對SQL執(zhí)行性能影響,在沒有索引及ORACLE沒有對表進(jìn)行統(tǒng)計分析的情況下ORACLE會按表出現(xiàn)的順序進(jìn)行鏈接,由此因為表的順序不對會產(chǎn)生十分耗服務(wù)器資源的數(shù)據(jù)交叉。(注:如果對表進(jìn)行了統(tǒng)計分析, ORACLE會自動先進(jìn)小表的鏈接,再進(jìn)行大表的鏈接)。

    • Order By語句中的非索引列會降低性能,可以通過添加索引的方式處理。嚴(yán)格控制在Order By語句中使用表達(dá)式
    • 當(dāng)在Sql語句中連接多個表時,使用表的別名,并將之作為每列的前綴。這樣可以減少解析時間
    • 多利用內(nèi)部函數(shù)提高Sql效率
    •  SQL語句索引的利用
      • 對操作符的優(yōu)化(見前面)
      • 對條件字段的一些優(yōu)化
        • 采用函數(shù)處理的字段不能利用索引
              如:
            substr(hbs_bh,1,4)=’5400’,優(yōu)化處理:hbs_bh like ‘5400%’

            trunc(sk_rq)=trunc(sysdate), 優(yōu)化處理:sk_rq>=trunc(sysdate) and sk_rq<trunc(sysdate+1)
        • 進(jìn)行了顯式或隱式的運(yùn)算的字段不能進(jìn)行索引
              如:

            ss_df+20>50,優(yōu)化處理:ss_df>30

            ‘X’||hbs_bh>’X5400021452’,優(yōu)化處理:hbs_bh>’5400021542’

            sk_rq+5=sysdate,優(yōu)化處理:sk_rq=sysdate-5

            hbs_bh=5401002554,優(yōu)化處理:hbs_bh=’ 5401002554’,注:此條件對hbs_bh 進(jìn)行隱式的to_number轉(zhuǎn)換,因為hbs_bh字段是字符型。
        • 條件內(nèi)包括了多個本表的字段運(yùn)算時不能進(jìn)行索引
              ys_df>cx_df,無法進(jìn)行優(yōu)化

              qc_bh||kh_bh=’5400250000’,優(yōu)化處理:qc_bh=’5400’ and kh_bh=’250000’



        可能引起全表掃描的操作

    • 在索引列上使用NOT或者“<>”
    • 對索引列使用函數(shù)或者計算
    • NOT IN操作
    • 通配符位于查詢字符串的第一個字符
    • IS NULL或者IS NOT NULL
    • 多列索引,但它的第一個列并沒有被Where子句引用


           ORACLE在SQL執(zhí)行分析方面已經(jīng)比較成熟,如果分析執(zhí)行的路徑不對首先應(yīng)在數(shù)據(jù)庫結(jié)構(gòu)(主要是索引)、服務(wù)器當(dāng)前性能(共享內(nèi)存、磁盤文件碎片)、數(shù)據(jù)庫對象(表、索引)統(tǒng)計信息是否正確這幾方面分析。






    --備注:多表查詢時,記錄最少的表放到最后



    xcp 2011-09-29 15:47 發(fā)表評論
    ]]>
    Oracle樹查詢及相關(guān)函數(shù)http://www.aygfsteel.com/xcp/archive/2011/09/29/359788.htmlxcpxcpThu, 29 Sep 2011 07:10:00 GMThttp://www.aygfsteel.com/xcp/archive/2011/09/29/359788.htmlhttp://www.aygfsteel.com/xcp/comments/359788.htmlhttp://www.aygfsteel.com/xcp/archive/2011/09/29/359788.html#Feedback0http://www.aygfsteel.com/xcp/comments/commentRss/359788.htmlhttp://www.aygfsteel.com/xcp/services/trackbacks/359788.htmlselect...start with... connect by ...prior 語法了。依托于該語法,我們可以將一個表形結(jié)構(gòu)的中以樹的順序列出來。在下面列述了Oracle中樹型查詢的常用查詢方式以及經(jīng)常使用的與樹查詢相關(guān)的Oracle特性函數(shù)等,在這里只涉及到一張表中的樹查詢方式而不涉及多表中的關(guān)聯(lián)等。

          以我做過的一個項目中的表為例,表結(jié)構(gòu)如下:

    CREATE TABLE FLFL
    (
      ID      NUMBER                                NOT NULL,
      MC      NVARCHAR2(20),
      FLJB    NUMBER,
      SJFLID  NUMBER
    )

          FLJB是作為樹的級別,在很多查詢中可以加快SQL的查詢效率。在下面演示的功能基本上不使用這個關(guān)鍵字。

          SJFLID存儲的是上級ID,如果是頂級父節(jié)點,該SJFLID為null(得補(bǔ)充一句,當(dāng)初的確是這樣設(shè)計的,不過現(xiàn)在知道,表中最好別有null記錄,這會引起全文掃描,建議改成0代替)。

          我們從最基本的操作,逐步列出樹查詢中常見的操作,所以查詢出來的節(jié)點以家族中的輩份作比方。

     

          1. 查找樹中的所有頂級父節(jié)點(輩份最長的人)。 假設(shè)這個樹是個目錄結(jié)構(gòu),那么第一個操作總是找出所有的頂級節(jié)點,再根據(jù)該節(jié)點找到其下屬節(jié)點。

    SELECT * FROM flfl WHERE sjflid IS NULL;

          這是個引子,沒用到樹型查詢。

     

          2.查找一個節(jié)點的直屬子節(jié)點(所有兒子)。 如果查找的是直屬子類節(jié)點,也是不用用到樹型查詢的。

    SELECT * FROM flfl WHERE sjflid = 819459;

          這個可以找到ID為819459的直屬子類節(jié)點。

     

          3.查找一個節(jié)點的所有 直屬子節(jié)點(所有后代)。

    SELECT * FROM flfl START WITH ID = 819459 CONNECT BY sjflid = PRIOR ID;

          這個查找的是ID為819459的節(jié)點下的所有直屬子類節(jié)點,包括子輩的和孫子輩的所有直屬節(jié)點。

     

          4.查找一個節(jié)點的直屬父節(jié)點(父親)。 如果查找的是節(jié)點的直屬父節(jié)點,也是不用用到樹型查詢的。

    SELECT b.* FROM flfl a JOIN flfl b ON a.sjflid = b.ID WHERE a.ID = 6758;

          這個找到的是ID為6758的節(jié)點的直屬父節(jié)點,要用到同一張表的關(guān)聯(lián)了。

     

          5.查找一個節(jié)點的所有直屬父節(jié)點(祖宗)。

    SELECT * FROM flfl START WITH ID = 6758 CONNECT BY PRIOR sjflid = ID;

          這里查找的就是ID為6758的所有直屬父節(jié)點,打個比方就是找到一個人的父親、祖父等。但是值得注意的是這個查詢出來的結(jié)果的順序是先列出子類節(jié)點再列出父類節(jié)點,姑且認(rèn)為是個倒序吧。

     

          上面列出兩個樹型查詢方式,第3條語句和第5條語句,這兩條語句之間的區(qū)別在于prior關(guān)鍵字的位置不同,所以決定了查詢的方式不同。 當(dāng)sjflid = PRIOR ID時,數(shù)據(jù)庫會根據(jù)當(dāng)前的ID迭代出sjflid與該ID相同的記錄,所以查詢的結(jié)果是迭代出了所有的子類記錄;而PRIOR ID = sjflid時,數(shù)據(jù)庫會跟據(jù)當(dāng)前的sjflid來迭代出與當(dāng)前的sjflid相同的id的記錄,所以查詢出來的結(jié)果就是所有的父類結(jié)果。

          以下是一系列針對樹結(jié)構(gòu)的更深層次的查詢,這里的查詢不一定是最優(yōu)的查詢方式,或許只是其中的一種實現(xiàn)而已。

     

          6.查詢一個節(jié)點的兄弟節(jié)點(親兄弟)。

    SELECT a.*
      FROM flfl a
     WHERE EXISTS (SELECT *
                     FROM flfl b
                    WHERE a.sjflid = b.sjflid AND b.ID = 6757);

          這里查詢的就是與ID為6757的節(jié)點同屬一個父節(jié)點的節(jié)點了,就好比親兄弟了。

     

          7.查詢與一個節(jié)點同級的節(jié)點(族兄弟)。 如果在表中設(shè)置了級別的字段,上表中的FLJB,那么在做這類查詢時會很輕松,同一級別的就是與那個節(jié)點同級的,在這里列出不使用該字段時的實現(xiàn)!

    WITH tmp AS
         (SELECT     a.*, LEVEL lev
                FROM flfl a
          START WITH a.sjflid IS NULL
          CONNECT BY a.sjflid = PRIOR a.ID)
    SELECT *
      FROM tmp
     WHERE lev = (SELECT lev
                    FROM tmp
                   WHERE ID = 819394)

           這里使用兩個技巧,一個是使用了LEVEL來標(biāo)識每個節(jié)點在表中的級別,還有就是使用with語法模擬出了一張帶有級別的臨時表。

     

          8.查詢一個節(jié)點的父節(jié)點的的兄弟節(jié)點(伯父與叔父)。

    WITH tmp AS
         (SELECT     flfl.*, LEVEL lev
                FROM flfl
          START WITH sjflid IS NULL
          CONNECT BY sjflid = PRIOR ID)
    SELECT b.*
      FROM tmp b,
           (SELECT *
              FROM tmp
             WHERE ID = 7004 AND lev = 2) a
     WHERE b.lev = 1
    UNION ALL
    SELECT *
      FROM tmp
     WHERE sjflid = (SELECT DISTINCT x.ID
                                FROM tmp x,
                                     tmp y,
                                     (SELECT *
                                        FROM tmp
                                       WHERE ID = 7004 AND lev > 2) z
                               WHERE y.ID = z.sjflid AND x.ID = y.sjflid);

           這里查詢分成以下幾步。首先,將第7個一樣,將全表都使用臨時表加上級別;其次,根據(jù)級別來判斷有幾種類型,以上文中舉的例子來說,有三種情況:(1)當(dāng)前節(jié)點為頂級節(jié)點,即查詢出來的lev值為1,那么它沒有上級節(jié)點,不予考慮。(2)當(dāng)前節(jié)點為2級節(jié)點,查詢出來的lev值為2,那么就只要保證lev級別為1的就是其上級節(jié)點的兄弟節(jié)點。(3)其它情況就是3以及以上級別,那么就要選查詢出來其上級的上級節(jié)點(祖父),再來判斷祖父的下級節(jié)點都是屬于該節(jié)點的上級節(jié)點的兄弟節(jié)點。 最后,就是使用UNION將查詢出來的結(jié)果進(jìn)行結(jié)合起來,形成結(jié)果集。

     

          9.查詢一個節(jié)點的父節(jié)點的同級節(jié)點(族叔)。

          這個其實跟第7種情況是相同的。

    WITH tmp AS
         (SELECT     a.*, LEVEL lev
                FROM flfl a
          START WITH a.sjflid IS NULL
          CONNECT BY a.sjflid = PRIOR a.ID)
    SELECT *
      FROM tmp
     WHERE lev = (SELECT lev
                    FROM tmp
                   WHERE ID = 819394) - 1

          只需要做個級別判斷就成了。

     

          基本上,常見的查詢在里面了,不常見的也有部分了。其中,查詢的內(nèi)容都是節(jié)點的基本信息,都是數(shù)據(jù)表中的基本字段,但是在樹查詢中還有些特殊需求,是對查詢數(shù)據(jù)進(jìn)行了處理的,常見的包括列出樹路徑等。

          補(bǔ)充一個概念,對于數(shù)據(jù)庫來說,根節(jié)點并不一定是在數(shù)據(jù)庫中設(shè)計的頂級節(jié)點,對于數(shù)據(jù)庫來說,根節(jié)點就是start with開始的地方。

          下面列出的是一些與樹相關(guān)的特殊需求。

     

          10.名稱要列出名稱全部路徑。

          這里常見的有兩種情況,一種是是從頂級列出,直到當(dāng)前節(jié)點的名稱(或者其它屬性);一種是從當(dāng)前節(jié)點列出,直到頂級節(jié)點的名稱(或其它屬性)。舉地址為例:國內(nèi)的習(xí)慣是從省開始、到市、到縣、到居委會的,而國外的習(xí)慣正好相反(老師說的,還沒接過國外的郵件,誰能寄個瞅瞅 )。

          從頂部開始:

    SELECT     SYS_CONNECT_BY_PATH (mc, '/')
          FROM flfl
         WHERE ID = 6498
    START WITH sjflid IS NULL
    CONNECT BY sjflid = PRIOR ID;

          從當(dāng)前節(jié)點開始:

    SELECT     SYS_CONNECT_BY_PATH (mc, '/')
          FROM flfl
    START WITH ID = 6498
    CONNECT BY PRIOR sjflid = ID;

          在這里我又不得不放個牢騷了。oracle只提供了一個sys_connect_by_path函數(shù),卻忘了字符串的連接的順序。在上面的例子中,第一個SQL是從根節(jié)點開始遍歷,而第二個SQL是直接找到當(dāng)前節(jié)點,從效率上來說已經(jīng)是千差萬別,更關(guān)鍵的是第一個SQL只能選擇一個節(jié)點,而第二個SQL卻是遍歷出了一顆樹來。再次PS一下。

          sys_connect_by_path函數(shù)就是從start with開始的地方開始遍歷,并記下其遍歷到的節(jié)點,start with開始的地方被視為根節(jié)點,將遍歷到的路徑根據(jù)函數(shù)中的分隔符,組成一個新的字符串,這個功能還是很強(qiáng)大的。

     

          11.列出當(dāng)前節(jié)點的根節(jié)點。

          在前面說過,根節(jié)點就是start with開始的地方。

    SELECT     CONNECT_BY_ROOT mc, flfl.*
          FROM flfl
    START WITH ID = 6498
    CONNECT BY PRIOR sjflid = ID;

          connect_by_root函數(shù)用來列的前面,記錄的是當(dāng)前節(jié)點的根節(jié)點的內(nèi)容。

     

          12.列出當(dāng)前節(jié)點是否為葉子。

          這個比較常見,尤其在動態(tài)目錄中,在查出的內(nèi)容是否還有下級節(jié)點時,這個函數(shù)是很適用的。

    SELECT     CONNECT_BY_ISLEAF, flfl.*
          FROM flfl
    START WITH sjflid IS NULL
    CONNECT BY sjflid = PRIOR ID;

          connect_by_isleaf函數(shù)用來判斷當(dāng)前節(jié)點是否包含下級節(jié)點,如果包含的話,說明不是葉子節(jié)點,這里返回0;反之,如果不包含下級節(jié)點,這里返回1。

     

          至此,oracle樹型查詢基本上講完了,以上的例子中的數(shù)據(jù)是使用到做過的項目中的數(shù)據(jù),因為里面的內(nèi)容可能不好理解,所以就全部用一些新的例子來進(jìn)行闡述。以上所有SQL都在本機(jī)上測試通過,也都能實現(xiàn)相應(yīng)的功能,但是并不能保證是解決這類問題的最優(yōu)方案(如第8條明顯寫成存儲過程會更好),如果誰有更好的解決方案、或者有關(guān)oracle樹查詢的任何問題,歡迎留言討論,以上的SQL有什么問題也歡迎大家留言批評。



    xcp 2011-09-29 15:10 發(fā)表評論
    ]]>
    SQL的四種連接-左外連接、右外連接、內(nèi)連接、全連接 http://www.aygfsteel.com/xcp/archive/2011/09/29/359786.htmlxcpxcpThu, 29 Sep 2011 06:36:00 GMThttp://www.aygfsteel.com/xcp/archive/2011/09/29/359786.htmlhttp://www.aygfsteel.com/xcp/comments/359786.htmlhttp://www.aygfsteel.com/xcp/archive/2011/09/29/359786.html#Feedback2http://www.aygfsteel.com/xcp/comments/commentRss/359786.htmlhttp://www.aygfsteel.com/xcp/services/trackbacks/359786.html今天在看一個遺留系統(tǒng)的數(shù)據(jù)表的時候發(fā)現(xiàn)平時查找的視圖是FULL OUT JOIN的,導(dǎo)致平時的數(shù)據(jù)記錄要進(jìn)行一些限制性處理,其實也可以設(shè)置視圖各表為右外連接并在視圖上設(shè)置各列的排序和篩選條件就可以達(dá)到效果。

     

    聯(lián)接條件可在FROM或WHERE子句中指定,建議在FROM子句中指定聯(lián)接條件。WHERE和HAVING子句也可以包含搜索條件,以進(jìn)一步篩選聯(lián)接條件所選的行。    
    聯(lián)接可分為以下幾類:    


    1、內(nèi)聯(lián)接(典型的聯(lián)接運(yùn)算,使用像 =  或 <> 之類的比較運(yùn)算符)。包括相等聯(lián)接和自然聯(lián)接。     
    內(nèi)聯(lián)接使用比較運(yùn)算符根據(jù)每個表共有的列的值匹配兩個表中的行。例如,檢索 students和courses表中學(xué)生標(biāo)識號相同的所有行。   
        
    2、外聯(lián)接。外聯(lián)接可以是左向外聯(lián)接、右向外聯(lián)接或完整外部聯(lián)接。     
    在 FROM子句中指定外聯(lián)接時,可以由下列幾組關(guān)鍵字中的一組指定:     

    1)LEFT  JOIN或LEFT OUTER JOIN     
    左向外聯(lián)接的結(jié)果集包括  LEFT OUTER子句中指定的左表的所有行,而不僅僅是聯(lián)接列所匹配的行。如果左表的某行在右表中沒有匹配行,則在相關(guān)聯(lián)的結(jié)果集行中右表的所有選擇列表列均為空值。       

    2)RIGHT  JOIN 或 RIGHT  OUTER  JOIN     
    右向外聯(lián)接是左向外聯(lián)接的反向聯(lián)接。將返回右表的所有行。如果右表的某行在左表中沒有匹配行,則將為左表返回空值。       
    3)FULL  JOIN 或 FULL OUTER JOIN
    完整外部聯(lián)接返回左表和右表中的所有行。當(dāng)某行在另一個表中沒有匹配行時,則另一個表的選擇列表列包含空值。如果表之間有匹配行,則整個結(jié)果集行包含基表的數(shù)據(jù)值。   
        
    3、交叉聯(lián)接   
    交叉聯(lián)接返回左表中的所有行,左表中的每一行與右表中的所有行組合。交叉聯(lián)接也稱作笛卡爾積。    

    FROM 子句中的表或視圖可通過內(nèi)聯(lián)接或完整外部聯(lián)接按任意順序指定;但是,用左或右向外聯(lián)接指定表或視圖時,表或視圖的順序很重要。有關(guān)使用左或右向外聯(lián)接排列表的更多信息,請參見使用外聯(lián)接。     
        
    例子:   

    -------------------------------------------------
      a表     id   name     b表     id   job   parent_id   
                  1   張3                   1     23     1   
                  2   李四                 2     34     2   
                  3   王武                 3     34     4       
      a.id同parent_id   存在關(guān)系   

    --------------------------------------------------    
     1) 內(nèi)連接   
      select   a.*,b.*   from   a   inner   join   b     on   a.id=b.parent_id       
      結(jié)果是     
      1   張3                   1     23     1   
      2   李四                  2     34     2   
        
      2)左連接   
      select   a.*,b.*   from   a   left   join   b     on   a.id=b.parent_id       
      結(jié)果是     
      1   張3                   1     23     1   
      2   李四                  2     34     2   
      3   王武                  null   

     

     3) 右連接   
      select   a.*,b.*   from   a   right   join   b     on   a.id=b.parent_id       
      結(jié)果是     
      1   張3                   1     23     1   
      2   李四                  2     34     2   
      null                       3     34     4   
        
     4) 完全連接   
      select   a.*,b.*   from   a   full   join   b     on   a.id=b.parent_id   

      結(jié)果是     
      1   張3                  1     23     1   
      2   李四                 2     34     2   
      null                   3     34     4   
      3   王武                 null



    xcp 2011-09-29 14:36 發(fā)表評論
    ]]>
    oracle 利用 rownum分頁的方法http://www.aygfsteel.com/xcp/archive/2011/09/16/358762.htmlxcpxcpFri, 16 Sep 2011 01:45:00 GMThttp://www.aygfsteel.com/xcp/archive/2011/09/16/358762.htmlhttp://www.aygfsteel.com/xcp/comments/358762.htmlhttp://www.aygfsteel.com/xcp/archive/2011/09/16/358762.html#Feedback0http://www.aygfsteel.com/xcp/comments/commentRss/358762.htmlhttp://www.aygfsteel.com/xcp/services/trackbacks/358762.html不排序分頁:
    select *
      
    from (select rownum as num,t.ID, t.NAME, t.MODEL, t.DEPTH, t.FATHER, t.PCS
              
    from v_za_bzdzk t
             
    where t.FATHER = '510502'
               
    and PCS like '%510502400000%'
               
    and depth = '2'
               
    and rownum<=30) gg
     
    where num >= 16
    排序分頁:
    select *
      
    from (select rownum as num, gg.*
              
    from (select t.ID, t.NAME, t.MODEL, t.DEPTH, t.FATHER, t.PCS
                      
    from v_za_bzdzk t
                     
    where t.FATHER = '510502'
                       
    and PCS like '%510502400000%'
                       
    and depth = '2'
                     
    order by ORDERNAME) gg
             
    where Rownum <= 30
            
            ) tt
     
    where tt.num >= 16



    xcp 2011-09-16 09:45 發(fā)表評論
    ]]>
    破解移植wm_concathttp://www.aygfsteel.com/xcp/archive/2011/08/15/356546.htmlxcpxcpMon, 15 Aug 2011 03:01:00 GMThttp://www.aygfsteel.com/xcp/archive/2011/08/15/356546.htmlhttp://www.aygfsteel.com/xcp/comments/356546.htmlhttp://www.aygfsteel.com/xcp/archive/2011/08/15/356546.html#Feedback0http://www.aygfsteel.com/xcp/comments/commentRss/356546.htmlhttp://www.aygfsteel.com/xcp/services/trackbacks/356546.html--
    /*****************************************
       功能: 破解移植wm_concat
       作者:xcp
       日期:2011-07-14
       說明:wm_concat出現(xiàn)在oracle10g版本中,不僅是加密的,而且是在一個單獨的用戶中,不方便使用。并且10g以前的版本也用不上。經(jīng)過破解移植,可以方便大家使用
             將下邊的一個type,一個函數(shù)的創(chuàng)建腳本執(zhí)行,就可以構(gòu)建自己的wm_concat(這里叫zh_concat)。使用方法同wm_concat:
    ******************************************/
    --type:
    create or replace TYPE za_concat_im
    AUTHID CURRENT_USER AS OBJECT
    (
      CURR_STR VARCHAR2(32767),
      STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT za_concat_im) RETURN NUMBER,
      MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT za_concat_im,
                   P1 IN VARCHAR2) RETURN NUMBER,
      MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN za_concat_im,
                                     RETURNVALUE OUT VARCHAR2,
                                     FLAGS IN NUMBER)
                         RETURN NUMBER,
      MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT za_concat_im,
                        SCTX2 IN  za_concat_im) RETURN NUMBER
    );
    /
    create or replace TYPE BODY za_concat_im
    IS
      STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT za_concat_im)
      RETURN NUMBER
      IS
      BEGIN
        SCTX := za_concat_im(NULL) ;
        RETURN ODCICONST.SUCCESS;
      END;
      MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT za_concat_im,
              P1 IN VARCHAR2)
      RETURN NUMBER
      IS
      BEGIN
        IF(CURR_STR IS NOT NULL) THEN
          CURR_STR := CURR_STR || ',' || P1;
        ELSE
          CURR_STR := P1;
        END IF;
        RETURN ODCICONST.SUCCESS;
      END;
      MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN za_concat_im,
                                     RETURNVALUE OUT VARCHAR2,
                                     FLAGS IN NUMBER)
        RETURN NUMBER
      IS
      BEGIN
        RETURNVALUE := CURR_STR ;
        RETURN ODCICONST.SUCCESS;
      END;
      MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT za_concat_im,
                                       SCTX2 IN za_concat_im)
      RETURN NUMBER
      IS
      BEGIN
        IF(SCTX2.CURR_STR IS NOT NULL) THEN
          SELF.CURR_STR := SELF.CURR_STR || ',' || SCTX2.CURR_STR ;
        END IF;
        RETURN ODCICONST.SUCCESS;
      END;
    END;
    /

    --函數(shù):
    create or replace FUNCTION za_concat(P1 VARCHAR2)
    RETURN VARCHAR2 AGGREGATE USING za_concat_im ;
    /



    xcp 2011-08-15 11:01 發(fā)表評論
    ]]>
    oracle復(fù)制表的sql語句http://www.aygfsteel.com/xcp/archive/2011/07/18/354513.htmlxcpxcpMon, 18 Jul 2011 03:01:00 GMThttp://www.aygfsteel.com/xcp/archive/2011/07/18/354513.htmlhttp://www.aygfsteel.com/xcp/comments/354513.htmlhttp://www.aygfsteel.com/xcp/archive/2011/07/18/354513.html#Feedback0http://www.aygfsteel.com/xcp/comments/commentRss/354513.htmlhttp://www.aygfsteel.com/xcp/services/trackbacks/354513.htmlcreate table b as select * from a where 1<>1

    2、即復(fù)制表結(jié)構(gòu)又復(fù)制表中數(shù)據(jù)的sql
    create table b as select * from a

    3、復(fù)制表的制定字段的sql
    create table b as select row_id,name,age from a where 1<>1//前提是row_id,name,age都是a表的列

    4、復(fù)制表的指定字段及這些指定字段的數(shù)據(jù)的sql
    create table b as select row_id,name,age from a

    以上語句雖然能夠很容易的根據(jù)a表結(jié)構(gòu)復(fù)制創(chuàng)建b表,但是a表的索引等卻復(fù)制不了,需要在b中手動建立。


    5、insert into 會將查詢結(jié)果保存到已經(jīng)存在的表中
    insert into t2(column1, column2, ....) select column1, column2, .... from t1



    xcp 2011-07-18 11:01 發(fā)表評論
    ]]>
    ibatis的$與#的區(qū)別http://www.aygfsteel.com/xcp/archive/2011/05/17/350389.htmlxcpxcpTue, 17 May 2011 04:26:00 GMThttp://www.aygfsteel.com/xcp/archive/2011/05/17/350389.html$ 表示原生類型,如 String 類型 : aa ---> aa

     

    每天遇到問題記錄

    1.#變量名#  會轉(zhuǎn)化為 jdbc 的 ?, 比如 select * from user where name=#name# 會轉(zhuǎn)化為jdbc的 select * from user where name=?,把?參數(shù)設(shè)置為name的值,而$變量名$就直接把 $name$替換為 name的內(nèi)容, 也就是由可能 select * from user where name=$name$ 如果name為 "' ' or 1 = 1", 那么這樣就有可能導(dǎo)致sql注入,所以ibatis用#比$好,不會造成sql注入。

    2.ibatis中的參數(shù)傳入的值參數(shù)比較多,最好用bean方式傳入,也就是通過set/get取值的方式給sql map注入?yún)?shù),不要用hashmap結(jié)構(gòu)傳入,每次用hashmap傳入會占用比較多的內(nèi)容。如果參數(shù)少,用hashmap也比較方便簡單。但是對傳入?yún)?shù)的判斷,用bean方式比較容易檢測發(fā)現(xiàn),配置也能夠統(tǒng)一配置。




    select * from user u where u.username=#name#                                              //自動加''號
    select * from user u where age=$age$ and username=$username$                  // username=$username$ 會出錯

    select * from $username$ u where age =$age$    order by $filed$                                          //$主要用處是動態(tài)表名 ,指定排序字端

    xcp 2011-05-17 12:26 發(fā)表評論
    ]]>
    oracle學(xué)習(xí)http://www.aygfsteel.com/xcp/archive/2010/10/01/333613.htmlxcpxcpFri, 01 Oct 2010 09:32:00 GMThttp://www.aygfsteel.com/xcp/archive/2010/10/01/333613.htmlhttp://www.aygfsteel.com/xcp/comments/333613.htmlhttp://www.aygfsteel.com/xcp/archive/2010/10/01/333613.html#Feedback0http://www.aygfsteel.com/xcp/comments/commentRss/333613.htmlhttp://www.aygfsteel.com/xcp/services/trackbacks/333613.html 1、OracleDBCConsoleeasy888 就是em等的控制臺的開啟
    2、OracleOraDb10g_home3iSQL*Plus就是瀏覽器里面的sqlplus調(diào)試工具
    3、OracleOraDb10g_home3TNSListener就是監(jiān)聽程序
    4、OracleServiceeasy888就是Oracle服務(wù)
    二、本地文件說明(sqlplus "sys/yjtc888 as sysdba")
    1. oradata  存放控制文件,數(shù)據(jù)文件,日志文件
        a. 控制文件
               1).查看表結(jié)構(gòu):desc v$controlfile 
               2).查看記錄  select status,name from v$controlfile
        b. 數(shù)據(jù)文件
                1).查看表結(jié)構(gòu):desc v$datafile
                2).查看記錄 select status,name from v$datafile
        c.日志文件
                1).查看表結(jié)構(gòu):desc v$logfile
                2).查看記錄 select status,name from v$logfile     

    2.flash_recovery_area 自動保存數(shù)據(jù)庫目錄  記錄日志文件
    3.db_3等文件,在其下面配置listener.ora、sqlnet.ora、tnsnames.ora

    三、ORACLE10g服務(wù)器端自帶工具集

    (一)、配置和移植工具

    1.Oracle Administration Assistant for window

    作用:管理ORACEL本地賬戶

    2.Database Configuration Assistant

    作用:數(shù)據(jù)庫創(chuàng)建、配置、刪除、集群配置等
    每個數(shù)據(jù)庫都會有三個服務(wù):OracleService[XXX]、OracleDBConsole[XXX]、OracleJobScheduler[XXX]

    3.Database Upgrade Assistant

    作用:將oracle8、9、10等版本數(shù)據(jù)庫升級到10g2版本。

    4.Locale Builder

    作用:管理地域、語言、字符集等本地化內(nèi)容。

    5.Microsoft ODBC 管理員

    作用:不用解釋了吧,創(chuàng)建連接字符串的。

    6.Net Configuration Assistant

    作用:網(wǎng)絡(luò)服務(wù),包括監(jiān)聽程序配置、命名方法配置、本地NET服務(wù)名配置和目錄使用配置。

    默認(rèn)監(jiān)聽:Oracle[XXX]10g_home1TNSListener

    添加1522端口監(jiān)聽:Oracle[XXX]10g_home1TNSListener[新監(jiān)聽名稱]

    7.Net Manager

    作用:管理服務(wù)命名、監(jiān)聽程序等。

    (二)、應(yīng)用程序開發(fā)

    1.SQL Plus

    作用:這個我就不多說了。

    (三)、集成管理工具

    1.Oracle Directory Manager

    作用:ORACLE目錄管理

    2.Wallet Manager

    作用:ORACLE錢包管理,我也沒用過。

    (四)、Oracle Installation Products

    1.Universal Installer



    xcp 2010-10-01 17:32 發(fā)表評論
    ]]>
    大哥大姐們:幫幫小弟 , 急??!http://www.aygfsteel.com/xcp/archive/2010/05/14/321004.htmlxcpxcpFri, 14 May 2010 13:07:00 GMThttp://www.aygfsteel.com/xcp/archive/2010/05/14/321004.htmlhttp://www.aygfsteel.com/xcp/comments/321004.htmlhttp://www.aygfsteel.com/xcp/archive/2010/05/14/321004.html#Feedback4http://www.aygfsteel.com/xcp/comments/commentRss/321004.htmlhttp://www.aygfsteel.com/xcp/services/trackbacks/321004.html閱讀全文

    xcp 2010-05-14 21:07 發(fā)表評論
    ]]>
    oracle11g 使用http://www.aygfsteel.com/xcp/archive/2010/03/18/315758.htmlxcpxcpThu, 18 Mar 2010 03:50:00 GMThttp://www.aygfsteel.com/xcp/archive/2010/03/18/315758.html

    xcp 2010-03-18 11:50 發(fā)表評論
    ]]>
    三種SQL分頁法http://www.aygfsteel.com/xcp/archive/2009/11/10/SqlPager.htmlxcpxcpTue, 10 Nov 2009 03:20:00 GMThttp://www.aygfsteel.com/xcp/archive/2009/11/10/SqlPager.htmlhttp://www.aygfsteel.com/xcp/comments/301797.htmlhttp://www.aygfsteel.com/xcp/archive/2009/11/10/SqlPager.html#Feedback2http://www.aygfsteel.com/xcp/comments/commentRss/301797.htmlhttp://www.aygfsteel.com/xcp/services/trackbacks/301797.html三種SQL分頁法
    表中主鍵必須為標(biāo)識列,[ID] int IDENTITY (1,1)

    1.分頁方案一:(利用Not In和SELECT TOP分頁)

    語句形式: 
    SELECT TOP 頁記錄數(shù)量 *
    FROM 表名
    WHERE (ID NOT IN
      (SELECT TOP (每頁行數(shù)*(頁數(shù)-1)) ID
       FROM 表名
       ORDER BY ID))
       ORDER BY ID
    //自己還可以加上一些查詢條件


    例:
    select top 2 *
    from Sys_Material_Type
    where (MT_ID not in
        (select top (2*(3-1)) MT_ID from Sys_Material_Type  order by MT_ID))
    order by MT_ID

     

    2.分頁方案二:(利用ID大于多少和SELECT TOP分頁)

    語句形式:
    SELECT TOP 每頁記錄數(shù)量 *
    FROM 表名
    WHERE (ID >
              (SELECT MAX(id)
        FROM (SELECT TOP 每頁行數(shù)*頁數(shù) id   FROM 表
               ORDER BY id) AS T)
           )
    ORDER BY ID

    例:
    SELECT TOP 2 *
    FROM Sys_Material_Type
    WHERE (MT_ID >
              (SELECT MAX(MT_ID)
               FROM (SELECT TOP (2*(3-1)) MT_ID
                     FROM Sys_Material_Type
                     ORDER BY MT_ID) AS T))
    ORDER BY MT_ID

     

    3.分頁方案三:(利用SQL的游標(biāo)存儲過程分頁)
    create  procedure SqlPager
    @sqlstr nvarchar(4000), --查詢字符串
    @currentpage int, --第N頁
    @pagesize int --每頁行數(shù)
    as
    set nocount on
    declare @P1 int, --P1是游標(biāo)的id
     @rowcount int
    exec sp_cursoropen @P1 output,@sqlstr,@scrollopt=1,@ccopt=1, @rowcount=@rowcount output
    select ceiling(1.0*@rowcount/@pagesize) as 總頁數(shù)--,@rowcount as 總行數(shù),@currentpage as 當(dāng)前頁
    set @currentpage=(@currentpage-1)*@pagesize+1
    exec sp_cursorfetch @P1,16,@currentpage,@pagesize
    exec sp_cursorclose @P1
    set nocount off

     

    4.總結(jié):
    其它的方案:如果沒有主鍵,可以用臨時表,也可以用方案三做,但是效率會低。
    建議優(yōu)化的時候,加上主鍵和索引,查詢效率會提高。

    通過SQL 查詢分析器,顯示比較:我的結(jié)論是:
    分頁方案二:(利用ID大于多少和SELECT TOP分頁)效率最高,需要拼接SQL語句
    分頁方案一:(利用Not In和SELECT TOP分頁)   效率次之,需要拼接SQL語句
    分頁方案三:(利用SQL的游標(biāo)存儲過程分頁)    效率最差,但是最為通用

    本文轉(zhuǎn)摘自『IT學(xué)習(xí)者』http://www.itlearner.com/article/2007/3740.shtml



    xcp 2009-11-10 11:20 發(fā)表評論
    ]]>
    SQL Server 2005 使用指南(個人筆記)http://www.aygfsteel.com/xcp/archive/2009/11/08/sql2005.htmlxcpxcpSat, 07 Nov 2009 17:17:00 GMThttp://www.aygfsteel.com/xcp/archive/2009/11/08/sql2005.htmlhttp://www.aygfsteel.com/xcp/comments/301584.htmlhttp://www.aygfsteel.com/xcp/archive/2009/11/08/sql2005.html#Feedback0http://www.aygfsteel.com/xcp/comments/commentRss/301584.htmlhttp://www.aygfsteel.com/xcp/services/trackbacks/301584.html閱讀全文

    xcp 2009-11-08 01:17 發(fā)表評論
    ]]>
    用JDBC連接Sql Server 2005總結(jié)http://www.aygfsteel.com/xcp/archive/2009/10/21/jdbcSqlerver2005.htmlxcpxcpWed, 21 Oct 2009 14:29:00 GMThttp://www.aygfsteel.com/xcp/archive/2009/10/21/jdbcSqlerver2005.htmlhttp://www.aygfsteel.com/xcp/comments/299255.htmlhttp://www.aygfsteel.com/xcp/archive/2009/10/21/jdbcSqlerver2005.html#Feedback0http://www.aygfsteel.com/xcp/comments/commentRss/299255.htmlhttp://www.aygfsteel.com/xcp/services/trackbacks/299255.html
    * 最近因為開發(fā)活動需要,用上了Eclipse,并要求使用精簡版的SQL數(shù)據(jù)庫(即Sql server 2005)來進(jìn)行開發(fā)項目 *
    工作: 準(zhǔn)備相關(guān)的軟件(Eclipse除外,開源軟件可以從官網(wǎng)下載)

    <1>.Microsoft SQL server 2005 Express Edition

    下載地址:http://download.microsoft.com/download/0/9/0/09020fab-d2c3-4a8c-b9e0-db53a7a30ae8/SQLEXPR_CHS.EXE

    <2>.SQL Server Management Studio

    下載地址:http://www.microsoft.com/downloads/details.aspx?displaylang=zh-cn&FamilyID=c243a5ae-4bd1-4e3d-94b8-5a0f62bf7796#filelist

    <3>.SQL Server 2005 driver for JDBC

    下載地址:http://download.microsoft.com/download/8/B/D/8BDABAE2-B6EA-41D4-B903-7916EF3690EF/sqljdbc_1.2.2323.101_enu.exe

    2.都下載完之后開始進(jìn)行安裝 ,前兩個是屬于數(shù)據(jù)庫軟件,正常安裝即可(注意數(shù)據(jù)庫登陸不要使用windows驗證)

    <1> 將JDBC解壓縮到任意位置,比如解壓到C盤program files下面,并在安裝目錄里找到sqljdbc.jar文件,得到其路徑開始配置環(huán)境變量

    在環(huán)境變量classpath 后面追加 C:\Program Files\Microsoft SQL Server2005 JDBC Driver\sqljdbc_1.2\enu\sqljdbc.jar

    <2> 設(shè)置SQLEXPRESS服務(wù)器:

        a.打開SQL Server Configuration Manager -> SQLEXPRESS的協(xié)議 -> TCP/IP

        b.右鍵單擊啟動TCP/IP

        c.雙擊進(jìn)入屬性,把IP地址中的IP all中的TCP端口設(shè)置為1433

        d.重新啟動SQL Server 2005服務(wù)中的SQLEXPRESS服務(wù)器

        e.關(guān)閉SQL Server Configuration Manager

    <3> 打開剛剛安裝好的 SQL Server Management Studio,連接SQLEXPRESS服務(wù)器, 新建數(shù)據(jù)庫,起名字為sample

    <4> 打開Eclipse

        a.新建工程-> java -> java project,起名為Test
      
        b.選擇eclipse->窗口->首選項->java->installed JRE  編輯已經(jīng)安裝好的jdk,查找目錄添加sqljdbc.jar

        c.右鍵單擊目錄窗口中的Test, 選擇Build Path ->Configure Build Path..., 添加擴(kuò)展jar文件,即把sqljdbc.jar添加到其中

    <5> 編寫java代碼來測試連接數(shù)據(jù)庫

    程序代碼:


    import java.sql.*;

     

    public class Test {
    public static void main(String[] srg) {
      String driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver";  //加載JDBC驅(qū)動
      String dbURL = "jdbc:sqlserver://localhost:1433; DatabaseName=sample";  //連接服務(wù)器和數(shù)據(jù)庫sample
      String userName = "sa";  //默認(rèn)用戶名
      String userPwd = "123456";  //密碼
      Connection dbConn;

      try {
       Class.forName(driverName);
       dbConn = DriverManager.getConnection(dbURL, userName, userPwd);
       System.out.println("Connection Successful!");  //如果連接成功 控制臺輸出Connection Successful!
      } catch (Exception e) {
       e.printStackTrace();
      }
    }
    }
        

     


    :

    1.因為SQLexpress服務(wù)器默認(rèn)是禁用的并且端口號沒有配置,所以要進(jìn)行重新設(shè)置

    2.如果你以前用java連接sql server 2000的話就要注意了:

    在sql server 2000 中加載驅(qū)動和URL路徑的語句是

    String driverName = "com.microsoft.jdbc.sqlserver.SQLServerDriver";
    String dbURL = "jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=sample";

    而sql server 2005 中加載驅(qū)動和url的語句則為

    String driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
    String dbURL = "jdbc:sqlserver://localhost:1433; DatabaseName=sample";

    如果寫法錯誤將會找不到驅(qū)動.


    好了,應(yīng)該沒什么疑問了吧...偶是有連接失敗經(jīng)歷才分享給大家的...



    xcp 2009-10-21 22:29 發(fā)表評論
    ]]>
    ORACLE 中ROWNUM用法總結(jié)! (轉(zhuǎn)) http://www.aygfsteel.com/xcp/archive/2009/10/07/rownum1.htmlxcpxcpWed, 07 Oct 2009 10:39:00 GMThttp://www.aygfsteel.com/xcp/archive/2009/10/07/rownum1.htmlhttp://www.aygfsteel.com/xcp/comments/297392.htmlhttp://www.aygfsteel.com/xcp/archive/2009/10/07/rownum1.html#Feedback0http://www.aygfsteel.com/xcp/comments/commentRss/297392.htmlhttp://www.aygfsteel.com/xcp/services/trackbacks/297392.html 

    ORACLE 中ROWNUM用法總結(jié)!
        對于 Oracle 的 rownum 問題,很多資料都說不支持>,>=,=,between...and,只能用以上符號(<、<=、!=),并非說用>,>=,=,between..and 時會提示SQL語法錯誤,而是經(jīng)常是查不出一條記錄來,還會出現(xiàn)似乎是莫名其妙的結(jié)果來,其實您只要理解好了這個 rownum 偽列的意義就不應(yīng)該感到驚奇,同樣是偽列,rownum 與 rowid 可有些不一樣,下面以例子說明

    假設(shè)某個表 t1(c1) 有 20 條記錄

       如果用 select rownum,c1 from t1 where rownum < 10, 只要是用小于號,查出來的結(jié)果很容易地與一般理解在概念上能達(dá)成一致,應(yīng)該不會有任何疑問的。

       可如果用 select rownum,c1 from t1 where rownum > 10 (如果寫下這樣的查詢語句,這時候在您的頭腦中應(yīng)該是想得到表中后面10條記錄),你就會發(fā)現(xiàn),顯示出來的結(jié)果要讓您失望了,也許您還會懷疑是不誰刪了一些記錄,然后查看記錄數(shù),仍然是 20 條???那問題是出在哪呢?

       先好好理解 rownum 的意義吧。ROWNUM是一個虛假的列,它將被分配為 1,2,3,4,...N,N 是行的數(shù)量。即查到結(jié)果集之后,任何排序和聚合之前,加上去的一個列 (強(qiáng)調(diào):先要有結(jié)果集)。簡單的說 rownum 是對符合條件結(jié)果的序列號。它總是從1開始排起的。所以你選出的結(jié)果不可能沒有1,而有其他大于1的值。所以您沒辦法期望得到下面的結(jié)果集:
      11 aaaaaaaa
      12 bbbbbbb
      13 ccccccc
       .................

     ROWNUM是一個序列,是oracle數(shù)據(jù)庫從數(shù)據(jù)文件或緩沖區(qū)中讀取數(shù)據(jù)的順序。它取得第一條記錄則rownum值為1,第二條為2,依次類推。如果你用>,>=,=,between...and這些條件,因為從緩沖區(qū)或數(shù)據(jù)文件中得到的第一條記錄的rownum為1,不滿足條件,則被刪除,接著取下條,可是它的rownum還是1,又被刪除,依次類推,便沒有了數(shù)據(jù)。

    有了以上從不同方面建立起來的對 rownum 的概念,那我們可以來認(rèn)識使用 rownum 的幾種現(xiàn)像:

    1. select rownum,c1 from t1 where rownum != 10 為何是返回前9條數(shù)據(jù)呢?它與 select rownum,c1 from tablename where rownum < 10 返回的結(jié)果集是一樣的呢?
     因為是在查詢到結(jié)果集后,顯示完第 9 條記錄后,之后的記錄也都是 != 10,或者 >=10,所以只顯示前面9條記錄。也可以這樣理解,rownum 為9后的記錄的 rownum為10,因條件為 !=10,所以去掉,其后記錄補(bǔ)上,rownum又是10,也去掉,如果下去也就只會顯示前面9條記錄了

     2. 為什么 rownum >1 時查不到一條記錄,而 rownum >0 或 rownum >=1 卻總顯示所以的記錄?

       因為 rownum 是在查詢到的結(jié)果集后加上去的,它總是從1開始,如果rownum>1的話,查詢第一數(shù)據(jù)的rownum=1,不滿足條件,刪除,第二條的rownum 又等于1,還是不滿足,刪除,所以到最后一天數(shù)據(jù)也沒有。

       3. 為什么 between 1 and 10 或者 between 0 and 10 能查到結(jié)果,而用 between 2 and 10 卻得不到結(jié)果
       原因同上一樣,因為 rownum 總是從 1 開始

      

       從上可以看出,任何時候想把 rownum = 1 這條記錄拋棄是不對的,它在結(jié)果集中是不可或缺的,少了rownum=1 就像空中樓閣一般不能存在,所以你的 rownum 條件要包含到 1

       

    但如果就是想要用 rownum > 10 這種條件的話話就要用嵌套語句,把 rownum 先生成,然后對他進(jìn)行查詢。
      select * from (selet rownum as rn,t1.* from a where ...) where rn >10

    一般代碼中對結(jié)果集進(jìn)行分頁就是這么干的。

      

       另外:rowid 與 rownum 雖都被稱為偽列,但它們的存在方式是不一樣的,rowid 可以說是物理存在的,表示記錄在表空間中的唯一位置ID,在DB中唯一。只要記錄沒被搬動過,rowid是不變的。rowid 相對于表來說又像表中的一般列,所以以 rowid 為條件就不會有 rownum那些情況發(fā)生。
       另外還要注意:rownum不能以任何基表的名稱作為前綴。

        本文轉(zhuǎn)載于:http://www.cnblogs.com/chinhr/archive/2007/09/30/911685.html

    xcp 2009-10-07 18:39 發(fā)表評論
    ]]>
    oracle中varchar,varchar2,nvarchar,nvarchar2有什么區(qū)別?http://www.aygfsteel.com/xcp/archive/2009/10/06/oracle1.htmlxcpxcpMon, 05 Oct 2009 17:55:00 GMThttp://www.aygfsteel.com/xcp/archive/2009/10/06/oracle1.html 現(xiàn)在版本的Oracle,varchar和varchar2是沒有區(qū)別的,varchar2和ANSI   varchar的區(qū)別是varchar2把空串等同于null處理。這也是為什么ORACLE推薦使用varchar2類型的原因,因為如果新版本Oralce的varchar類型完全兼容ANSI標(biāo)準(zhǔn)時,使用varchar2的腳本可以不修改。

    至于一個varchar2字符要用幾個字節(jié)存儲,要看數(shù)據(jù)庫使用的字符集,比如GBK,漢字就會占兩個字節(jié),英文1個,如果是UTF-8,漢字一般占3個字節(jié),英文還是1個。

    而NCHAR、NVARCHAR是以UNICODE-16存儲,每個字符固定兩個字節(jié)。



    轉(zhuǎn)載于http://topic.csdn.net/u/20070918/09/762642ab-4dbd-41cb-b412-0ebe380f85a1.html

    xcp 2009-10-06 01:55 發(fā)表評論
    ]]>
    主站蜘蛛池模板: 武夷山市| 嘉义市| 嘉禾县| 荔浦县| 濮阳市| 孙吴县| 东阿县| 麦盖提县| 衡南县| 兰州市| 遵义县| 磴口县| 长葛市| 罗定市| 江城| 定襄县| 柞水县| 邻水| 房产| 黑河市| 塘沽区| 上虞市| 长春市| 北票市| 靖州| 若羌县| 大竹县| 江西省| 盘山县| 博客| 洞口县| 大厂| 眉山市| 灌南县| 台湾省| 台山市| 苏尼特左旗| 青冈县| 渑池县| 南雄市| 彭阳县|