通過plsql 測試存儲過程遇到的問題和學習到的一些基礎知識整理

pl/sql developer 中文字段顯示亂碼

在windows中創 建一個名爲“NLS_LANG”的系統環境變量,設置其值爲“SIMPLIFIED CHINESE_CHINA.ZHS16GBK”,然後重新啓動 pl/sql developer,這樣檢索出來的中文內容就不會是亂碼了。如果想轉換爲UTF8字符集,可以賦予“NLS_LANG”爲 “AMERICAN_AMERICA.UTF8”,然後重新啓動 pl/sql developer。其它字符集設置同上。

 

ORA-01400: cannot insert NULL into ("SYS"."OBJ$"."NAME") 當報這個錯誤時 :

解決方法爲 把文檔中的雙引號改爲單引號。

 

 

Oracle 的函數寫法:

CREATE OR REPLACE FUNCTION ISEQUAL
(
    VAR1 IN VARCHAR2,
    VAR2 IN VARCHAR2
)
RETURN NUMBER  -- 0:no equal 1:equal  -1: error
IS
   BEGIN
      IF(VAR1 IS NULL AND VAR2 IS NULL OR VAR1 IS NOT NULL AND VAR2 IS NOT NULL AND VAR1 = VAR2) THEN
         RETURN 1;
      ELSE
         RETURN 0;
      END IF;
EXCEPTION
    WHEN OTHERS THEN
    RETURN -1;
END ISEQUAL;

 

 

 

存儲過程創建語法:

       create or replace procedure 存儲過程名(param1 in type,param2 out type)

as

變量1 類型(值範圍);

變量2 類型(值範圍);

Begin

    Select count(*) into 變量1 from 表A where列名=param1;

    If (判斷條件) then

       Select 列名 into 變量2 from 表A where列名=param1;

       Dbms_output。Put_line(‘打印信息’);

    Elsif (判斷條件) then

       Dbms_output。Put_line(‘打印信息’);

    Else

       Raise 異常名(NO_DATA_FOUND);

    End if;

Exception

    When others then

       Rollback;

End;

 

 

注意事項:

1,  存儲過程參數不帶取值範圍,in表示傳入,out表示輸出

2,  變量帶取值範圍,後面接分號

3,  在判斷語句前最好先用count(*)函數判斷是否存在該條操作記錄

4,  用select 。。。into。。。給變量賦值

5,  在代碼中拋異常用 raise+異常名

 

 

 

 

命名的系統異常                          產生原因

ACCESS_INTO_NULL                   未定義對象

CASE_NOT_FOUND                     CASE 中若未包含相應的 WHEN ,並且沒有設置

ELSE 時

COLLECTION_IS_NULL                集合元素未初始化

CURSER_ALREADY_OPEN          遊標已經打開

DUP_VAL_ON_INDEX                   唯一索引對應的列上有重複的值

INVALID_CURSOR                 在不合法的遊標上進行操作

INVALID_NUMBER                       內嵌的 SQL 語句不能將字符轉換爲數字

NO_DATA_FOUND                        使用 select into 未返回行,或應用索引表未初始化的 

 

TOO_MANY_ROWS                      執行 select into 時,結果集超過一行

ZERO_DIVIDE                              除數爲 0

SUBSCRIPT_BEYOND_COUNT     元素下標超過嵌套表或 VARRAY 的最大值

SUBSCRIPT_OUTSIDE_LIMIT       使用嵌套表或 VARRAY 時,將下標指定爲負數

VALUE_ERROR                             賦值時,變量長度不足以容納實際數據

LOGIN_DENIED                           PL/SQL 應用程序連接到 oracle 數據庫時,提供了不

正確的用戶名或密碼

NOT_LOGGED_ON                       PL/SQL 應用程序在沒有連接 oralce 數據庫的情況下

訪問數據

PROGRAM_ERROR                       PL/SQL 內部問題,可能需要重裝數據字典& pl./SQL

系統包

ROWTYPE_MISMATCH                宿主遊標變量與 PL/SQL 遊標變量的返回類型不兼容

SELF_IS_NULL                             使用對象類型時,在 null 對象上調用對象方法

STORAGE_ERROR                        運行 PL/SQL 時,超出內存空間

SYS_INVALID_ID                         無效的 ROWID 字符串

TIMEOUT_ON_RESOURCE         Oracle 在等待資源時超時 

 

 

觸發器

1.觸發器的創建規則:
  ①作用範圍清晰;
  ②不要讓觸發器去完成Oracle 後臺已經能夠完成的功能;
  ③限制觸發器代碼的行數;
  ④不要創建遞歸的觸發器;
  ⑤觸發器僅在被觸發語句觸發時進行集中的,全局的操作,同用戶和數據庫應用無關。

