全面學習DBMS包之DBMS_SQL

来源:http://www.cnblogs.com/androidshouce/archive/2016/06/20/5599579.html
-Advertisement-
Play Games

在PL/SQL編程當中,經常會遇到一些需要動態處理數據或表結構的問題,比如對一批表裡的數據進行處理,或者批量創建表,索引,觸發器等等,這個時候就可以通過DBMS_SQL包進行操作。你可能會有疑問,ORACLE不是提供了EXECUTE IMMEDIATE了嘛?幹嘛還要DBMS_SQL包來處理?嘿嘿,不 ...


在PL/SQL編程當中,經常會遇到一些需要動態處理數據或表結構的問題,比如對一批表裡的數據進行處理,或者批量創建表,索引,觸發器等等,這個時候就可以通過DBMS_SQL包進行操作。你可能會有疑問,ORACLE不是提供了EXECUTE IMMEDIATE了嘛?幹嘛還要DBMS_SQL包來處理?嘿嘿,不錯,很多人都習慣用EXECUTE IMMEDIATE來動態處理此類需求。下麵根據我的理解,解釋一下二者的區別。
1、execute   immediate的效率比dbms_sql低  。
execute   immediate每次都要進行語句的硬分析,而通過DBMS_SQL.PRASE卻不會。
2、execute   immediate可以使用變數  
  如execute   immediate   'select   count(*)   from   tab   where   uid=:id'   using   myid   into   nums;
3、dbms_sql包的功能遠比execute   immediate強大,可以實現動態變數傳遞。
總的來說呢。EXECUTE IMMEDIATE可以看成是實現了DBMS_SQL的一部分功能,接下來你看DBMS_SQL有那麼多子過程嘛,那可不是蓋的哦.......
(一)介紹
 DBMS_SQL系統包提供了很多函數及過程,現在簡要闡述其中使用頻率較高的幾種: 
function
 open_cursor:打開一個動態游標,並返回一個整型;   
procedure close_cursor(c in out integer);關閉一個動態游標,參數為open_cursor所打開的游標;  procedure parse(c in integer, statement in varchar2, language_flag in integer):對動態游標所提供的sql語句進行解析,參數C表示游標,statement為sql語句,language-flag為解析sql語句所用oracle版本,一般有V6,V7跟native(在不明白所連database版本時,使用native);  procedure define_column(c in integer, position in integercolumn any datatype, [column_size in integer]):定義動態游標所能得到的對應值,其中c為動態游標,positon為對應動態sql中的位置(從1開始),column為該值所對應的變數,可以為任何類型,column_size只有在column為定義長度的類型中使用如VARCHAR2,CHAR等(該過程有很多種情況,此處只對一般使用到的類型進行表述);   
function
 execute(c in integer):執行游標,並返回處理一個整型,1表示成功,0表示失敗,代表處理結果(對insert,delete,update才有意義,而對select語句而言可以忽略);
function
 fetch_rows(c in integer):對游標進行迴圈取數據,並返回一個整數,為0時表示已經取到游標末端;  
procedure column_value(c in integer, position in integer, value):將所取得的游標數據賦值到相應的變數,c為游標,position為位置,value則為對應的變數;  

procedure bind_variable(c in integername in varchar2, value):定義動態sql語句(DML)中所對應欄位的值,c為游標,name為欄位名稱,value為欄位的值; 
(二)一般過程  

對於一般的select 操作,如果使用動態的sql語句則需要進行以下幾個步驟:  
open   cursor --->parse--->define column--->excute--->fetch rows--->close cursor;   
而對於dml操作(insert , update )則需要進行以下幾個步驟:  
open   cursor --->parse--->bind variable--->execute--->close cursor;   
對於delete 操作只需要進行以下幾個步驟:  
open   cursor --->parse--->execute--->close cursor;   
對DDL操作需要進行一下幾個步驟
open cursor--->parse---->close cursor
(三)實例
1.DDL
複製代碼 SQL> create or replace procedure pro_test_dbms_sql(l_num in number,l_tabname in varchar2)
  
2  is
  
3  l_cur integer;
  
4  l_sql1 varchar2(400);
  
