Oracle PL/SQL

来源:互联网 发布:mac 待机一晚上耗电量 编辑:程序博客网 时间:2024/06/05 18:59

SQL

Oracle数据库中大小写敏感

 

要求找出含有%的记录

这需要使用ESCAPE标识转义字符

select * from t_charwhere a like ‘%\%%' escape '\';

select * fromt_char where a like ‘%K%%' escape ‘K';

 

PLSQL中日期比较 

1.格式需要一致,可以通过字符串比较。

2.TO_CHAR(CREATE_DATE,'yyyy-mm-dd')>=NVL(P_CREATE_FROMDATE,TO_CHAR(CREATE_DATE,'yyyy-mm-dd'))

2.  START_DATE <= TO_date(p_trans_date,'YYYY-MM-DD')

 

--不易发现的错误

select * from test1where column1 ='1234';--将所有行转换为字符串

select * from test1where column1 =1234;--将所有行转换为数字,包含字符的行出错

--连接

-oracle全外外连接

select e.last_name,e.department_id,d.department_namefrom employees e,departments dwhere e.department_id=d.department_id(+)union

select e.last_name,e.department_id,d.department_namefrom employees e,departments dwhere e.department_id(+)=d.department_id;

 

--sql1999标准

SELECT e.last_name, e.department_id, d.department_name

FROM employees e

FULLOUTERJOIN departments d

ON (e.department_id =d.department_id) ;

 

分组计算函数和group by子句

备注:MIN, MAX 可用于任何数据类型,但AVG SUMSTDDEV,VARIANCE仅适用于数值型字段。

 

使用GROUP BY 子句进行分组:

 

l 可以按照某一个字段分组,也可以按照多个字段的组合进行分组

l SELECT查询语句中同时选择分组计算函数表达式和其他独立字段时,其他字段必须出现在Group By子句中,否则不合法。

l 不能在Where条件中使用分组计算函数表达式,当出现这样的需求的时候,使用Having 子句。

l 分组计算函数也可嵌套使用。

 

事务控制

隐式的事务提交或回滚动作:

Commit,rollback 是显式的提交和回滚语句,还有一些隐式的提交和回滚是大家需要知道并引起注意的:

当如下事件发生是,会隐式的执行Commit动作:

1、数据定义语句被执行的时候,比如新建一张表:Create Table …

2、数据控制语句被执行的时候,比如赋权GRANT …( 或者DENY)

3、正常退出iSQL*Plus 或者PLSQLDEVELOPER, 而没有显式的执行COMMIT 或者ROLLBACK 语句。

当如下事件发生时,会隐式执行Rollback 动作:

1、非正常退出iSQL*Plus, PLSQL DEVELOPER, 或者发生系统错误。

 

在Commit 或者Rollback前后数据的状态:

1、在数据已经被更改,但没有Commit前,被更改记录处于被锁定状态,其他用户无法进行更改;

2、在数据已经被更改,但没有Commit前,只有当前Session的用户可以看到这种变更,其他Session的用户

看不到数据的变化。

3、在数据已经被更改,并且被Commit后,被更改记录自动解锁,其他用户可以进行更改;

4、在数据已经被更改,并且被Commit后,其他Session的用户再次访问这些数据时,看到的是变化后的数据。

那么同理可知Rollback前后数据的状态及锁的变化。

 

 

表的命名要求和表中列的命名要求:

1、必须以字母开头

2、长度不能超过30个字符

3、只能包含A–Z,a–z, 0–9,_, $, and #

4、不能与数据库中的已有对象重名

5、不能使用Oracle 数据库的保留字

 

注意TRUNCATE 与DELETE FROM table 的区别: 1)没有Rollback机会2)HWM标记复位(HWM高水位线)都不会删除表结构

 

约束

 

更改表的语法:

添加列:

ALTERTABLE table

ADD(column datatype [DEFAULT expr]

[, columndatatype]...);

更改列:

ALTERTABLE table

MODIFY(column datatype [DEFAULT expr]

[, columndatatype]...);

删除列:

ALTERTABLE table

DROP(column);

 

ALTER TABLE tablenameADD CONSTRAINT constraintname

constrainttype(column1,…);

 

CONSTRAINT emp_email_ukUNIQUE(email))

 

CONSTRAINT dept_id_pk PRIMARYKEY(department_id))

 

CONSTRAINT emp_dept_fk FOREIGN KEY (department_id)

 

REFERENCESdepartments(department_id) 

 

CONSTRAINT emp_salary_min CHECK (salary > 0)

 

索引、序列、同义词

函数索引

CREATE INDEX upper_dept_name_idx

ON departments(UPPER(department_name));

 

控制用户权限

GRANT object_priv [(columns)]

ON object