2.可以創建被如下語句所觸發的觸發器:
  ①DML語句(DELETE,INSERT,UPDATE);
  ②DDL語句(CREATE,ALTER, DROP);
  ③數據庫操作(SERVERERROR,LOGON,LOGOFF,STARTUP,SHUTDOWN)。

3.注意事項
  ①觸發器可以聲明爲在對記錄進行操作之前,在之前(檢查約束之前和 INSERT,UPDATE 或 DELETE 執行前)或之後(在檢查約束之後和完成 INSERT, UPDATE 或 DELETE 操作)觸發;
  ②一個 FOR EACH ROW 執行指定操作的觸發器爲操作修改的每一行都調用一次;
  ③SELECT 並不更改任何行,因此不能創建 SELECT 觸發器.這種場合下規則和視圖更適合;
  ④觸發器和某一指定的表格有關,當該表格備刪除時,任何與該表有關的觸發器同樣會被刪除;
  ⑤在一個表上的每一個動作只能有一個觸發器與之關聯;
  ⑥在一個單獨的表上,最多隻能創建三個觸發器與之關聯,一個INSERT觸發器,一個DELETE觸發器和一個UPDATE觸發器;

4.刪除觸發器的語句格式爲:

DROP   TRIGGER  name  ON   table ;

  一個觸發器由三部分組成:觸發事件或語句、觸發限制和觸發器動作。觸發事件或語句是指引起激發觸發器的SQL語句,可爲對一指定表的INSERT、UNPDATE或DELETE語句。觸發限制是指定一個布爾表達式,當觸發器激發時該布爾表達式是必須爲真。觸發器作爲過程,是PL/SQL塊,當觸發語句發出、觸發限制計算爲真時該過程被執行。

5.實例
  編寫一個數據庫觸發器,當任何時候某個部門從dept表中刪除時,該觸發器將從emp表中刪除該部門的所有僱員。
CREATE   OR   REPLACE   TRIGGER  del_emp_deptno
  BEFORE 
DELETE   ON  dept
  
FOR  EACH ROW
BEGIN
  
DELETE   FROM  emp  WHERE  deptno  =  :OLD.deptno;
END ;


6:select into 用法:我在用的時候遇到個錯誤
SELECT count(*) into v_able_count,sum(useable_scores) into v_total_scores  這樣是不對的
應該改成
SELECT count(*) ,sum(useable_scores) into v_able_count ,v_total_scores


7: Oracle 定義數組如下:
Type scoresIdArray is
    table Of user_scores.id%type
    Index by Binary_Integer;
  這裏的user_scores.id%type 表示 user_scores表中的 id字段
%ROWTYPE 這種類型 表示某表的行數據類型

補充::
存儲過程中的轉義字符 可以是‘  單引號  如'''||v_key_time||'''   v_key_time 是一個定義的變量  類型爲字符串 

insert into  select   語法:  +   case when 語法
很強大的一個sql;
insert into ec_carts (ID,USER_ID, GOODS_ID, GOODS_NO, GOODS_NAME,
      MARTET_PRICE, GOODS_PRICE, CONSUME_SCORES,GOODS_NUMBER, IS_REAL,
      IS_GIFT, CREATED_AT,GET_SCORES,LIMIT_NUM,BUY_TYPE ,M_GOODS_ID,KEY_TIME)
    select EC_CARTS_SEQ.NEXTVAL,2011461,id,goods_no,
    case when 0= 1 then GOODS_GBK
        when 0 = 2 then GOODS_EN
        else  GOODS_CN end goods_name,
        MARKET_PRICE ,SHOP_PRICE ,0,SALE_NUMBER,
      case when GOODS_KIND =3 then 0
         else 1 end GOODS_KIND ,0,SYSDATE,
      case when (  BUY_FIXED_SCORES is not null) then BUY_FIXED_SCORES
         when (SCORE_BUY_PARAM is not null) then SHOP_PRICE*SCORE_BUY_PARAM
         else 0 end user_get_score,LIMIT_NUMBER ,1,8440001,SYSDATE
         from ec_goods where id in (8010001,7010007)and SYSDATE >=SALE_START AND SYSDATE <=SALE_END


存儲過程中 的 if elsif  else  end if  用法
如:
if v_buy_fixed_score is not null then
        v_user_get_score := v_buy_fixed_score;
    elsif v_buy_score_param is not null then
        v_user_get_score := v_shop_price*v_buy_score_param;
    else
        v_user_get_score := 0;
    end if;
 其中  elsif  沒寫錯  注意了。。。。。。

寫存儲過程的時候 一般都喜歡定義一個now 的sysdate  在整個存儲過程中使用它,然而在拼裝sql字符串的時候 千萬別用

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