zoukankan      html  css  js  c++  java
  • Oracle创建存储过程

    SET SERVEROUTPUT  ON; --开启输出显示功能,默认是关闭的,否则执行成功,看不到输出结果
    BEGIN 
     dbms_output.put_line('Hello,Welcome to PL/SQL');
     END;

    输出结果:

     

    CREATE OR REPLACE PROCEDURE P_TEST
    IS 
    BEGIN 
     dbms_output.put_line('Hello,Welcome to PL/SQL');
    END;
     EXEC P_TEST;--执行存储过程

    结果:

    CREATE OR REPLACE PROCEDURE P_TEST
    IS 
    BEGIN 
      dbms_output.put_line(2/0);  
    EXCEPTION   --这是异常处理语句
    WHEN OTHERS THEN  --必须知道什么异常,这里指定其他
     dbms_output.put_line('0不能作为被除数');
    END;

    执行结果:

     这样一个带有执行块的和异常的存储过程就创建完整了。

    标识符

    命名规则

    例子

    程序变量

    V_name

    V_name

    程序常量

    C_Name

    C_Name

    游标变量

    Name_cursor

    Emp_cursor

    异常标识

    E_name

    E_too_many

    表类型

    Name_table_type

    Emp_record_type

    Name_table

    Emp

    记录类型

    Name_record

    Emp_record

    SQL*PLUS替代变量

    P_name

    P_sal

    绑定变量

    G_name

    G_year_sal

    CREATE OR REPLACE PROCEDURE P_TEST(V_name varchar2,V_sal number)
    IS 
    BEGIN 
     UPDATE emp SET sal = V_sal WHERE ename=V_name;
     dbms_output.put_line('更新成功');
    EXCEPTION   --这是异常处理语句
    WHEN OTHERS THEN  --必须知道什么异常,这里指定其他
     dbms_output.put_line('更新失败');
    END;

    执行存储过程

     EXEC P_TEST('SMITH',10);

    CREATE OR REPLACE PROCEDURE P_TEST(V_name varchar2,V_sal number)
    IS 
    v_yearSal number;  --定义年薪变量
    BEGIN 
     UPDATE emp SET sal = V_sal WHERE ename=V_name;
     v_yearSal:=12*V_sal;  --给变量赋值 用:=
     dbms_output.put_line('更新成功');
     dbms_output.put_line('12个月的总工资为:');
     dbms_output.put_line(v_yearSal);  --输出年薪
    EXCEPTION   --这是异常处理语句
    WHEN OTHERS THEN  --必须知道什么异常,这里指定其他
     dbms_output.put_line('更新失败');
    END;

    执行

     EXEC P_TEST('SMITH',10);

    结果:

    存储过程:   

    先来个最简单的存储过程,往表中添加一条数据

    --1.创建测试表
     create table myTest (
       name varchar2(30),
       passwd varchar2(30));
     
     --2编写存储过程,向测试表添加数据
     create or replace procedure p_insert is
     begin 
       insert into myTest values('Jim','changeit');
       end;
    
     --3.调用存储过程
         exec p_insert;
        
    View Code

     下面创建一个带参数的存储过程,将员工的姓名和薪水作为参数,去修改原来表中的数据

     --存储过程
          create or replace procedure p_update (spName varchar2, newSal number) is
          begin 
            update emp set sal=newSal where ename = spName;
            end;

    创建一个存储过程,可以直接调用插入表的数据

       

      执行存储过程:

    查询:

      

      

      存储过程

    一.最简单的存储过程架构:

       CREATE OR REPLACE PROCEDURE 存储过程名  --创建或者覆盖一个存储过程

      IS                                                          --关键词,表面后面跟随一个PL/SQL体

      BEGIN                                                --表示PL/SQL体开始

      NULL;                                    --这里NULL不能删除,因为PL/SQL体必须有一行

      END;                  --代表结束

    --创建空的存储过程
    CREATE OR REPLACE PROCEDURE SP_Upadte IS
    BEGIN
     NULL;
           END;

    二.带参数和变量的存储过程

    CREATE OR REPLACE PROCEDURE SP_Update (参数1 类型1,参数2 类型2,. . . )

    AS            (这里IS也可以)

     变量1 类型1;    --自己定义的变量 和类型

     变量2 类型2;

    begin

    null;  --这里是代码

    end;

    --带参数和自定义变量的存储过程
    CREATE OR REPLACE PROCEDURE SP_Upadte
    ( Id in number,
      Name out nvarchar2 )
     AS
     Sex char(2);   --定义的变量
     Class varchar2(20);
    BEGIN
     NULL;   --代码块
           END;

    根据年月日,利用存储过程,自动更新其他字段

    DATE_ID YEAR_MONTH YEAR  YEAR_QUARTER YEAR_HALF HALF_NUMBER HALF_NAME QUARTER_NAME QUARTER_NUMBER MONTH MONTH_NUMBER MONTH_NAME MONTH_DEDAK WEEK WEEK_NUMBER WEEK_NAME
    20160702 201607 2016 2016Q3 2016H2         2       H2         Q3             3 JUL           7 JULY 07D1 SAT 7 SATURDAY

    现在只需要输入DATE_ID,调用存储过程,后面的值可以自动更新,正确补上

    废话少说,直接来代码

    --创建更新date的存储过程
    CREATE OR REPLACE PROCEDURE SP_Update_Date    --此存储过程不带参数
           AS
           v_Half number;                        --定义数字,1,2代表上半年,下半年
           v_Quarter number;                     --定义季度 1,2,3,4
           v_Month VARCHAR2(10);          --定义月份 1~12
           v_Dedak number;             --定义上中下旬,1,2,3
           v_Week VARCHAR2(10);           --定义星期几
           CURSOR c_date IS              --定义游标
           SELECT DATE_ID,YEAR_MONTH FROM DIM_TIME;
           c_row c_date%rowtype;            --new 一个实例(对比编程语言,创建好类后,就可以new 一个对象BEGIN
             for c_row in c_date loop  --循环游标
             v_Month:=to_char(to_Date(c_row.DATE_ID,'YYYYMMDD'),'MONTH'); --月份名称
             v_Week:=to_char(to_Date(c_row.DATE_ID,'YYYYMMDD'),'DAY'); --星期名称
             v_Dedak:=to_number(Substr(c_row.date_id,7,2));--(日期最后几号)日   
             if(to_number(to_char(to_Date(c_row.DATE_ID,'YYYYMMDD'),'MM'))<7) then
               v_Half:=1;  --上半年
             else         
               v_Half:=2; --下半年
                 end if;
            if(to_number(to_char(to_Date(c_row.DATE_ID,'YYYYMMDD'),'MM'))<4) then
               v_Quarter:=1;  --季度
            elsif(to_number(to_char(to_Date(c_row.DATE_ID,'YYYYMMDD'),'MM'))<7) then
               v_Quarter:=2;
            elsif(to_number(to_char(to_Date(c_row.DATE_ID,'YYYYMMDD'),'MM'))<10) then
               v_Quarter:=3;
            else
               v_Quarter:=4;
                 end if;
              if v_Dedak<11 then
                 v_Dedak:=1;
              elsif v_Dedak<21 then 
                 v_Dedak:=2;
              else
                 v_Dedak:=3;
                 end if;
                 --这里也可以直接调用写好的函数
               --  v_Half:=getYearHalf(to_Date(c_row.DATE_ID,'YYYYMMDD'));
               update DIM_TIME  set
                year_month =Substr(c_row.date_id,1,6),  --根据Date_ID得到year_Month
                year=Substr(c_row.date_id,1,4),     --得到年份
                year_quarter=Substr(c_row.date_id,1,4)||'Q'||v_Quarter, --得到年和季度
                year_half=Substr(c_row.date_id,1,4)||'H'||v_Half,
                half_number=v_Half,
                half_name='H'||v_Half,
                quarter_name= 'Q'||v_Quarter,
                quarter_number= v_Quarter,
                month=Substr(v_Month,1,3),
                month_number=to_char(to_Date(c_row.DATE_ID,'YYYYMMDD'),'MM'),
                month_name=v_Month,
                MONTH_DEDAK=Substr(c_row.date_id,5,2)||'D'||v_Dedak,
                week=Substr(v_Week,1,3),
                week_number=to_number(to_char(to_Date(c_row.DATE_ID,'YYYYMMDD'),'D')),
                week_name=v_Week
                where DIM_TIME.DATE_ID=c_row.DATE_ID;
              end loop;   
           END;

    几点注意:

    •     if else分支与java,C 语言有区别 通常我们是 :

         编程语言:   if(条件1)

                               代码1

                          else if(条件2)

                              代码2

                          else

                             代码3

    *************************华丽的分割线************************************

      Oracle :

               if  条件1 then 

                   代码1

              elsif  条件2 then

                   代码2

              elsif  条件3  then

                  代码3

              else 

                 代码4

             end if;

    嗯,看到红色的elsif没?没错,就是这样的,不习惯也没办法,慢慢习惯就好了!

     再来个升级版的存储过程,直接创建好时间,还没提供参数,所以时间定了从1900-1-1至2019-12-31日,要是能提供两个日期参数,那就绝了

    好吧,没有参数的先这么写吧:

    --创建更新date的存储过程(利用游标)
    --还可以升级,输入初始日期和最后日期
    CREATE OR REPLACE PROCEDURE SP_Update_Date
           AS
           v_Half number; 
           v_Quarter number;
           v_Month VARCHAR2(10);
           v_Dedak number;
           v_Week VARCHAR2(10);
           CURSOR c_date IS
           SELECT DATE_ID,YEAR_MONTH FROM DIM_TIME;
           c_row c_date%rowtype;
           BEGIN
             -----以下-----
             --这里是插入DATE_ID
              MERGE INTO DIM_TIME  T1
      USING (SELECT DATE'1900-1-1'+(ROWNUM-1) as Date_Name FROM dual CONNECT BY rownum <=
      (date'2020-1-1'-date'1900-1-1')) temp_Date
      on (T1.Date_Name =temp_Date.Date_Name)
      when  matched then
        update set T1.Date_ID=to_char(temp_Date.Date_Name,'YYYYMMDD')
      when not matched then
       insert (DATE_ID) values(to_char(temp_Date.Date_Name,'YYYYMMDD'));
             
             
             ----以上----
             for c_row in c_date loop  --循环游标
             v_Month:=to_char(to_Date(c_row.DATE_ID,'YYYYMMDD'),'MONTH'); --月份名称
             v_Week:=to_char(to_Date(c_row.DATE_ID,'YYYYMMDD'),'DAY'); --星期名称
             v_Dedak:=to_number(Substr(c_row.date_id,7,2));--(日期最后几号)日
             if(to_number(to_char(to_Date(c_row.DATE_ID,'YYYYMMDD'),'MM'))<7) then
               v_Half:=1;  --上半年
             else         
               v_Half:=2; --下半年
                 end if;
            if(to_number(to_char(to_Date(c_row.DATE_ID,'YYYYMMDD'),'MM'))<4) then
               v_Quarter:=1;  --季度
            elsif(to_number(to_char(to_Date(c_row.DATE_ID,'YYYYMMDD'),'MM'))<7) then
               v_Quarter:=2;
            elsif(to_number(to_char(to_Date(c_row.DATE_ID,'YYYYMMDD'),'MM'))<10) then
               v_Quarter:=3;
            else
               v_Quarter:=4;
                 end if;
              if v_Dedak<11 then
                 v_Dedak:=1;
              elsif v_Dedak<21 then 
                 v_Dedak:=2;
              else
                 v_Dedak:=3;
                 end if;
                 --这里也可以直接调用写好的函数
               --  v_Half:=getYearHalf(to_Date(c_row.DATE_ID,'YYYYMMDD'));
               update DIM_TIME  set
                year_month =Substr(c_row.date_id,1,6),  --根据Date_ID得到year_Month
                year=Substr(c_row.date_id,1,4),     --得到年份
                year_quarter=Substr(c_row.date_id,1,4)||'Q'||v_Quarter, --得到年和季度
                year_half=Substr(c_row.date_id,1,4)||'H'||v_Half,
                half_number=v_Half,
                half_name='H'||v_Half,
                quarter_name= 'Q'||v_Quarter,
                quarter_number= v_Quarter,
                month=Substr(v_Month,1,3),
                month_number=to_char(to_Date(c_row.DATE_ID,'YYYYMMDD'),'MM'),
                month_name=v_Month,
                MONTH_DEDAK=Substr(c_row.date_id,5,2)||'D'||v_Dedak,
                week=Substr(v_Week,1,3),
                week_number=to_number(to_char(to_Date(c_row.DATE_ID,'YYYYMMDD'),'D')),
                week_name=v_Week,
                DIM_TIME.DATE_NAME=to_date(c_row.DATE_ID,'YYYYMMDD')
                where DIM_TIME.DATE_ID=c_row.DATE_ID;
              end loop;   
           END;

    查询的时候,坑爹了,足足让我等了六分多钟。

    --最简单的pl/sql语句块
    set serveroutput on ;--(默认是关闭的)
    begin
      dbms_output.put_line('HelloWorld');
      end;
    
    --先定义变量,再赋值
    declare
    v_name varchar2(20);
    begin
      v_name:='My name';
      dbms_output.put_line(v_name);
      end;
      
    --加异常捕获
    declare 
    v_name number :=4;
    begin
      v_name := 2/v_name;
      dbms_output.put_line(v_name);
      exception
        when others then
          dbms_output.put_line('error');
          end;
    --变量赋值和声明
    declare 
     v_date nvarchar2(10) :='20160808';
     v_week nvarchar2(10);
     begin 
       v_week := to_char(to_date(v_date,'YYYYMMDD'),'Q');
       dbms_output.put_line(v_week);
       end;
       
    --变量声明,使用%type属性
    
    declare
    v_sal number(4);
    v_empname emp.ename%type;
    v_empno emp.empno%type;
    begin
      v_empname:= 'What';
       dbms_output.put_line(v_empname);
      end;

     我们先来创建些日期,比如创建2015年1月1日到2015年12月31日这一年的日期,我们该怎么做呢?

    肯定不会去一天一天的输入吧,好了,来个很洋气的查日期的方法:

    SELECT to_date('20150101','YYYYMMDD')+rownum-1 AS tempdate FROM dual 
    connect by rownum<= to_date('20160101','YYYYMMDD')-to_date('20150101','YYYYMMDD');

    这样2015年一整年的没一天都有啦,我要10年呢?我要任何一段时间都没问题,有了这些日期,利用我们oracle强大的日期函数,立马就

    知道了这一天是星期几,是那个月,是哪个季度等等

    下面来写个存储过程,直接一步到位,将我们要的那段日期导入我们的日期表中,

    当然是创建我们的日期维度表:

    --创建时间维度表
    CREATE TABLE DIM_DATE(
    DATE_ID NUMBER,--20160809
    DATE_NAME DATE, --2016/8/9
    YEAR_HALF nvarchar2(10),--2016H1
    YEAR_QUARTER NVARCHAR2(10),--2016Q3
    YEAR_MONTH NUMBER,--201608
    QUARTER CHAR(2), --Q1
    MONTH_NAME NVARCHAR2(15),--August
    MONTH_NUMBER NUMBER,  --8
    WEEK_NAME NVARCHAR2(10),--Tuesday
    WEEK_NUMBER NUMBER); --2
    --创建存储过程
    CREATE OR REPLACE PROCEDURE PRD_UPDATE(startDate number,endDate number) AS
           v_Date_Name date;
           v_year number;
           v_half number;
           v_quarter_number number;
           v_month_name varchar2(10);
           v_month_number number;
           v_week_name varchar2(10);
           v_week_number number;  
           Idate_Id number; 
           CURSOR c_date IS 
           SELECT DATE_ID FROM DIM_DATE;
           c_row c_date%rowtype;       
     BEGIN
          MERGE INTO DIM_DATE t1
          USING(SELECT to_date(startDate,'YYYYMMDD')+rownum-1 AS d FROM dual connect by rownum<=
          to_date(endDate,'YYYYMMDD')-to_date(startDate,'YYYYMMDD')) t2
          ON (t1.DATE_NAME=t2.d)
          when not matched then
            insert(DATE_ID,CREATEDATE) values(to_char(t2.d,'YYYYMMDD'),sysdate);
          for c_row in c_date loop
            Idate_Id:=c_row.DATE_ID;
           v_year:=substr(Idate_Id,1,4);
           v_Date_Name:=to_date(Idate_Id,'YYYY/MM/DD');
           v_quarter_number:=to_char(v_Date_Name,'Q');
           v_month_name:=to_char(v_Date_Name,'MONTH');
           v_month_number:=to_char(v_Date_Name,'MM');
           v_week_name:=to_char(v_Date_Name,'DAY'); 
           v_week_number:=to_char(v_Date_Name,'D');
           dbms_output.put_line(v_Date_Name);
           if(v_month_number>6) then
            v_half:=2;
            else
              v_half:=1;
              end if;
            dbms_output.put_line(v_half);
     UPDATE DIM_DATE SET
            DATE_NAME=v_Date_Name,
            YEAR_HALF=v_year||'H'||v_half,
            YEAR_QUARTER=v_year||'Q'||v_quarter_number,
            YEAR_MONTH=substr(Idate_Id,1,6),
            QUARTER = 'Q'||v_quarter_number,
            MONTH_NAME=v_month_name,
            MONTH_NUMBER=v_month_number,
            WEEK_NAME=v_week_name,
            WEEK_NUMBER=v_week_number,
            UPDATEDATE=SYSDATE
       WHERE DATE_ID = Idate_Id;     
       END LOOP;
      EXCEPTION
        WHEN OTHERS THEN 
        dbms_output.put_line('错误');
      END; 

    看看最终效果是这样的:

    DATE_ID
    20160809
    20160810
    DATE_ID DATE_NAME YEAR_HALF YEAR_QUARTER YEAR_MONTH QUARTER MONTH_NAME MONTH_NUMBER WEEK_NAME WEEK_NUMBER    
    20160809 2016/8/9 2016H2 2016Q3 201608 Q3 August 8 Tuesday 3    
    20160810 2016/8/10 2016H2 2016Q3 201608 Q3 August 8 Wednesday 4    

         

    1.不带参数的存储过程

    --1.不带参数的存储过程
    CREATE OR REPLACE PROCEDURE prd_getDate
    AS
    BEGIN
       dbms_output.put_line('Ready');
    END;

    2.带参数的存储过程

    --2.带参数的存储过程
    CREATE OR REPLACE PROCEDURE prd_getDate(name nvarchar2)
    AS
    BEGIN
       dbms_output.put_line(name);
    END;

    3.自定义变量的存储过程

    --3.自定义变量的存储过程
    CREATE OR REPLACE PROCEDURE prd_getDate(name nvarchar2)
    AS
    myName nvarchar2(100);
    BEGIN
      myName:='My name is '||name;
       dbms_output.put_line(name);
       dbms_output.put_line(myName);
    END;

    4.判断语句的存储过程

    CREATE OR REPLACE PROCEDURE prd_getDate( x number)
    AS
    myNumber number;
    BEGIN
      IF x>0 then
        dbms_output.put_line('大于0');
        myNumber := -x;
        dbms_output.put_line(myNumber);
        end if;
      if x=0 then
         dbms_output.put_line('等于0');
         myNumber := x;
         dbms_output.put_line(myNumber);
        end if;
      if x<0 then
        dbms_output.put_line('小于0');
        myNumber := x;
        dbms_output.put_line(myNumber);
        end if;
    END;

    或者

    CREATE OR REPLACE PROCEDURE prd_getDate( x number)
    AS
    myNumber number;
    BEGIN
      IF x>0 then
        dbms_output.put_line('大于0');
        myNumber := -x;
        dbms_output.put_line(myNumber); 
      elsif x=0 then
         dbms_output.put_line('等于0');
         myNumber := x;
         dbms_output.put_line(myNumber);
      else
        dbms_output.put_line('小于0');
        myNumber := x;
        dbms_output.put_line(myNumber);
        end if;
    END; 

    5.for循环游标

    CREATE OR REPLACE PROCEDURE prd_getDate
    AS
    date_str nvarchar2(30);
    CURSOR c_date IS SELECT t1.week_name,t1.date_name FROM DIM_DATE t1;
    c_row c_date%rowtype;
    BEGIN
      FOR c_row IN c_date LOOP
        date_str:=c_row.week_name;
        dbms_output.put_line(date_str);
        dbms_output.put_line(to_char(c_row.date_name,'YYYY/MM/DD'));
       END LOOP;
    END; 

      

      

  • 相关阅读:
    如何通过命令行窗口查看sqlite数据库文件
    eclipse自动补全的设置
    文本装饰
    注释和特殊符号
    文本装饰
    网页背景
    通过ArcGIS Server admin 查看和删除已注册的 Web Adaptor
    通过 ArcGIS Server Manager 查看已安装的 Web Adaptor
    通过 ArcGIS Server Manager 验证 DataStore
    Windows上安装ArcGIS Enterprise——以 Windows Server 2012 R2上安装 ArcGIS 10.8为例
  • 原文地址:https://www.cnblogs.com/Jims2016/p/5505925.html
Copyright © 2011-2022 走看看