TO {user|role|PUBLIC}

[WITHGRANT OPTION];

如果你想让其他用户也有权把你赋给他的权限进一步赋予给别人,那么需要带WITH GRANT OPTION;

 

GRANT select, insert

ON departments

TO scott

WITH GRANT OPTION;

撤销权限

REVOKE {privilege [, privilege...]|ALL}

ON object

FROM{user[, user...]|role|PUBLIC}

 

创建DB-LINK,通过DB-LINK访问另一数据库中的表

CREATE PUBLIC DATABASE LINK hq.acme.com

USING'sales';

 

SELECT*

FROMemp@HQ.ACME.COM;

 

递归查询

SELECTlast_name||' reports to '||

PRIORlast_name "Walk Top Down"

FROMemployees

STARTWITH last_name = 'King'

CONNECTBY PRIOR employee_id = manager_id ;

 

使用LEVEL关键字和LPAD函数,在OUTPUT中显示树形层次。

SELECT LPAD(last_name,LENGTH(last_name)+(LEVEL*2)-2,'_')

AS org_chart

FROM employees

START WITH last_name='King'

CONNECT BYPRIOR employee_id=manager_id

 

Group By 子句的增强

在Group By 中使用Rollup 产生常规分组汇总行以及分组小计

 

在Group By 中使用Cube 产生Rollup结果集+ 多维度的交叉表数据源

 

GROUPING函数:Rollup 和Cube有点抽象,他分别相当于n+1 和2的n次方常规Group by 运

算;那么在Rollup 和Cube的结果集中如何很明确的看出哪些行是针对那些列或者列的组合进行

分组运算的结果的? 答案是可以使用Grouping 函数; 没有被Grouping到返回1,否则返回0

 

使用Grouping Set 来代替多次UNION

 

Exercise

 

--14.  Showall employees who have managers with a salary higher than $15,000.

--Show the following data: employeename, manager name, manager salary, and salary grade of the manager.

createtable job_grades(grade_levelvarchar(20),lowest_salnumber,highest_salnumber);

 

insertinto job_gradesvalues('E',10000,1000000);

insertinto job_gradesvalues('E',9000,900000);

 

SELECT e.last_name, m.last_name manager,m.salary, j.grade_level

 FROM employees e,employees m, job_grades j

 WHERE e.manager_id = m.employee_id

  AND m.salaryBETWEEN j.lowest_salAND j.highest_sal

   AND m.salary >15000;

--15.  Showthe department number, name, number of employees, and average salary of alldepartments,

--together with the names, salaries,and jobs of the employees working in each department.

SELECT d.department_id,

      d.department_name,

      count(e1.employee_id)employees,

      NVL(TO_CHAR(AVG(e1.salary),'99999.99'),'No average') avg_sal,

      e2.last_name,

      e2.salary,

      e2.job_id

 FROM departments d,employees e1, employees e2

 WHERE d.department_id = e1.department_id(+)

  AND d.department_id =e2.department_id(+)

 GROUPBY d.department_id,

          d.department_name,

          e2.last_name,

          e2.salary,

          e2.job_id

 ORDERBY d.department_id, employees;

 

--19.  Showthe employee number, last name, salary, department number, and the averagesalary in their department for all employees.

select e.employee_id, e.last_name,e.department_id,avg(d.salary)

 from employees d,employees e

 where d.department_id = e.department_id

 groupby e.employee_id, e.last_name, e.department_id;

 

--31. Write a query to delete the oldestJOB_HISTORY row of  an employee bylooking up the

--JOB_HISTORY table for theMIN(START_DATE) for the employee.

--Delete the records of only those employees who have changed at leasttwo jobs.

--If your query executes correctly,    you will get the feedback:

DELETEFROM job_history JH

 WHERE employee_id = (SELECT employee_id

                        FROM employees E

                       WHERE JH.employee_id = E.employee_id

                         AND START_DATE =

                             (SELECTMIN(start_date)

                                FROM job_history JH

                               WHERE JH.employee_id =E.employee_id)

                         AND3 > (SELECTCOUNT(*)

                                    FROM job_history JH

                                   WHERE JH.employee_id =E.employee_id

                                   GROUPBY EMPLOYEE_ID

                                  HAVINGCOUNT(*) >=2));

 

--41. Write a SQL script file to dropall objects (tables, views, indexes, sequences, synonyms, and so on) that youown.

SET HEADINGOFF ECHOOFF FEEDBACKOFF

SET PAGESIZE0

 

SELECT'DROP' || object_type ||' ' || object_name ||';'

FROM user_objects

ORDERBY object_type

 

SET HEADINGON ECHOON FEEDBACKON

SET PAGESIZE24


PLSQL

1.       Oracle 同义词

