经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » Oracle » 查看文章
Oracle数据库之第四篇
来源:cnblogs  作者:小小一  时间:2019/10/8 9:20:19  对本文有异议
  1. /*
  2. 授权命令 grant 权限 to 用户
  3. 授权可以授予多个权限
  4. grant connect,resource to baidu
  5. 收回权限 revoke 权限 from 用户
  6. revoke dba from baidu
  7. 创建用户 分配表空间--指定用户的默认表空间
  8. create table p(..) 建表存在默认表空间
  9. --建表时候指定表空间
  10. create table p(...) talebspace 表空间名
  11. */
  12. /*
  13. PlSql编程语言 procedure language 过程语言
  14. 是在sql语句中加入一些处理过程的语句
  15. 常见的条件表达式 if else 还有循环结构
  16. 基本结构
  17. declare
  18. --声明部分 理解为定义
  19. --声明使用的变量
  20. begin
  21. --处理逻辑的代码块
  22. end;
  23. */
  24. --psSql简单示例
  25. declare
  26. v_n number := 1; --声明数值变量 赋值使用符号:=
  27. v_s varchar2(4) :='s'; --声明字符类型变量
  28. emp_ename emp.ename%type ;-- 引用类型变量
  29. emp_row emp%rowtype ;-- 记录类型变量
  30. begin
  31. dbms_output.put_line('v_n====='||v_n); --输出语句相当于sys out
  32. dbms_output.put_line('v_s====='||v_s);
  33. select ename into emp_ename from emp where empno=7499; --使用into关键字赋值
  34. dbms_output.put_line('emp_ename====='||emp_ename);
  35. select * into emp_row from emp where empno = 7499; --赋值记录类型变量
  36. dbms_output.put_line('员工编号=='||emp_row.empno||'员工姓名'||emp_row.ename);
  37. end;
  38. /*
  39. plsql 的条件表达式判断
  40. if .. 处理语句 else if ..处理语句
  41. -------------------------
  42. if .. then
  43. elsif .. then
  44. else
  45. end if;
  46. */
  47. ---使用条件表达式判断员工的工资 使用汉字输出
  48. declare
  49. emp_row emp%rowtype ;-- 记录类型变量
  50. begin
  51. select * into emp_row from emp where empno = 7499; --赋值记录类型变量
  52. --使用表达式判断工资
  53. if emp_row.sal > 3000 then
  54. dbms_output.put_line('员工工资大于3000=='||emp_row.sal);
  55. elsif emp_row.sal < 1000 then
  56. dbms_output.put_line('员工工资小于1000=='||emp_row.sal);
  57. else
  58. dbms_output.put_line('员工工资位于1000到3000之间=='||emp_row.sal);
  59. end if;
  60. end;
  61. /*
  62. 循环结构
  63. 第一种-----
  64. loop
  65. exit when 条件
  66. end loop;
  67. 第二种 ---
  68. while 条件 loop
  69. end loop;
  70. 第三种 ---
  71. for 变量 in 范围 loop
  72. end loop;
  73. */
  74. -------使用循环输出数字 1-----10
  75. /*
  76. 第一种
  77. loop
  78. exit when 条件
  79. end loop;
  80. */
  81. declare
  82. v_n number :=1;
  83. begin
  84. loop
  85. --只是用来判断退出使用的,并不是相当于if()else{}
  86. exit when v_n>10 ; --退出条件
  87. dbms_output.put_line(v_n);
  88. v_n:=v_n+1; --自增
  89. end loop;
  90. end;
  91. /*
  92. 第二种
  93. while 条件 loop
  94. end loop;
  95. */
  96. declare
  97. v_n number :=1;
  98. begin
  99. while v_n<11 loop
  100. dbms_output.put_line(v_n);
  101. v_n:=v_n+1; --自增
  102. end loop;
  103. end;
  104. /*
  105. 第三种
  106. for 变量 in 范围 loop 变量的声明和范围的控制是由for循环自动执行
  107. end loop;
  108. */
  109. declare
  110. begin
  111. for i in 1..10 loop
  112. dbms_output.put_line(i);
  113. end loop;
  114. end;
  115. /*
  116. 游标 光标 是用于接收查询的记录结果集 ResultSet 提示记录使用.next()
  117. 游标的使用步骤
  118. 声明游标 cursor 游标名 is select 语句 指定游标的记录结果集
  119. 打开游标 open 游标名
  120. 提取游标 fetch 游标名 into 记录类型变量
  121. 关闭游标 close cursor
  122. 游标的两个属性 游标名%found : 判断它有找到
  123. 游标名%notfound : 判断它没有找到
  124. if emp_cursor%found then
  125. dbms_output.put_line('found');
  126. elsif emp_cursor%notfound then
  127. dbms_output.put_line('notfound');
  128. elsif emp_cursor%notfound is null then
  129. dbms_output.put_line('null');
  130. end if;
  131. */
  132. --使用while循环结构演示游标
  133. declare
  134. --声明游标
  135. cursor emp_cursor is select * from emp;
  136. --声明记录类型变量 用于接收游标提取的记录
  137. emp_row emp%rowtype;
  138. begin
  139. --打开游标
  140. open emp_cursor;
  141. --提取游标(判断下一个是否有值)
  142. fetch emp_cursor into emp_row ;
  143. --有值就执行while循环
  144. while emp_cursor%found loop
  145. dbms_output.put_line(emp_row.empno||'员工姓名'||emp_row.ename);
  146. --继续提取游标(并判断下一个是否有值)
  147. fetch emp_cursor into emp_row ;
  148. end loop;
  149. close emp_cursor;
  150. end;
  151. /*
  152. loop
  153. exit when 游标提取不到
  154. end loop
  155. */
  156. declare
  157. --声明游标
  158. cursor emp_cursor is select * from emp;
  159. --声明记录类型变量 用于接收游标提取的记录
  160. emp_row emp%rowtype;
  161. begin
  162. --打开游标
  163. open emp_cursor;
  164. loop
  165. fetch emp_cursor into emp_row;
  166. exit when emp_cursor%notfound;
  167. dbms_output.put_line(emp_row.empno||'员工姓名'||emp_row.ename);
  168. end loop;
  169. close emp_cursor;
  170. end;
  171. --使用游标提取某个部门的员工信息
  172. --声明带参数的游标信息
  173. declare
  174. --声明游标
  175. cursor emp_cursor(dno number) is select * from emp where deptno = dno ;
  176. --声明记录类型变量 用于接收游标提取的记录
  177. emp_row emp%rowtype;
  178. begin
  179. --打开游标 时候传入参数
  180. open emp_cursor(10);
  181. loop
  182. fetch emp_cursor into emp_row;
  183. exit when emp_cursor%notfound;
  184. dbms_output.put_line(emp_row.empno||'员工姓名'||emp_row.ename);
  185. end loop;
  186. close emp_cursor;
  187. end;
  188. /*
  189. 错误信息开发中的异常
  190. 数据库中叫做 例外
  191. 异常的分类 1.系统异常 系统定义好的异常
  192. 2.自定义的异常
  193. new 自定义类继承Exception 自定义传值(错误代码,提示信息)
  194. 使用场景
  195. 不满足某些特定业务场景,抛出自定义异常
  196. 异常的处理
  197. java try{}catche(IndexOutOfBoundException e){}catche(Exception e){}
  198. java try{}catche(Exception e){} catche(IndexOutOfBoundException e){}--报错
  199. 数据库可以捕捉处理异常
  200. exception 关键字捕捉异常
  201. when 异常类型 then 处理语句 判断异常类型 处理异常
  202. */
  203. --异常的简单示例
  204. /*
  205. --除0的异常 除数为0
  206. --赋值错误
  207. */
  208. declare
  209. v_n number :=0;
  210. v_m number :=1;
  211. begin
  212. v_m:='s'; --将字符串赋值给数值变量
  213. v_m:= v_m/v_n;
  214. exception
  215. when zero_divide then
  216. dbms_output.put_line('除数不能为0');
  217. when value_error then
  218. dbms_output.put_line('赋值有误');
  219. end;
  220. ---处理太多记录数异常
  221. declare
  222. emp_row emp%rowtype ;-- 记录类型变量
  223. begin
  224. select * into emp_row from emp ; --赋值记录类型
  225. exception
  226. when too_many_rows then
  227. dbms_output.put_line('太多记录数');
  228. when others then --others是最大范围的异常 相当于java Exception
  229. dbms_output.put_line('其他异常');
  230. end;
  231. /*
  232. 需求 :使用游标查询部门下的员工信息
  233. 如果部门下没有员工 报错提示
  234. 需要自定义异常
  235. 变量名 exception --声明自定义异常
  236. */
  237. declare
  238. cursor emp_cursor is select * from emp where deptno= 40; --游标结果集不存在
  239. emp_row emp%rowtype ;-- 记录类型变量
  240. no_dept_emp exception ; --声明自定义异常
  241. begin
  242. open emp_cursor; --打开游标
  243. fetch emp_cursor into emp_row;
  244. if emp_cursor%notfound then
  245. --没有员工 抛出错误异常
  246. raise no_dept_emp;
  247. end if;
  248. close emp_cursor;
  249. exception
  250. when no_dept_emp then
  251. dbms_output.put_line('部门下面没人,快招人吧');
  252. end;
  253. /*
  254. 存储过程 是一段封装好的代码块,过程是编译好放在服务器提供开发人员调用
  255. 封装的代码块意义: 提升开发效率 可以复用 谁用直接调用
  256. 提升运行效率 一调用直接运行
  257. 语法:create [or repalce] procedure 过程名称(参数名 out|in 参数类型)
  258. as|is
  259. --声明变量的部分
  260. begin
  261. --处理过程语句代码块
  262. end;
  263. 调用存储过程
  264. 在begin和end之间使用 过程名传参调用
  265. */
  266. --存储过程的简单示例 使用存储过程给某个员工增加工资100
  267. create or replace procedure add_sal(eno in number )
  268. as
  269. emp_sal number :=0;
  270. begin
  271. select sal into emp_sal from emp where empno = eno ;
  272. dbms_output.put_line('涨工资之前是===='||emp_sal);
  273. update emp set sal=sal+100 where empno = eno;
  274. select sal into emp_sal from emp where empno = eno ;
  275. dbms_output.put_line('涨工资之后是===='||emp_sal);
  276. commit;
  277. end;
  278. --------调用存储过程
  279. declare
  280. begin
  281. add_sal(7499);
  282. end;
  283. /*
  284. 使用存储过程统计某个员工的年薪,年薪需要返回输出打印
  285. in 类型输入参数可以 省略 默认就是输入参数
  286. */
  287. create or replace procedure count_sal(eno number,year_sal out number)
  288. as
  289. begin
  290. select sal*12+nvl(comm,0) into year_sal from emp where empno=eno; --使用into赋值给输出参数
  291. end;
  292. ----调用存储过程计算年薪
  293. declare
  294. v_emp_sal number :=0;
  295. begin
  296. count_sal(7499,v_emp_sal);
  297. dbms_output.put_line('年薪为=='||v_emp_sal);
  298. end;
  299. /*
  300. 使用存储过程 查询出某个部门的员工信息
  301. 某个部门应该接受一个in类型的输入参数
  302. 查询到的部门员工多条记录返回应该使用结果集
  303. 声明游标 cursor 游标名 is select 语句指定结果集
  304. 系统引用游标
  305. sys_refcursor
  306. 声明系统引用游标 变量名 sys_refcursor; --不需要指定结果集
  307. 打开游标 open 系统引用游标 for select 语句 --使用for关键字装入数据
  308. */
  309. create or replace procedure dept_emp(dno number,cusor_emp out sys_refcursor)
  310. as
  311. begin
  312. --根据传进来的部门编号给游标装入结果集数据
  313. open cusor_emp for select * from emp where deptno = dno;
  314. end;
  315. ----调用存储过程查询部门下的员工
  316. declare
  317. cursor_emp sys_refcursor; --声明系统引用游标传参使用
  318. emp_row emp%rowtype ;--记录类型变量
  319. begin
  320. dept_emp(10,cursor_emp);
  321. --提取游标中的数据
  322. loop
  323. fetch cursor_emp into emp_row;
  324. exit when cursor_emp%notfound;
  325. dbms_output.put_line('编号'||emp_row.empno||'姓名'||emp_row.ename);
  326. end loop;
  327. close cursor_emp;
  328. end;
  329. /*
  330. 存储函数 是一段封装好的代码块,是编译好放在服务器提供开发人员调用
  331. 封装的代码块意义: 提升开发效率 可以复用 谁用直接调用
  332. 提升运行效率 一调用直接运行
  333. 语法:create [or repalce] function 函数名称(参数名 out|in 参数类型) return 数据类型
  334. in 代表传入参数,out 代表传出参数
  335. as|is
  336. --声明变量的部分
  337. begin
  338. --处理过程语句代码块
  339. --return 变量
  340. end;
  341. 调用存储函数
  342. 在begin和end之间使用 函数名传参调用 函数必须使用变量接收 返回值
  343. */
  344. --使用存储函数统计某个员工的年薪
  345. create or replace function count_emp_sal(eno number,year_sal out number) return number
  346. as
  347. v_sal number :=0;
  348. begin
  349. select sal*12+nvl(comm,0) into year_sal from emp where empno=eno; --使用into赋值给输出参数
  350. return v_sal;
  351. end;
  352. --不带out类型输出参数统计年薪
  353. create or replace function count_sal_noout(eno number) return number
  354. as
  355. v_sal number :=0;
  356. begin
  357. select sal*12+nvl(comm,0) into v_sal from emp where empno=eno; --使用into赋值给输出参数
  358. return v_sal;
  359. end;
  360. --调用函数统计年薪
  361. declare
  362. emp_sal number:=0;
  363. total_sal number :=0;
  364. begin
  365. --total_sal := count_emp_sal(7499,emp_sal);
  366. total_sal := count_sal_noout(7499);
  367. dbms_output.put_line(emp_sal);--0
  368. dbms_output.put_line(total_sal); --统计后年薪
  369. end;
  370. /*
  371. 存储函数和过程的区别
  372. 1.创建的关键字 procedure funciton
  373. 2.创建函数 必须使用return 声明函数的返回变量数据类型
  374. 3.在函数的方法体内 必须使用return 返回一个变量
  375. 4.函数的调用 必须有变量接收返回值
  376. 5.函数可以用在select 查询语句中 select emp.*,count_sal_noout(empno) from emp;
  377. 存储函数和过程使用场景
  378. 开发规范 java代码待用过程 过程是用来处理业务逻辑代码
  379. 如果逻辑中需要用到一些功能性的封装,可以调用函数
  380. 90%情况下 函数和过程通用 过程可以调用函数,函数同样可以调用过程
  381. */
  382.  
  383. /*
  384. 触发器 是一个监视器,监视对表中数据的操作
  385. 如果对数据的操作满足触发器的执行条件,
  386. 触发器会自动运行
  387. 触发器语法:
  388. create or repalce trigger 触发器名称
  389. after|before --触发器执行时机
  390. insert|update|delete --监视的动作
  391. on 表名 --表级触发器
  392. declare
  393. begin
  394. end;
  395. 行级触发器 insert update delete
  396. :new 动作之后的记录 要插入的记录 修改后的记录 空
  397. :old 动作之前的记录 空 原始的记录 原始的记录
  398. */
  399. --创建触发器监视表,如果表中有数据插入,输出一个欢迎语句
  400. create or replace trigger insert_trigger
  401. after
  402. insert
  403. on p
  404. declare
  405. begin
  406. dbms_output.put_line('欢迎加入!');
  407. end;
  408. ----插入数据测试效果
  409. insert into p values(1,'zs');
  410. commit;
  411. --插入数据不能在休息日插入数据
  412. --休息日 周六和周日
  413. /*
  414. raise_application_error(v1,v2) v1错误代码 v2是提示语句
  415. -20000 -20999
  416. */
  417. create or replace trigger insert_no_work
  418. before
  419. insert
  420. on p
  421. declare
  422. v_day varchar2(10) ;
  423. begin
  424. --获取到当前星期
  425. select to_char(sysdate,'day') into v_day from dual;
  426. --判断星期是否在休息日
  427. if trim(v_day) in ('saturday','sunday') then
  428. --如果休息 错误提示
  429. raise_application_error(-20001,'不能休息日插入数据');
  430. end if;
  431. end;
  432. ----插入数据测试效果
  433. insert into p values(1,'zs');
  434. commit;
  435. --使用触发器监视表中数据修改,不能做降低工资的操作
  436. create or replace trigger can_not_low
  437. before
  438. update
  439. on emp
  440. for each row --行级触发器
  441. declare
  442. begin
  443. --获取到原始记录的工资 --获取修改后的工资
  444. if :old.sal > :new.sal then
  445. --谈错误框提示
  446. raise_application_error(-20002,'不能降低工资');
  447. end if;
  448. end;
  449. --修改员工的工资测试触发器
  450. update emp set sal=sal-1 where empno=7499;
  451. /*
  452. 触发器实际应用
  453. 使用触发器实现 插入数据的id 自增长 面试题
  454. **/
  455. create or replace trigger auto_increment_id
  456. before
  457. insert
  458. on test_trigger
  459. for each row
  460. declare
  461. begin
  462. --补全将要插入记录的id
  463. --补全的id 是自增长的数值 如果没有提前创建序列,需要提前创建序列 --创建序列 create sequence order_sequence
  464. select order_sequence.nextval into :new.pid from dual;
  465. end;
  466. insert into test_trigger(pname,phone) values('zs','1234566');
  467. commit;
  468. package baidu;
  469. import java.sql.CallableStatement;
  470. import java.sql.Connection;
  471. import java.sql.DriverManager;
  472. import java.sql.PreparedStatement;
  473. import java.sql.ResultSet;
  474. import org.junit.Test;
  475. import oracle.jdbc.OracleCallableStatement;
  476. import oracle.jdbc.OracleTypes;
  477. public class TestJdbc {
  478. String driverClass = "oracle.jdbc.driver.OracleDriver";
  479. String url ="jdbc:oracle:thin:@192.168.17.128:1521:orcl";
  480. String user= "baidu_03";
  481. String password = "baidu_03";
  482. /*
  483. *测试jdbc连接数据库
  484. *
  485. * */
  486. @Test
  487. public void querEmp(){
  488. try{
  489. //加载驱动
  490. Class.forName(driverClass);
  491. //获取链接
  492. Connection con = DriverManager.getConnection(url, user,password);
  493. //获取预编译的statement
  494. PreparedStatement pst= con.prepareStatement("select * from emp");
  495. //执行查询
  496. ResultSet rs = pst.executeQuery();
  497. //处理结果
  498. while(rs.next()){
  499. System.out.println(rs.getInt(1)+"员工姓名"+rs.getString("ename"));
  500. }
  501. rs.close();
  502. con.close();
  503. //关闭连接
  504. }catch(Exception e){
  505. e.printStackTrace();
  506. }
  507. }
  508. /*存储过程的调用
  509. * {call <procedure-name>[(<arg1>,<arg2>, ...)]}
  510. add_sal(eno number,addsal number)
  511. * */
  512. @Test
  513. public void callAddSal(){
  514. try{
  515. //加载驱动
  516. Class.forName(driverClass);
  517. //获取链接
  518. Connection con = DriverManager.getConnection(url, user,password);
  519. //获取预编译的statement
  520. CallableStatement pst= con.prepareCall("{call add_sal(?,?)}");
  521. pst.setInt(1, 7499);
  522. pst.setInt(2, 1000);
  523. //执行查询
  524. pst.execute();
  525. con.close();
  526. //关闭连接
  527. }catch(Exception e){
  528. e.printStackTrace();
  529. }
  530. }
  531. /*存储过程的调用
  532. * {call <procedure-name>[(<arg1>,<arg2>, ...)]}
  533. count_yearsal(eno number,total_year_sal out number)
  534. * */
  535. @Test
  536. public void callCountSal(){
  537. try{
  538. //加载驱动
  539. Class.forName(driverClass);
  540. //获取链接
  541. Connection con = DriverManager.getConnection(url, user,password);
  542. //获取预编译的statement
  543. CallableStatement pst= con.prepareCall("{call count_yearsal(?,?)}");
  544. pst.setInt(1, 7499);
  545. //注册输出参数
  546. pst.registerOutParameter(2, OracleTypes.NUMBER);
  547. //执行查询
  548. pst.execute();
  549. int total = pst.getInt(2);
  550. System.out.println(total);
  551. con.close();
  552. //关闭连接
  553. }catch(Exception e){
  554. e.printStackTrace();
  555. }
  556. }
  557. /*
  558. * pro_dept_emp(dno number,dept_emp out sys_refcursor)
  559. * */
  560. @Test
  561. public void callProEmp(){
  562. try{
  563. //加载驱动
  564. Class.forName(driverClass);
  565. //获取链接
  566. Connection con = DriverManager.getConnection(url, user,password);
  567. //获取预编译的statement
  568. CallableStatement pst= con.prepareCall("{call pro_dept_emp(?,?)}");
  569. pst.setInt(1, 10);
  570. //注册输出参数
  571. pst.registerOutParameter(2, OracleTypes.CURSOR);
  572. //执行查询
  573. pst.execute();
  574. OracleCallableStatement ocs = (OracleCallableStatement)pst;
  575. ResultSet rs = ocs.getCursor(2);
  576. while(rs.next()){
  577. System.out.println(rs.getInt(1)+"员工姓名"+rs.getString("ename"));
  578. }
  579. rs.close();
  580. ocs.close();
  581. pst.close();
  582. con.close();
  583. //关闭连接
  584. }catch(Exception e){
  585. e.printStackTrace();
  586. }
  587. }
  588. }
  589. public void show4(){
  590. try {
  591. Class.forName(driverClass);
  592. Connection con = DriverManager.getConnection(url, user,password);
  593. CallableStatement pst= con.prepareCall("{?= call count_sal_noout(?)}");
  594. //给第二个参数赋值
  595. pst.setLong(2, 7499);
  596. // stat2.setLong(2, empno);
  597. //声明第一个参数的类型
  598. pst.registerOutParameter(1, OracleTypes.NUMBER);
  599. pst.execute();
  600. OracleCallableStatement ocs = (OracleCallableStatement)pst;
  601. NUMBER num = ocs.getNUMBER(1);
  602. System.out.println(num);
  603. // long i = pst.getLong(1);
  604. // System.out.println(i);
  605. con.close();
  606. } catch (Exception e) {
  607. e.printStackTrace();
  608. }
  609. }
  610. /*

 

原文链接:http://www.cnblogs.com/haizai/p/11611751.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号