5  l_sql2 varchar2(400);
  
6  begin
  
7  l_cur :=dbms_sql.open_cursor;
  
8  if l_num=1 then
  
9  l_sql2 :='drop table '||l_tabname;
 
10  dbms_sql.parse(l_cur,l_sql2,dbms_sql.native);
 
11  dbms_sql.close_cursor(l_cur);
 
12  end if;
 
13  if l_num=0 then
 
14  l_sql1 :='create table '||l_tabname||' (id number(10))';
 
15  dbms_sql.parse(l_cur,l_sql1,dbms_sql.native);
 
16  dbms_sql.close_cursor(l_cur);
 
17  end if;
 
18  exception
 
19  when others then
 
20  raise;
 
21  
 
22  end;
 
23  /

過程已創建。

SQL
>  exec pro_test_dbms_sql(0,'test');

PL
/SQL 過程已成功完成。

SQL
> select table_name from user_tables where table_name='TEST';

TABLE_NAME
------------------------------
TEST

SQL
> exec  pro_test_dbms_sql(1,'test');

PL
/SQL 過程已成功完成。

SQL
> select count(1from user_tables where table_name='TEST';

  
COUNT(1)
----------
         0

SQL
>
複製代碼

2.DML
複製代碼 在這個例子里,我要用動態語句去更新TEMP表LJJE欄位,得到JE的累積和。當然直接在LOOP里去執行UPDATE也可以得到,這裡是為了熟悉和說明DBMS_SQL包的使用拿來舉例。
SQL
> select * from temp;

        ID         JE       LJJE
---------- ---------- ----------
         1       1000       1000
         
2                  1000
         
3       2000       3000
         
4        500       3500

SQL
> update temp set ljje=null;

已更新4行。

SQL
> select * from temp;

        ID         JE       LJJE
---------- ---------- ----------
         1       1000
         
2
         
3       2000
         
4        500

SQL
> 
SQL
> create or replace procedure pro_update_ljje
  
2  as
  
3  l_num integer;
  
4  l_cur integer;
  
5  l_sql varchar2(400);
  
6  l_return integer default 0;
  
7  begin
  
8  select max(id) into l_num from temp;
  
9  for i in 1..l_num  loop
 
10  l_cur :=dbms_sql.open_cursor;
 
11  l_sql:='update temp set ljje=(select sum(nvl(je,0)) from temp where id<='||i||') where id='||i;

 
12  dbms_sql.parse(l_cur,l_sql,dbms_sql.native);
 
13  l_return :=dbms_sql.execute(l_cur);
 
14  commit;
 
15  dbms_sql.close_cursor(l_cur);
 
16  end loop;
 
17  exception
 
18  when others then
 
19  dbms_sql.close_cursor(l_cur);
 
20  dbms_output.put_line('執行失敗');
 
21  end;
 
22  /

過程已創建。

SQL
> exec pro_update_ljje;

PL
/SQL 過程已成功完成。

SQL
> select * from temp;

        ID         JE       LJJE
---------- ---------- ----------
         1       1000       1000
         
2                  1000
         
3       2000       3000
         
4        500       3500

SQL
>
複製代碼
3、 DML之綁定變數
複製代碼 SQL> create table test(
  
2  id integer,
  
3  country varchar2(20),
  
4  company varchar2(50),
  
5  name    varchar2(10),
  
6  address varchar2(100)
  
7  );

表已創建。

SQL
> insert into test
  
2  select 1,'china','sap lab','Bob','Pudong New Area' from dual
  
3  union all
  
4  select 2,'china','sap lab','Myth','Xujiahui' from dual
  
5  union all
  
6  select 3,'china','sap lab','Lucy','Huangpu' from dual
  
7  union all
  
8  select 4,'china','INXITE','Kate','Jingan' from dual
  
9  ;

已創建4行。

SQL
> commit;

提交完成。


SQL
> set linesize 100
SQL
> select * from test;

        ID COUNTRY    COMPANY                                            NAME       ADDRESS
---------- ---------- -------------------------------------------------- ---------- ----------
         1 china      sap lab                                            Bob        Pudong New
                                                                                     Area

         
2 china      sap lab                                            Myth       Xujiahui
         
3 china      sap lab                                            Lucy       Huangpu
         
4 china      INXITE                                             Kate       Jingan

SQL
> 

SQL
> create or replace procedure pro_update_address(l_country varchar2,l_address varchar2)
  
2  as
  
3  l_cur integer;
  
4  l_sql varchar2(400);
  
5  l_return integer;
  
6  begin
  
7  l_cur :=dbms_sql.open_cursor;
  
8  l_sql:='update test set address= :l_address where country= :l_country ' ;
  
9  dbms_sql.parse(l_cur,l_sql,dbms_sql.native);
 
10  dbms_sql.bind_variable(l_cur,':l_address',l_address);
 
11  dbms_sql.bind_variable(l_cur,':l_country',l_country);
 
12  l_return :=dbms_sql.execute(l_cur);
 
13  commit;
 
14  dbms_sql.close_cursor(l_cur);
 
15  exception
 
16  when others then
 
17  dbms_sql.close_cursor(l_cur);
 
18  end;
 
19  /

過程已創建。

SQL
> 

SQL
> exec pro_update_address('china','Pudong Area');

PL
/SQL 過程已成功完成。

SQL
> select * from test;

        ID COUNTRY    COMPANY                                            NAME       ADDRESS
---------- ---------- -------------------------------------------------- ---------- ----------
         1 china      sap lab                                            Bob        Pudong Are
                                                                                    a

         
2 china      sap lab                                            Myth       Pudong Are
                                                                                    a

         
3 china      sap lab                                            Lucy       Pudong Are
                                                                                    a

         
4 china      INXITE                                             Kate       Pudong Are
                                                                                    a

        ID COUNTRY    COM
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 第 14 章 可擴展性設計之數據切分 前言 通過 MySQL Replication 功能所實現的擴展總是會受到資料庫大小的限制,一旦資料庫過於龐大,尤其是當寫入過於頻繁,很難由一臺主機支撐的時候,我們還是會面臨到擴展瓶頸。這時候,我們就必須許找其他技術手段來解決這個瓶頸,那就是我們這一章所要介紹惡 ...
  • 1、標準sql規範 2、decode函數 DECODE的語法: DECODE(value,if1,then1,if2,then2,if3,then3,...,else) 表示如果value等於if1時,DECODE函數的結果返回then1,...,如果不等於任何一個if值,則返回else。 3、ca ...
  • WITH cte AS ( SELECT a.FNUMBER,a.FMATERIALID AS MainId,b.FMATERIALID AS ChileID,CAST(b.FMATERIALID AS VARCHAR(max)) AS lev FROM t_eng_bom a JOIN dbo.T ...
  • 本章主要講如何使用腳本創建資料庫;如何使用腳本創建表;如何刪除對象和修改對象. CREATE 語句:CREATE <object type> <onject name> 創建資料庫基本語法:CREATE DATABASE <database name> ON [PARIMARY] ( [NAME=< ...
  • mysql主從複製指兩個伺服器之間資料庫的同步,當主伺服器的數據進行了變更,從伺服器也會自動更新,其過程是通過bin log日誌實現的,本質是binlog日誌的傳輸。 mysql主從分兩個角色 1、主伺服器 master 2、從伺服器 slave 主伺服器 MySQL 配置 從伺服器 MySQL 配 ...
  • 上一篇介紹到查詢。這一篇主要講連接查詢,將介紹INNER JOIN,OUTER JOIN(LEFT和RIGHT),FULL JOIN,CROSS JOIN。 連接顧名斯義就是把多個數據表數據合併到一個結果集。 用內部連接檢索匹配的數據(inner join) 連接結構語法如下:SELECT <col ...
  • 對於設計和創建資料庫完全是個新手?沒關係,Joe Celko, 世界上讀者數量最多的SQL作者之一,會告訴你這些基礎。和往常一樣,即使是最專業的資料庫老手,也會給他們帶來驚喜。Joe是DMBS雜誌是多年來最受 讀者喜愛的作者。他在美國、英國,北歐,南美及非洲傳授SQL知識。他在ANSI / ISO ...
  • Query OK, 0 rows affected (0.00 sec) ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...