相当于alias(别名),比如把user1.table1在user2中建一个同义词table1

create synonym table1 for user1.table1;

这样当你在user2中查select * from table1时就相当于查select * from user1.table1;

优点自己总结吧。

 

2.       Oracle 受权 ORA-00990: 权限缺失或无效

创建一个用户:

create user xxx identified by yyy

 当密码里面有特殊字符时  windows平台下面应该用 "yyy"  其它平台未测试

刚创建好的用户是没有任何权限的  连登录数据库的权限都没有

这时,就要给用户授予权限:

ORACLE里面的权限有系统权限和对象权限两种

可以通过

select distinct p.privilege

 from user_sys_privs p

 order by p.privilege asc;

 

 来查询ORACLE里面的所有系统权限;

常用的系统权限有 :

           CREATE SESSION                     创建会话 登录数据库

       CREATE SEQUENCE                     创建序列

       CREATE SYNONYM                      创建同名对象

       CREATE TABLE                        在用户模式中创建表

       CREATE ANY TABLE                    在任何模式中创建表

       DROP ANY TABLE                      在任何模式中删除表

       CREATE PROCEDURE                    创建存储过程

       EXECUTE ANY PROCEDURE               执行任何模式的存储过程

       CREATE USER                         创建用户

       DROP USER                           删除用户

       CREATE VIEW                         创建视图

通过下面的SQL可以查询所有的对象权限:

select distinct t.privilege fromuser_tab_privs t;

 结果如下:

              FLASHBACK
             EXECUTE
             ONCOMMIT REFRESH
             ALTER
             DEQUEUE
             UPDATE
             DELETE
             DEBUG
             UNDER
             QUERY REWRITE
             SELECT
             READ
             INSERT
              INDEX
              WRITE
              REFERENCES
              MERGE VIEW

另外还有角色授权  可以通过下面的SQL来查询ORALCE里面内置有哪些角色:

select distinct r.granted_role role_name

 from user_role_privs r

 where r.default_role = 'YES'

 order by role_name asc;

 授权语句:grant 权限

系统授权直接写:grant 权限名称  to  用户名;

对象权限则要写成:grant 权限名称  on schema. 对象名 to 用户名

 还要注意一点是:授予权的时候系统权限和对象权限不能同时写,也就是说不能写成下面这个样子:

GRANT CREATE TABLE, SELECT ON scott.testTO scott1

 这样写会报  ORA-00990:权限缺失或无效

但是系统权限和角色是可以同时写在一起授予给某一个用户的

 

3.       oracle之报错:ORA-00054: 资源正忙,要求指定NOWAIT

解决方案:

select session_id from v$locked_object; --首先得到被锁对象的session_id

SELECT sid, serial#, username, osuser FROM v$sessionwhere sid = session_id; --通过上面得到的session_id去取得v$sessionsidserial#,然后对该进程进行终止。

ALTER SYSTEM KILL SESSION 'sid,serial';

example:

ALTER SYSTEM KILL SESSION '13, 8';

 

--ora0054

--查找锁定的会话

 select session_idfromv$locked_object;

 

 SELECTsid, serial#,username, osuser

   FROM v$session

  wheresidin (4908,4913,4955);

--杀死会话

  ALTERSYSTEMKILLSESSION'4908,2223';

  ALTERSYSTEMKILLSESSION'4913,937';

  ALTERSYSTEMKILLSESSION'4955,3079';

--查找锁 

select *from v$lockwhereblock=1;

select *from v$locked_object;

 

--查看当前用户的一些权限

selectdistinct p.privilegefromuser_sys_privs p;

 

