zoukankan      html  css  js  c++  java
  • PL/SQL一个简短的引论

    前言
    文本


    PL/SQL


    (Procedure Language,程序语言)SQL 1999主要的数据库供应商提供结构化的共同语言  PL/SQL只有支持Oracle数据库


    基本的语法


    多行凝视   /*    */      单行凝视   --



    PLSQL程序块


    结构

    [declare]
    定义变量
    begin
    过程语句
    [exception]
    处理 异常
    end;


    样例 输出helloworld


    begin
      dbms_output.put_line('hello');
    end;
    --假设过程运行完没有输出,必须将server输出打开

    运行
     
    SQL> set serveroutput on/off;
    SQL> 
    SQL> begin
      2    dbms_output.put_line('hello');
      3  end;
      4  /
     
    hello
     
    PL/SQL procedure successfully completed


    变量


    declare
    变量名称   变量类型;
    begin

    end;
    标识符:不能以数字開始 长度不能超过30个字符


    变量初始化

    採用:= 进行赋值
    v_age number(10) := 10;

    变量类型


    number(m,n)  数字类型
    char()       固定长度字符串
    varchar2()   可变长度字符串 
    date         日期类型
    boolean(true/false/null)      布尔类型
    binary_integer  有符号整型
    注意:布尔类型不能直接输出


    代码演示样例




    注意:变量名称不能是SQLkeyword,最好不要和表中字段同名
    变量命名:
    v_实际含义的单词
    常量命名:
    c_实际含义 
    參数命名
    p_实际含义
    游标类型
    名称_cursor
    表类型
    名称_table
    记录类型
    名称_record
    变量作用域
    变量从声明開始到相应模块的end结束为它的作用域

    --变量作用域代码演示样例


    变量的其它类型


    1.表类型 


    定义表类型
    type  表类型名称 is table  of  表类型存储的基本类型 index by binary_integer
    声明变量为表类型
    变量名称  表类型名称


    表类型类似java中的数组,用来存储具有同种类型的数据




    属性:
    first  表示获得表类型的第一个下标
    last   表示获得表类型的最后一个下标
    count  表示表类型的数据个数
    next(下标) 表示下一个下标
    prior(下标) 表示前一个下标
    代码演示样例:


    表类型通过下标操作


    2.记录类型


     用来存储一条记录
     type  记录类型名称 is record(field1 类型,field2 类型)
     定义变量,将变量类型设置成记录类型
     v_record 记录类型名称
    代码演示样例



    定义记录类型的简单方式


     %rowtype 定义记录类型
     表名%rowtype
    代码演示样例
    <div></div>


    定义表类型的简单方式


     %type  定义表类型
     表名.字段名%type
    代码演示样例



    代码演示样例: 将表中的全部记录存在一个变量中


    操作符


    算数运算符


    跟java一致
    v_age number(3) := 0;

    v_age := v_age +1;


    比較运算符


    >  < >= = 不等于!= <> ~= ^= 

    逻辑运算符


    and or not 


    between   and 


    赋值运算符


    :=

    流程控制


       分支:


       1.if分支
         if  布尔表达式  then
         …………
         else
         …………
         end if;


       多个分支:
         if  布尔表达式  then
         …………
         elsif 布尔表达式 then
         …………
         elsif 布尔表达式 then
         …………
         else
         …………
         end if;


    案例: --查找员工,依据职位进行工资的添加




    2.case分支,类似java中的switch````case



    case 变量
    when 条件 then
    语句·····
    when 条件 then
    语句·····
    when 条件 then
    语句·····
    else
    语句·····
    end case;


    案例


        循环:


    1.loop循环


    定义一个循环指数
    v_index binary_integer := 0;


    loop
    if v_index=循环次数 then
      exit;
    end if;
    循环体




    循环指数自增
    v_index := v_index+1;
     


    end loop;

    案例:
    --loop循环
    declare
    --定义循环指数
    v_index binary_integer :=1;
    begin
    --定义loop循环
    loop
    --定义推出循环的条件
    if v_index=5 then
    exit;
    end if;
    --运行循环体
    dbms_output.put_line(v_index);
    --循环指数自增
    v_index := v_index+1;
    end loop;
    end;

    2.for循环

    定义一个循环指数 
    v_index binary_integer;


    for 循环指数 in 下限指数..上限指数 loop
    循环体
    end loop;


    案例:
    --for循环


    注意:循环指数的開始一定要小于结束

    通过reversekeyword实现循环反转

    --for循环反转
    declare
      v_index binary_integer;
    begin
      for v_index in reverse 10..20 loop
      dbms_output.put_line(v_index);
      end loop;
    end;



    3.while循环



    定义循环指数
    v_index binary_integer := 1;

    while 布尔表达式 loop
    循环体
    循环指数自增
    end loop;


    案例:
    --while循环
    declare
      v_index binary_integer := 1;
    begin
      while v_index<5 loop
      dbms_output.put_line(v_index);
      v_index := v_index+1;
      end loop;
    end;



    循环嵌套


    通过<<label>>标签方式来控制循环


    案例:


    4.goto跳转






    PL/SQL中书写定义sql


    1.DQL语言


    select 语句要求:1.必须写intokeyword
    2.查询语句仅仅能有一条返回值
    异常演示样例: 没有值  no_data_found。值过多  too_many_rows

    2.DML(insert/update/delete)



    注意:运行DML语句要处理事务

    动态传參
    &+变量来实现动态传參


    --运行DML语句
    declare
    begin
        --普通DML语句
        delete from emp where empno=&xx;
        --事务处理
        commit;
    end;


    3.DDL(create/drop/alter/truncate)


    DDL语句要在 execute  immediate('DDL')



    游标(cursor)



    sql语句运行时会在内存中开辟一个区域。用来存放运行的sql语句以及返回的数据,我们把这个内存区域叫做上下文环境(context);游标就是指向这个上下文环境的指针。


    游标分类

    隐式游标:由数据库管理系统创建运行
    显示游标:有程序猿负责创建运行和关闭的游标

    游标的属性

    %rowcount  存储的是游标运行时所影响的记录条数

    操作属性

    显示游标:自己定义游标名称%rowcount
    隐式游标:sql%rowcount
    %found  推断当前数据有没有下一条 true/fase
    %notfound 推断当前数据有没有下一条 true/fase
    %isopen  推断游标是否开启 







    显示游标


    1.创建游标
    cursor 游标名称 is 查询语句
    2.开启游标
    open 游标名称
    3.获取数据
    fetch 游标名称 into 变量
    4.关闭游标
    close 游标名称

    案例: --显示游标


    for循环来循环游标





    定义游标时传递參数




    注意:设置形參时不要写參数的长度,实參是在开启游标的时候传递
         游标不能反复开启和关闭


    定义游标类型的变量



    1.定义游标类型


    type 游标类型名称 is ref cursor return 返回结果类型


    2.定义游标类型的变量



    变量名称   游标类型名称





    过程和函数


    过程(procedure)又叫存储过程(stored procedure)。是一个有名称的PL/SQL程序块
    过程相当于java中的方法。它注重的是实现某种业务功能
    函数(function)也相当于java中的方法。它注重计算而且总是有返回结果
    过程和函数都是可以永久存储在数据库中的程序代码块。应用时通过调用运行


    过程的基本结构


    create [or replace ] procedure 过程名称(形參名称  形參类型,形參名称  形參类型······)
    is | as 
    定义变量
    begin
    过程体
    exception
    异常
    end;


    1.含有输入參数的过程


    输入參数  用in 标识  可省略



    2.无參的过程


    3.有输出參数的过程


    输出參数用 out 标识




    过程的调用



    1.通过匿名块调用


    输入參数


    输出參数过程



    无參的过程

    begin
        mypro_noparam;
    end;


    2.命令行调用


    调用输入參数
    SQL> exec mypro(7788,3000);
    输出參数
    SQL> var v_sal number;   注冊变量
    SQL> exec mypro(7788,:v_sal); :变量名称 使用变量接收输出
    调用无參
    SQL> exec mypro;

    演示样例代码:
    1.写一个过程封装emp表中的数据

    2.写一个过程输入员工编号。通过游标获取输出该员工相应下属的信息

    3./*计算100-200的素数*/


    3.通过java调用过程

    java调用过程代码演示样例




    自己定义函数


    function.sql代码演示样例



    异常


    系统异常分为提前定义异常和非提前定义异常
    提前定义异常。是由数据库定义好。含有异常编码,异常名称,异常信息的这么一种异常。大概有20种,比如too_many_rouws;no_data_found;zero_divide.
    非提前定义异常:异常编码。异常信息,但没有异常名称
    非提前定义异常代码演示样例

    自己定义异常


    自己定义异常代码演示样例

    包用于管理过程和函数
    包分为包头和包体

    包的代码演示样例




    jdbc调用含有包的过程体的代码演示样例


    注:包一定要有包头,包头负责声明函数、过程、变量和常量
    包体详细来实现包头所声明定义的函数和过程
    包体封装实现
    包头可单独定义,那么单独定义的包头仅仅能含有常量


    触发器 trigger


    类似java中的Listener

    触发器由数据库管理系统负责调用和运行
    通过触发触发器所监听的事物来实现触发器的调用

    表级别的触发器(对于整个数据库表做监听)
    行级别的触发器(对于表中的每一行做监听)

    触发器代码演示样例




    注:触发器的运行顺序

    有表级别的触发器,行级别的触发器作用于同一个表

    1.before表级别触发器
    2.before 行级别触发器
    3.after 行级别触发器
    4.after 表级别触发器


    系统触发器


    DBA用来调试系统
    on database


    注:
    触发器不带參数,没有放回值。不作事务处理




    总结

    使用SQL*PLUS登陆远程数据库的配置

    手工编辑

    $ORACLE_HOME/network/admin/tnsnames.ora文件。

    工具编辑

    通过Net Configuration Assistant Net Manager进行本地网络服务名配置。

    UNIX系统

    使用“sqlplus”命令登陆。

    比如DEV =

      (DESCRIPTION =

        (ADDRESS_LIST =

          (ADDRESS = (PROTOCOL = TCP)(HOST = 172.11.11.11)(PORT = 1521))

        )

        (CONNECT_DATA =

          (SERVICE_NAME = m11oti11on11)

        )

      )

     

    使用SET命令配置环境

    SQL*PLUS系统提供了很多SET命令。

    使用SET命令能够控制当前环境的设置。SET命令的语法形式例如以下:

    SET system_variable value

    在上面的语法中, system_variable变量用来控制当前环境,value是该系统变量的当前值。

    假设希望得到当前指定SET命令的设置,那么能够使用SHOW [ALL]命令显示当前环境设置。

    建立数据库

    CREATE DATABASE database;


    建立顺序号


    CREATE SEQUENCE CINOSEQ MINVALUE 1 MAXVALUE 4000000000 START WITH 41 INCREMENT BY 1 NOCYCLE;

    创建索引


    语法
    CREATE [ UNIQUE ] INDEX index
    ON table "("
         column [ ASC | DESC]
      [, column [ ASC | DESC]]... ")" ;

    改动表


    在表的后面添加一个字段


    ALTER TABLE 表名 ADD 字段名 字段名描写叙述   [ DEFAULT expr ][ NOT NULL ][ ,字段名2 ……];


    改动表里字段的定义描写叙述


    ALTER TABLE 表名 MODIFY 字段名1 字段名1描写叙述  [ DEFAULT expr ][ NOT NULL ][ ,字段名2 ……];


    删除表里的某个字段


    ALTER TABLE 表名 DROP 字段名;


    给表里的字段加上/禁止/启用约束条件


    ALTER TABLE 表名 ADD | DISABLE | ENABLE CONSTRAINT 约束名 PRIMARY KEY (字段名1[,字段名2 ……]);
    ALTER TABLE 表名 ADD | DISABLE | ENABLE CONSTRAINT 约束名 UNIQUE (字段名1[,字段名2 ……]);

    删除表里的约束条件


    ALTER TABLE 表名 DROP CONSTRAINTS 约束名 [CASCADE];
    会把约束相关的索引一起删除,CASCADE能同一时候删去外键的约束条件。

    删除索引


    DROP INDEX 索引名;
    删除顺序号
    DROP SEQUENCE 顺序名;
    删除数据库表
    DROP TABLE 表名 [{CASCADE | CASCADE CONSTRAINTS | RESTRICT}] ;

    查询


    SELECT [ DISTINCT | ALL ]
         { * |  column [[AS] alias] }
         FROM { table | view }[ alias ]
              [ WHERE condition]
                  [ { [ START WITH condition ]
                      CONNECT BY condition
                  | GROUP BY expr [, expr]...
                  | [HAVING condition] }]

    单表查询


    SELECT t.* FROM table t WHERE t.c1=‘…’;


    内连接


    SELECT t1.* FROM table1 t1 INNER JOIN table2 t2 ON t1.column1=t2.column2;


    SELECT t1.* FROM table1 t1, table2 t2 WHERE t1.column1=t2.column2;


    外连接


    SELECT t1.* FROM table1 t1 { [ LEFT | RIGTH ] } [ OUTER ] JOIN table2 t2 ON t1.column1=t2.column2;


    SELECT t1.* FROM table1 t1, table2 t2  WHERE t1.column1=t2.column2(+);


    SELECT t1.* FROM table1 t1, table2 t2  WHERE t1.column1(+)=t2.column2;


    子查询


    SELECT … FROM (SELECT … FROM t1, [t2, …]  WHERE condition1) WHERE condition2;


    SELECT … FROM t1 WHERE t1.c1 IN (SELECT t2.c2 FROM t2 WHERE condition);


    SELECT … FROM t1 WHERE t1 WHERE [NOT] EXISTS ( SELECT t2.c2 FROM t2 WHERE condition );


    树查询(递归查询)


    SELECT t1.* FROM table t1 START WITH  t1.c1= … CONNECT BY PRIOR t1.c1=t1.c2;

    connect by 是结构化查询中用到的。其基本的语法是:

    select * from tablename start with cond1

    connect by cond2

    where cond3;

     

     

    oracle中的select语句能够用START WITH...CONNECT BY PRIOR子句实现递归查询,connect by 是结构化查询中用到的,其基本的语法是:

    select * from tablename start with cond1

    connect by cond2

    where cond3;

    简单说来是将一个树状结构存储在一张表里。比方一个表中存在两个字段:

    id,parentid那么通过表示每一条记录的parent是谁。就能够形成一个树状结构。

    用上述语法的查询能够取得这棵树的全部记录。

    当中COND1是根结点的限定语句,当然能够放宽限定条件,以取得多个根结点,实际就是多棵树。

    COND2是连接条件。当中用PRIOR表示上一条记录。比方 CONNECT BY PRIOR ID=PRAENTID就是说上一条记录的ID是本条记录的PRAENTID。即本记录的父亲是上一条记录。

    COND3是过滤条件。用于对返回的全部记录进行过滤。

     

    对于oracle进行简单树查询(递归查询)

    DEPTID           NUMBER                   部门id

    PAREDEPTID   NUMBER                   父部门id(所属部门id)

    NAME              CHAR (40 Byte)        部门名称

     

    通过子节点向根节点追朔.

     

    select * from persons.dept start with deptid=76 connect by prior paredeptid=deptid

    通过根节点遍历子节点.

     

    select * from persons.dept start with paredeptid=0 connect by prior deptid=paredeptid

    可通过level keyword查询所在层次.

     

    select a.*,level from persons.dept a start with paredeptid=0 connect by prior deptid=paredeptid

    PS:start with 后面所跟的就是就是递归的种子。也就是递归開始的地方;

    connect by  prior后面的字段顺序是有讲究的;

    若prior缺省:则仅仅能查询到符合条件的起始行,并不进行递归查询。比如:

     select * from emp  start with  empno=7839 connect by  empno=mgr;
     
    EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO
    ----- ---------- --------- ----- ----------- --------- --------- ------
     7839 KING       PRESIDENT       1981-11-17    5000.00               10

     例:

    select * from table

    start with org_id = 'HBHqfWGWPy'

    connect by prior org_id = parent_id;

     

    简单说来是将一个树状结构存储在一张表里,比方一个表中存在两个字段:

    org_id,parent_id那么通过表示每一条记录的parent是谁,就能够形成一个树状结构。

    用上述语法的查询能够取得这棵树的全部记录。

    当中:

    条件1 是根结点的限定语句,当然能够放宽限定条件,以取得多个根结点,实际就是多棵树。

    条件2 是连接条件,当中用PRIOR表示上一条记录,

    比方 CONNECT BY PRIOR org_id = parent_id就是说上一条记录的org_id 是本条记录的parent_id,即本记录的父亲是上一条记录。

    条件3 是过滤条件,用于对返回的全部记录进行过滤。

     

    简介例如以下:

    在扫描树结构表时,须要依此訪问树结构的每一个节点。一个节点仅仅能訪问一次,其訪问的过程例如以下:

    第一步:从根节点開始;

    第二步:訪问该节点;

    第三步:推断该节点有无未被訪问的子节点,若有,则转向它最左側的未被訪问的子节点,并运行第二步,否则运行第四步;

    第四步:若该节点为根节点,则訪问完成,否则运行第五步;

    第五步:返回到该节点的父节点,并运行第三步骤。

    总之:扫描整个树结构的过程也即是中序遍历树的过程。

     

    1. 树结构的描写叙述

    树结构的数据存放在表中,数据之间的层次关系即父子关系,通过表中的列与列间的关系来描写叙述,如 EMP 表中的 EMPNO 和 MGR 。 EMPNO 表示该雇员的编号, MGR 表示领导该雇员的人的编号。即子节点的 MGR 值等于父节点的 EMPNO 值。在表的每一行中都有一个表示父节点的 MGR (除根节点外)。通过每一个节点的父节点。就能够确定整个树结构。

    select * from emp  start with  empno=7839 connect by prior empno=mgr;

    在 SELECT 命令中使用 CONNECT BY 和 START WITH 子句能够查询表中的树型结构关系。其命令格式例如以下:

    SELECT ...

    CONNECT BY {PRIOR 列名 1= 列名 2| 列名 1=PRIOR 裂名 2}

    [START WITH] ;

    当中: CONNECT BY 子句说明每行数据将是按层次顺序检索,并规定将表中的数据连入树型结构的关系中。

    PRIORY 运算符必须放置在连接关系的两列中某一个的前面。对于节点间的父子关系。 PRIOR 运算符在一側表示父节点,在还有一側表示子节点。从而确定查找树结构的顺序是自顶向下还是自底向上。

    在连接关系中,除了能够使用列名外,还同意使用列表达式。 START WITH 子句为可选项。用来标识哪个节点作为查找树型结构的根节点。若该子句被省略,则表示全部满足查询条件的行作为根节点。

    START WITH: 不但能够指定一个根节点。还能够指定多个根节点。

     

     

    2. 定义查找起始节点

    在自顶向下查询树结构时,不但能够从根节点開始,还能够定义不论什么节点为起始节点。以此開始向下查找。这样查找的结果就是以该节点为開始的结构树的一枝。

     

    3.使用 LEVEL

    在具有树结构的表中。每一行数据都是树结构中的一个节点,因为节点所处的层次位置不同。所以每行记录都能够有一个层号。层号依据节点与根节点的距离确定。

    不论从哪个节点開始。该起始根节点的层号始终为 1 ,根节点的子节点为 2 , 依此类推。

     

    4.节点和分支的裁剪

    在对树结构进行查询时,能够去掉表中的某些行,也能够剪掉树中的一个分支,使用 WHERE 子句来限定树型结构中的单个节点。以去掉树中的单个节点。但它却不影响其后代节点(自顶向下检索时)或前辈节点(自底向顶检索时)。

    5.排序显示

    像在其他查询中一样,在树结构查询中也能够使用 ORDER BY 子句,改变查询结果的显示顺序。而不必依照遍历树结构的顺序。

     

     

    插入数据insert


    INSERT INTO { table | view } ["("column [, column]...")"]{ VALUES "(" expression[, expression]...")" | subquery };
    说明
    使用INSERT语句一次仅仅能插入一行数据。

    update


    UPDATE { table | view } [ alias ] SET column = { expression | subquery } [, column = { expr | subquery }]...[WHERE condition] ;
    说明
    在改动表中数据时,不能破环表的完整性约束。假设改动的数据与完整性约束有冲突,那么这样的改动操作不能成功。


    delete


    DELETE FROM { table | view }[WHERE condition] ;
    说明
    就像改动数据一样,删除数据时也不能破坏数据库的完整性约束。

    事务


    事务是一个逻辑上的单元。

    要么所有成功,要么所有失败。
    在以下的情况下系统自己主动地结束一个事务:
    COMMIT或ROLLBACK命令。
    DDL,如CREATE TABLE语句;
    退出SQL*PLUS;
    系统失败。

    语法


    COMMIT [WORK] ;
    ROLLBACK [{ WORK | TO savepoint_name }] ;
    SAVEPOINT savepoint_name ;
    REMOVE SAVEPOINT <savepoint_name>;


    数据的导入和导出的样例


    将数据库TEST全然导出,usernamesystem passwordmanager 导出到daochu.dmp中
    exp system/manager@TEST file=d:daochu.dmp full=y
    将数据库中的表inner_notify、notify_staff_relat导出
    exp aichannel/aichannel@TESTDB2 file= datanewsmgnt.dmp tables= (inner_notify,notify_staff_relat)
    样例:导入
    将daochu.dmp 中的数据导入 TEST数据库中
    imp system/manager@TEST file=daochu.dmp
    将daochu.dmp中的表table1 导入
    imp system/manager@TEST file=d:daochu.dmp tables=(table1)

  • 相关阅读:
    python-scapy学习笔记-(1)
    python系统性能模块笔记
    Python爬虫总结
    pm2的的常用命令及用法
    Javascript的map与forEach的区别
    对MVVM思想的在认识
    RN的打包
    undefined与null的区别
    rem与em的区别
    JS的函数参数传递为值传递
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/5034155.html
Copyright © 2011-2022 走看看