4.  ORACLE-关于ORA-04021得解决办法(timeout occurred while waiting to lock object 

某个应用正在锁定该表或者包

表为

select b.SID,b.SERIAL#, c.SQL_TEXT

  from v$locked_object a, v$session b,v$sqlarea c

 where a.SESSION_ID = b.SID

   and b.SQL_ADDRESS = c.ADDRESS

   and c.sql_textlike'%table_name%'

包为

select B.SID,b.USERNAME, b.MACHINE, B.SERIAL#

  FROM V$ACCESS A, V$SESSION B

 WHERE A.SID = B.SID

   and a.OBJECT ='%PACKAGE_name%'

   and a.TYPE ='PACKAGE'

找出这个session

然后 kill

alter system kill session 'sid,serial#'

 

5.       层次查询实例也可以利用两个嵌套的游标实现

PLSQL\PACKAGE_GET_AUDIT_DESC.pck

selectdistinct x.form_kind, x.form_no, auditm

  from (selectt.FORM_KIND,

              t.FORM_NO,

               substr(sys_connect_by_path(t.AUDITM,','),2) auditm,

               level lv,

               max(level)over(partitionbyt.FORM_KIND, t.FORM_NO) max_level

          fromdw_tes_flow_audit_fs_v t

         where1 =1

              /*and t.FORM_KIND= 'SYS.FORM.009'

              andt.FORM_NO = '277721'*/

           andconnect_by_isleaf =1

        connectbyprior t.FORM_KIND= t.FORM_KIND

               andprior t.FORM_NO =t.FORM_NO

               andprior t.AUDITM< t.AUDITM) x

 where lv =max_level;

 

6.       UNION和UNION ALL

Union,对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序;

UnionAll,对两个结果集进行并集操作,包括重复行,不进行排序;

 

7.       dbms_mview.refresh()函数

dbms_mview.refresh('表名', 'F')   --快速刷新,也就是增量刷新
dbms_mview.refresh('
表名', 'C')   --完全刷新

详见http://www.linuxidc.com/Linux/2011-12/48463.htm

 

8.       动态游标运用

DECLARE

  -- Localvariables here

  a        VARCHAR2(20);

  l_cursor NUMBER;

  l_state  NUMBER;

  l_sql    VARCHAR2(2000);

  l_name   VARCHAR2(100);

BEGIN

  -- Teststatements here

  a := '''' ||'A' ||'''' ||',' ||'''' ||'B' ||'''';

 dbms_output.put_line('a: ' || a);

  l_sql := 'select namefrom cux_test t where t.name in (' || a ||')';

 dbms_output.put_line('sql: ' || l_sql);

  l_cursor :=dbms_sql.open_cursor;

  dbms_sql.parse(l_cursor,l_sql, dbms_sql.native);

 dbms_sql.define_column(l_cursor,1, l_name,100);

  l_state :=dbms_sql.EXECUTE(l_cursor);

 

  LOOP

    EXITWHENdbms_sql.fetch_rows(l_cursor) <= 0;

   dbms_sql.column_value(l_cursor,1, l_name);

    dbms_output.put_line('result: ' || l_name);

  ENDLOOP;

END;

 

9.       如果在本机可以正常使用,可是到局域网中的其他机器就出现“ORA-12170:TNS:连接超时

解决方法:1.cmd-----ping ip地址查看网络问题,看能否ping2.cmd-----tnsping   ip地址(或者是服务器的实例名SID)如果报“TNS-12535:操作超时,可能是服务器端防火墙    没有关闭3.cmd----netstat -na 查看1521端口是否关闭,如果关闭Windows XP中的防火墙设置中将1521端口设为例外4.cmd----lsnrctl status   lsnrctllistener-control 监听器的缩写,查看监听的状态
 

10.   窗口切换诸多不便,上网搜了一下需要这么整:

tools -> window list(笔者注:变成打勾状态)

在tools->preferences->user interface->options 里面钩上 Autosavedesktop

不然每次重开pl/sql developer时都要调整位置

 

11.   Plsql执行计划

Plsq F5键详见http://www.fengfly.com/plus/view-210418-1.html

http://alexgao.iteye.com/blog/1562962

 

12.   SQL的内连接与外连接

http://blog.163.com/cs_mayong/blog/static/9581317120096595410120/

http://blog.csdn.net/yiluoak_47/article/details/7449590

1)左连接:Left Join或Left Outer Join

      左连接的结果集包括LEFT OUTER子句中指定的左表的所有行,而不仅仅是联接列所匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值(Null)。

2) 右连接:Right Join或Right Outer Join

右连接和左连接相反,它将返回右表的所有行。如果右表的某行在左表中没有匹配行,则将为左表返回空值(Null)

3) 完整外部联接:Full Join或 Full Outer Join

  完整外部联接返回左表和右表中的所有行。当某行在另一个表中没有匹配行时,则另一个表的选择列表列包含空值。如果表之间有匹配行,则整个结果集行包含基表的数据值。

另一种方式"(+)"所在位置的另一侧为连接的方向

总之,

左连接显示左边全部的和右边与左边相同的

右连接显示右边全部的和左边与右边相同的

 

13.   Oracle的方案(Schema)和用户(User)的区别

oracle中的schema就是指一个用户下所有对象的集合,schema本身不能理解成一个对象,oracle并没有提供创建schema的语法,schema也并不是在创建user时就创建,而是在该用户下创建第一个对象之后schema也随之产生,只要user下存在对象,schema就一定存在,user下如果不存在对象,schema也不存在;这一点类似于temp tablespace group,另外也可以通过oem来观察,如果创建一个新用户,该用户下如果没有对象则schema不存在,如果创建一个对象则和用户同名的schema也随之产生。

http://blog.csdn.net/kimsoft/article/details/4627520

http://blog.sina.com.cn/s/blog_6c845fae0100peof.html


5 0
原创粉丝点击