regexp_like正则表达式写法求助

blank7 2014-03-28 11:52:16
使用regexp_like函数判断传入字符串是否符合格式如:1111,22221,.....,33332
1. 逗号为各子串分割符
2. 各子串仅为数字组成,最长不超过20位
3. 字符串不能包含数字及逗号以外的字符
4. 无限定字符串包含多少个子串
...全文
659 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
blank7 2014-04-01
  • 打赏
  • 举报
回复
引用 6 楼 hdg5211314 的回复:
亲,都是我一个人在回复,我把sql丢给你吧,写了我半个小时
--函数只是用于判断是否纯数字以及带符号的
CREATE OR REPLACE FUNCTION ONERE_TO_MANYRE(VALUE1 IN VARCHAR2,--这个是字符串
                                           SYMBOL IN CHAR) RETURN VARCHAR2 IS--这个是你的判断字符,在你的需求里面是分号
    RESULT      VARCHAR2(100);
    STRING_NUM1 NUMBER;
    STRING_NUM2 NUMBER;
    Number_flag CHAR(1);
    reg_exp     NVARCHAR2(100);
BEGIN
    reg_exp := '^[1-9][0-9]*(' || SYMBOL || '[0-9]*)*';
    SELECT COUNT(CASE LENGTH(REGEXP_SUBSTR(a, reg_exp))
                     WHEN LENGTH(A) THEN
                      a
                 END) B
      INTO Number_flag
      FROM (SELECT VALUE1 a FROM dual);
    IF Number_flag = 0 THEN
        RESULT := '存在非数字';
    ELSIF Number_flag = 1 THEN
    
        --这是使用正则表达式判断进行拆分(注:这个有缺陷)
        SELECT COUNT(*)
          INTO STRING_NUM2
          FROM (sELECT DISTINCT regexp_substr(a, '[[:digit:]]+', 1, level) t
                  from (SELECT VALUE1 a FROM DUAL)
                connect by level <=
                           length(regexp_replace(a, '[[:digit:]]+')))
         WHERE length(t) >= 20;
    
        IF STRING_NUM2 >= 1 THEN
            RESULT := '存在超过20个字符的子字符';
        ELSE
            RESULT := '有效字符';
        END IF;
    END IF;
    /* --未使用正则表达式对源字符进行拆分并判断,不建议使用这个
    SELECT COUNT(*)
      INTO STRING_NUM1
      FROM (SELECT SUBSTR(SYMBOL || A.STR || SYMBOL,
                          INSTR(SYMBOL || A.STR || SYMBOL, SYMBOL, 1, ROWNUM) + 1,
                          INSTR(SYMBOL || A.STR || SYMBOL,
                                SYMBOL,
                                1,
                                ROWNUM + 1) -
                          INSTR(SYMBOL || A.STR || SYMBOL, SYMBOL, 1, ROWNUM) - 1) T
              FROM (SELECT VALUE1 STR FROM DUAL) A, ALL_OBJECTS
             WHERE ROWNUM <
                   LENGTH(SYMBOL || A.STR || SYMBOL) -
                   LENGTH(REPLACE(SYMBOL || A.STR || SYMBOL, SYMBOL)))
     WHERE LENGTH(T) >= 20;
    
    IF STRING_NUM1 >= 1 THEN
        RESULT := '存在超过20个字符的子字符';
    END IF;*/
    RETURN(RESULT);
END ONERE_TO_MANYRE;
我后来降低要求了,直接判断数字还有逗号分隔,子串长度就不判断了
流浪川 2014-03-31
  • 打赏
  • 举报
回复
引用 4 楼 blank7 的回复:
[quote=引用 1 楼 hdg5211314 的回复:] 为了你这个问题,我还真是想了很久,首先分享一个观点吧: oracle对正则支持很浅,建议不使用在oracle中使用正则表达式,因为容易造成low performance。由于你的条件比较多,我的sql也比较复杂,肯定我的有值得优化的地方,嘿嘿,新手路过。
 WITH TS AS
 (SELECT '1111,222,3312' A FROM DUAL UNION ALL
 SELECT '1,2,3,4,5,6' FROM  DUAL UNION ALL
 SELECT '66,77' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  )

 SELECT DISTINCT a,regexp_substr(a,'[[:alnum:]]+',1,level) t,LEVEL e
 from ts
    connect by level<=length(regexp_replace(a,'[[:alnum:]]+'))+1
我最初的想法是直接用regexp_like来判断格式,不知道可不可行,如果一句正则表达式就能把格式覆盖的话效率就不会低,如果不行的话我是打算直接用自定义函数做[/quote] 直接用实现不了,因为你每一段还有判断规则。。先按1楼的方法分割以后,再判断分割的时候存在不满足或者超过20的。。取count值即可,如果count为0即满足否者不满足。
blank7 2014-03-31
  • 打赏
  • 举报
回复
引用 1 楼 hdg5211314 的回复:
为了你这个问题,我还真是想了很久,首先分享一个观点吧: oracle对正则支持很浅,建议不使用在oracle中使用正则表达式,因为容易造成low performance。由于你的条件比较多,我的sql也比较复杂,肯定我的有值得优化的地方,嘿嘿,新手路过。
 WITH TS AS
 (SELECT '1111,222,3312' A FROM DUAL UNION ALL
 SELECT '1,2,3,4,5,6' FROM  DUAL UNION ALL
 SELECT '66,77' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  )

 SELECT DISTINCT a,regexp_substr(a,'[[:alnum:]]+',1,level) t,LEVEL e
 from ts
    connect by level<=length(regexp_replace(a,'[[:alnum:]]+'))+1
我最初的想法是直接用regexp_like来判断格式,不知道可不可行,如果一句正则表达式就能把格式覆盖的话效率就不会低,如果不行的话我是打算直接用自定义函数做
hdg5211314 2014-03-31
  • 打赏
  • 举报
回复
自己用oracle的正则替换一下就行了,然后外层加一个select判断是否大于20
hdg5211314 2014-03-31
  • 打赏
  • 举报
回复
还是不建议这样做,太耗性能了,尽量在程序实现; 实在不行,写oracle的function吧,这个真的不行,虽然实现目的,但是其性能,哎。
hdg5211314 2014-03-31
  • 打赏
  • 举报
回复
为了你这个问题,我还真是想了很久,首先分享一个观点吧: oracle对正则支持很浅,建议不使用在oracle中使用正则表达式,因为容易造成low performance。由于你的条件比较多,我的sql也比较复杂,肯定我的有值得优化的地方,嘿嘿,新手路过。
 WITH TS AS
 (SELECT '1111,222,3312' A FROM DUAL UNION ALL
 SELECT '1,2,3,4,5,6' FROM  DUAL UNION ALL
 SELECT '66,77' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  UNION ALL
 SELECT '65,98,53' FROM  DUAL  )

 SELECT DISTINCT a,regexp_substr(a,'[[:alnum:]]+',1,level) t,LEVEL e
 from ts
    connect by level<=length(regexp_replace(a,'[[:alnum:]]+'))+1
hdg5211314 2014-03-31
  • 打赏
  • 举报
回复
哦,在注释中忘了说了,函数对你的需求没有任何问题,只是拓展性很差。 是使用正则表达式判断进行拆分这里说了一句,有缺陷,但由于使用了if条件判断,所以没有任何问题,大可拿去测试。
hdg5211314 2014-03-31
  • 打赏
  • 举报
回复
亲,都是我一个人在回复,我把sql丢给你吧,写了我半个小时
--函数只是用于判断是否纯数字以及带符号的
CREATE OR REPLACE FUNCTION ONERE_TO_MANYRE(VALUE1 IN VARCHAR2,--这个是字符串
                                           SYMBOL IN CHAR) RETURN VARCHAR2 IS--这个是你的判断字符,在你的需求里面是分号
    RESULT      VARCHAR2(100);
    STRING_NUM1 NUMBER;
    STRING_NUM2 NUMBER;
    Number_flag CHAR(1);
    reg_exp     NVARCHAR2(100);
BEGIN
    reg_exp := '^[1-9][0-9]*(' || SYMBOL || '[0-9]*)*';
    SELECT COUNT(CASE LENGTH(REGEXP_SUBSTR(a, reg_exp))
                     WHEN LENGTH(A) THEN
                      a
                 END) B
      INTO Number_flag
      FROM (SELECT VALUE1 a FROM dual);
    IF Number_flag = 0 THEN
        RESULT := '存在非数字';
    ELSIF Number_flag = 1 THEN
    
        --这是使用正则表达式判断进行拆分(注:这个有缺陷)
        SELECT COUNT(*)
          INTO STRING_NUM2
          FROM (sELECT DISTINCT regexp_substr(a, '[[:digit:]]+', 1, level) t
                  from (SELECT VALUE1 a FROM DUAL)
                connect by level <=
                           length(regexp_replace(a, '[[:digit:]]+')))
         WHERE length(t) >= 20;
    
        IF STRING_NUM2 >= 1 THEN
            RESULT := '存在超过20个字符的子字符';
        ELSE
            RESULT := '有效字符';
        END IF;
    END IF;
    /* --未使用正则表达式对源字符进行拆分并判断,不建议使用这个
    SELECT COUNT(*)
      INTO STRING_NUM1
      FROM (SELECT SUBSTR(SYMBOL || A.STR || SYMBOL,
                          INSTR(SYMBOL || A.STR || SYMBOL, SYMBOL, 1, ROWNUM) + 1,
                          INSTR(SYMBOL || A.STR || SYMBOL,
                                SYMBOL,
                                1,
                                ROWNUM + 1) -
                          INSTR(SYMBOL || A.STR || SYMBOL, SYMBOL, 1, ROWNUM) - 1) T
              FROM (SELECT VALUE1 STR FROM DUAL) A, ALL_OBJECTS
             WHERE ROWNUM <
                   LENGTH(SYMBOL || A.STR || SYMBOL) -
                   LENGTH(REPLACE(SYMBOL || A.STR || SYMBOL, SYMBOL)))
     WHERE LENGTH(T) >= 20;
    
    IF STRING_NUM1 >= 1 THEN
        RESULT := '存在超过20个字符的子字符';
    END IF;*/
    RETURN(RESULT);
END ONERE_TO_MANYRE;
1 SQL基础 1.1 基本概念 结构化查询语言(Structured Query Language)简称SQL,是一种关系数据库查询语言,用于存取数据以及查询、更新和管理关系数据库系统。 1.2 语句结构 1.2.1 数据查询语言(DQL) 对数据库进行的信息查询,select。 1.2.2 数据操作语言(DML) 用于操作关系型数据库对象内部的数据,insert、update、delete。 1.2.3 数据定义语言(DDL) 用来建立及定义数据表、字段以及索引等数据库结构,create、alter、drop 。 1.2.4 数据控制语言(DCL) 用于控制对数据库里数据的访问,通常用于创建与用户访问相关的对象以及控制用户的权限,grant、revoke(撤销)。 1.2.5 事务控制命令(TPL) 用于管理数据库事务,commit、rollback、savepoint(在一组事务里创建标记点以用于回退)。 1.3 表的构成 1.3.1 字段 字段是表里的一列,用于保持每条记录的特定信息 1.3.2 记录 记录,也被成为一行数据,是表里的每一行 1.4 完整性的约束条件 1.4.1 实体完整性 关系模型的实体完整性在create table中用primary key约束实现,primary key约束用于定义主键,它保证主键的唯一性和非空性。 1.4.2 参照完整性 关系模型的参照完整性可以通过在create table中用foreign key (<外键>) references <被参照表名> (<与外键对应的主键名>)进行约束定义。 1.4.3 用户定义完整心 在create table语句中可以根据应用要求,定义属性以及元组上的约束。 常见的用户定义的完整性约束有: not null或null约束。 unique约束:唯一性约束。 default约束:默认值约束。 check约束:检查约束,check约束通过约束条件表达式设置列值应该满足的条件。 1.5 范式 1.5.1 第一范式 1.5.1.1 规范 无重复的列,确保每列保持原子性,即数据库表中的所有字段值都是不可分解的原子值。 1.5.1.2 举例 姓名 年龄 联系电话 地址 省 市 详细地址 1.5.2 第二范式 1.5.2.1 规范 属性完全依赖于主键,确保表中每列都与主键相关。 1.5.2.2 举例 订单表 订单Id 商品Id 总金额 商品名称 001 1 10 苹果 001 2 10 橘子 联合主键订单Id、商品Id => 商品表 商品Id 商品名称 单价 订单表 订单Id 总金额 1.5.3 第三范式 1.5.3.1 规范 属性不依赖于其它非主属性,确保数据表中的每一列数据都和主键直接相关,而不能间接相关,即要求一个数据库表中不包含已在其它表中已包含的非主关键字信息。 1.5.3.2 举例 党员表 党员Id 党员姓名 组织Code 符合3NF 党员表 党员Id 党员姓名 组织名称 不符合3NF 组织表 组织Code 组织名称 1.6 外连接 1.6.1 准备 create table student_A( uuid varchar2(32), name varchar2(100)); create table student_B( uuid varchar2(32), name varchar2(100)); insert into student_A values('1','小黄'); insert into student_A values('2','小黑'); insert into student_A values('3','小红'); insert into student_B values('1','大黄'); insert into student_B values('2','大黑'); insert into student_B values('4','大红'); insert into student_B values('4','大紫'); 1.6.2 左连接(left join) 1.6.2.1 说明 查询指定的左表的所有行,而不仅仅是联接列所匹配的行;如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值。 1.6.2.2 语法 select A.*,B.* from student_A A left join student_B B on A.Uuid = B.Uuid; 1.6.2.3 结果 1.6.2.4 (+)表示 select A.*,B.* from student_A A,student_B B where A.Uuid = B.Uuid(+) 1.6.3 右连接(right join) 1.6.3.1 说明 查询指定的右表的所有行,而不仅仅是联接列所匹配的行;如果右表的某行在左表中没有匹配行,则在相关联的结果集行中左表的所有选择列表列均为空值。 1.6.3.2 语法 select A.*,B.* from student_A A right join student_B B on A.Uuid = B.Uuid; 1.6.3.3 结果 1.6.3.4 (+)表示 select A.*,B.* from student_A A,student_B B where A.Uuid(+) = B.Uuid 1.6.4 全外连接(full outer join) 1.6.4.1 说明 完整外部联接返回左表和右表中的所有行;当某行在另一个表中没有匹配行时,则另一个表的选择列表列包含空值;如果表之间有匹配行,则整个结果集行包含基表的数据值。 1.6.4.2 语法 select A.*, B.* from student_A A full outer join student_B B on A.Uuid = B.Uuid; 1.6.4.3 结果 1.6.4.4 全外连接不支持(+)写法 1.6.5 (+) + 表示补充,即哪个表有加号,这个表就是匹配表。 1.7 运算符 1.7.1 比较 =、>,<,>=,<=,!=,<>, 1.7.2 确定范围 between and 、not between and 1.7.3 确定集合 in、not in 1.7.4 字符匹配 like(“%”匹配任何长度,“_”匹配一个字符) 1.7.5 转义字符 1.7.5.1 常规转义字符 “\”转义字符,“\%”则表示单纯的字符“%” 1.7.5.2 escape escape关键字经常用于使某些特殊字符,如通配符:'%','_'转义为它们原来的字符的意义,被定义的转义字符通常使用'\',但是也可以使用其他的符号。 select * from Student_a where name like '%$%%' escape '$'; 1.7.6 空值 is null、is not null 1.7.7 集合查询 union(并)、intersect(交)、minus(差) 1.7.8 多重条件 and、or、not 1.7.9 对查询结果分组 1.7.10 分组筛选条件 [having <条件表达式>] 1.7.11 字符串拼接 select 'A' || 'B' from dual; // || 拼接 1.8 函数 1.8.1 聚集函数 count、sum、avg、max、min 1.8.2 case when 1.8.2.1 语法 select t.uuid, t.score, case when t.score > 90 then '优秀' when t.score > 60 then '及格' else '不及格' end from exam_user_exam t 1.8.3 decode 1.8.3.1 语法 select decode(x,1,'x is 1', 2 , 'x is 2','others') from dual 1.8.3.2 说明 当x等于1时,则返回‘x is 1’,当x等于2时,则返回‘x is 2’,否则,返回‘others’。 1.8.4 nulls first(nulls last)排序 1.8.4.1 语法 select * from dy_info t order by t.degree nulls first 1.8.4.2 说明 控制null显示行位置 1.8.5 Nvl 1.8.5.1 语法 select nvl(t.sap,'空') from dy_info t; 1.8.5.2 说明 如果sap号为空,则返回‘空’,否则返回sap号。 1.8.6 递归查询 1.8.6.1 语法 select t.* from g_organ t start with t.organcode = '080' connect by prior t.parentcode = t.organcode; //递归查询父节点 select t.* from g_organ t start with t.organcode = '080' connect by t.parentcode = prior t.organcode; //递归查询子节点 1.8.7 union 和 union all 1.8.7.1 语法 select * from dual union all select * from dual 1.8.7.2 说明 union 会对查询数据进行去重并排序,union all只是简单的将两个结果合并。 1.8.8 wm_concat 1.8.8.1 语法 select wm_concat(t.role_name) from g_role t where t.role_name like '%书记%' 1.8.8.2 说明 拼接字符串,结果为:‘党工委副书记,总支副书记,党支部书记,党委书记,党委副书记,党总支书记,党工委书记,党总支副书记,党支部副书记’ 1.8.9 相似度 1.8.9.1 语法 select utl_match.edit_distance_similarity('aaaaa','bbaaaa') from dual; 1.8.10 去格式 1.8.10.1 oracle正则表达式:去除<>格式 select REGEXP_REPLACE(title,'<[^>]*>','') title from exam_question 1.8.11 rank() over (partition by …) 1.8.11.1 语法 select organcode,score,ranknum from ( select t.organcode, t.score, rank() over (partition by t.organcode order by t.score desc) ranknum from exam_user_exam t) where ranknum < 4 1.8.11.2 说明 获取每个组织,考试成绩前三名。 1.9 存储过程 1.9.1 定义 存储过程是一组为了完成特定功能的SQL语句集,经编译后存储在数据库中。用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。 1.9.2 准备 create table t_user ( username varchar2(20), password varchar2(20) ); create table t_user_temp ( username varchar2(20), password varchar2(20) ); insert into t_user(username,password) values('小王','1111'); insert into t_user(username,password) values('小李','1111'); 1.9.3 创建存储过程 create or replace procedure adduser as begin insert into t_user_temp(username,password) select username,password from t_user t where t.username = '小李'; end adduser; 1.9.4 执行 begin adduser; end; 1.9.5 验证 select * from t_user; select * from t_user_temp 2 SQL深入 2.1 常用 2.1.1 表空间 2.1.1.1 创建表空间 create tablespace TS_DJY datafile 'd:/software/oracle/tablespace/ts_djy.dat' size 1024M autoextend on next 100M maxsize 2048M; 2.1.1.2 指定用户表空间 alter user cssdj default tablespace TS_DJY; 2.1.1.3 指定表的表空间 create table t_student( uuid varchar2(32) )tablespace TS_DJY; 2.1.2 自增sequence 2.1.2.1 创建 create sequence seq_student_uuid minvalue 1 maxvalue 999999999999999 start with 1 increment by 1 nocache; 2.1.2.2 使用 select seq_student_uuid.nextval from dual; //获取下一个 select seq_student_uuid.currval from dual; //获取当前 2.1.3 批量插入 2.1.3.1 查询结果批量插入 insert into tablea(cola,colb) select cola,colb from tableb; 2.1.3.2 创建相同的表结构并插入数据(备份表数据) create tab_new as select * from tab_old; 2.1.3.3 创建相同的表结构不插入数据 create tab_new as select * from tab_old where rownum=0; 2.1.4 伪列伪表 2.1.4.1 伪列 伪列不是表的真实列,但是你可以象使用真实列一样使用伪列,常用伪列:rowid行的绝对物理编号,每一行是唯一的。rownum序号,返回查询结果的每行序号。系统时间sysdate,返回系统当前时间。 2.1.4.2 伪表 select * from dual; 2.1.5 系统表 2.1.5.1 user_tables 当前用户表信息 2.1.5.2 user_tab_columns 当前用户表所有列信息,搜索列所在的表: select * from user_tab_columns t where t.column_name like '%ORGANCODE%'; 2.1.5.3 user_tablespaces 当前用户表空间 2.1.5.4 dba_users 数据库所有用户 2.1.5.5 dba_tables 数据库所有表 2.1.5.6 dba_tablespaces 数据库所有表空间 2.1.6 锁表解锁 2.1.6.1 查看锁表信息 select l.OBJECT_ID,s.SID,s.SERIAL#,s.USERNAME, s.MACHINE from V$locked_Object l,V$session s where l.SESSION_ID = s.SID; 2.1.6.2 解锁 alter system kill session 'sid,serial#'; 2.1.7 备份与恢复 2.1.7.1 导出 导出用户: exp cssdj/cssdj@zr owner=(cssdj,cssdj_zsy) file=d:/cssdj.dmp log=d:/cssdj.log 导出用户表: exp cssdj/cssdj@zr tables=(g_dict,g_dict_item) file=d:/cssdj.dmp log=d:/cssdl.log 2.1.7.2 导入 imp cssdj/cssdj@zr fromuser=cssdj_zsy touser=cssdj file=d:/cssdj.cmp log=d:/cssdj.log 2.1.7.3 数据泵 2.1.8 Dblink 2.1.8.1 创建 create database link orcllink connect to cssdj identified by cssdj using '(DESCRIPTION = (ADDRESS_LIST= (ADDRESS=(PROTOCOL = TCP)(HOST = 219.239.110.65)(PORT = 1521))) (CONNECT_DATA=(SID = orcl)))'; 2.1.8.2 删除 drop database link orcllink; 2.1.8.3 使用 select * from dy_info@orcllink; 2.2 Oracle与Mysql差异 2.2.1 Group by 2.2.1.1 Oracle select后面出现的列,如果没有使用集合函数,必须出现在group by 中。 select sno,sname,sum(grade) from student group by sno,sname; //合法写法 select sno,sname,sum(grade) from student group by sno; //非法写法 select sno,min(sname),sum(grade) from student group by sno; //建议用这种写法,效率高些 2.2.1.2 Mysql select sno,sname,sum(grade) from student group by sno,sname; //合法写法 select sno,sname,sum(grade) from student group by sno; //合法写法 2.2.2 分页 2.2.2.1 Oracle 使用rownum来表明分页位置,而且rownum只能小于某值,不能大于某值,故而rownum和where联用才能完成数据范围的控制 2.2.2.2 Mysql mysql的分页可以用limit startNum,pageNum 2.3 了解 2.3.1 事务 2.3.1.1 Rollback start transaction; --开始事务 insert into g_dict values('test','测试','1',''); --执行数据操作语言(DML) select * from g_dict where code = 'test'; --可以查看是否执行正确 rollback; --错误执行rollback操作 commit; --正确执行commit操作 2.3.1.2 Savepoint start transaction; --开始事务 insert into g_dict values('t1','测试','1',''); --执行数据操作语言(DML) savepoint pointA; insert into g_dict values('t2','测试','1',''); --执行数据操作语言(DML) select * from g_dict where code = 'test33'; --可以查看是否执行正确 rollback to savepoint pointA; 2.3.2 利用执行计划评估SQL语句的性能 2.3.2.1 工具 在PL/SQL Developer中写好一段SQL代码后,按F5,PL/SQL Developer会自动打开执行计划窗口,显示该SQL的执行计划。 2.3.2.2 查看总COST,获得资源耗费的总体印象 一般而言,执行计划第一行所对应的COST(即成本耗费)值,反应了运行这段SQL的总体估计成本,单看这个总成本没有实际意义,但可以拿它与相同逻辑不同执行计划的SQL的总体COST进行比较,通常COST低的执行计划要好一些。 2.3.2.3 了解执行计划的执行步骤 按照从左至右,从上至下的方法,了解执行计划的执行步骤; 执行计划按照层次逐步缩进,从左至右看,缩进最多的那一步,最先执行,如果缩进量相同,则按照从上而下的方法判断执行顺序,可粗略认为上面的步骤优先执行。每一个执行步骤都有对应的COST,可从单步COST的高低,以及单步的估计结果集(对应ROWS/基数),来分析表的访问方式,连接顺序以及连接方式是否合理。 2.3.2.4 分析表的访问方式 表的访问方式主要是两种:全表扫描(TABLE ACCESS FULL)和索引扫描(INDEX SCAN),如果表上存在选择性很好的索引,却走了全表扫描,而且是大表的全表扫描,就说明表的访问方式可能存在问题;若大表上没有合适的索引而走了全表扫描,就需要分析能否建立索引,或者是否能选择更合适的表连接方式和连接顺序以提高效率。 2.3.2.5 分析表的连接方式和连接顺序 表的连接顺序:就是以哪张表作为驱动表来连接其他表的先后访问顺序。 表的连接方式:简单来讲,就是两个表获得满足条件的数据时的连接过程。主要有三种表连接方式,嵌套循环(NESTED LOOPS)、哈希连接(HASH JOIN)和排序-合并连接(SORT MERGE JOIN)。我们常见得是嵌套循环和哈希连接。 嵌套循环:最适用也是最简单的连接方式。类似于用两层循环处理两个游标,外层游标称作驱动表,Oracle检索驱动表的数据,一条一条的代入内层游标,查找满足WHERE条件的所有数据,因此内层游标表中可用索引的选择性越好,嵌套循环连接的性能就越高。 哈希连接:先将驱动表的数据按照条件字段以散列的方式放入内存,然后在内存中匹配满足条件的行。哈希连接需要有合适的内存,而且必须在CBO优化模式下,连接两表的WHERE条件有等号的情况下才可以使用。哈希连接在表的数据量较大,表中没有合适的索引可用时比嵌套循环的效率要高。 2.3.3 优化器 Oracle优化器分为基于规则的优化器(RBO)和基于代价的优化器(CBO)。 2.3.3.1 规则的优化器(RBO) RBO的优化方式,依赖于一套严格的语法规则,只要按照规则写出的语句,不管数据表和索引的内容是否发生变化,不会影响PL/SQL语句的"执行计划"。 2.3.3.2 基于代价的优化器(CBO) CBO计算各种可能"执行计划"的"代价",即cost,从中选用cost最低的方案,作为实际运行方案。各"执行计划"的cost的计算根据,依赖于数据表中数据的统计分布,ORACLE数据库本身对该统计分布是不清楚的,须要分析表和相关的索引,才能搜集到CBO所需的数据。 2.3.4 表分析analysis 2.3.4.1 说明 analyze table,一般可以指定分析表、所有字段、所有索引字段、所有索引,若不指定则全部都分析。 2.3.4.2 表分析 analyze table dy_info compute statistics; 2.3.4.3 删除分析数据 analyze table dy_info delete statistics; 2.3.5 oracle添加强制索引 如果使用的是CBO的话,可能SQL不执行索引,则可以添加强制索引执行索引。 2.3.5.1 语法 /*+index(tablename indexname)*/ 2.3.5.2 举例 select /*+index(t INDEX_SAP)*/* from dy_info t where t.sap = 'T6000890'
-- 首先,以超级管理员的身份登录oracle sqlplus sys/bjsxt as sysdba --然后,解除对scott用户的锁 alter user scott account unlock; --那么这个用户名就能使用了。 --(默认全局数据库名orcl) 1、select ename, sal * 12 from emp; --计算年薪 2、select 2*3 from dual; --计算一个比较纯的数据用dual表 3、select sysdate from dual; --查看当前的系统时间 4、select ename, sal*12 anuual_sal from emp; --给搜索字段更改名称(双引号 keepFormat 别名有特殊字符,要加双引号)。 5、--任何含有空值的数学表达式,最后的计算结果都是空值。 6、select ename||sal from emp; --(将sal的查询结果转化为字符串,与ename连接到一起,相当于Java中的字符串连接) 7、select ename||'afasjkj' from emp; --字符串的连接 8、select distinct deptno from emp; --消除deptno字段重复的值 9、select distinct deptno , job from emp; --将与这两个字段都重复的值去掉 10、select * from emp where deptno=10; --(条件过滤查询) 11、select * from emp where empno > 10; --大于 过滤判断 12、select * from emp where empno 10 --不等于 过滤判断 13、select * from emp where ename > 'cba'; --字符串比较,实际上比较的是每个字符的AscII值,与在Java中字符串的比较是一样的 14、select ename, sal from emp where sal between 800 and 1500; --(between and过滤,包含800 1500) 15、select ename, sal, comm from emp where comm is null; --(选择comm字段为null的数据) 16、select ename, sal, comm from emp where comm is not null; --(选择comm字段不为null的数据) 17、select ename, sal, comm from emp where sal in (800, 1500,2000); --(in 表范围) 18、select ename, sal, hiredate from emp where hiredate > '02-2月-1981'; --(只能按照规定的格式写) 19、select ename, sal from emp where deptno =10 or sal >1000; 20、select ename, sal from emp where deptno =10 and sal >1000; 21、select ename, sal, comm from emp where sal not in (800, 1500,2000); --(可以对in指定的条件进行取反) 22、select ename from emp where ename like '%ALL%'; --(模糊查询) 23、select ename from emp where ename like '_A%'; --(取第二个字母是A的所有字段) 24、select ename from emp where ename like '%/%%'; --(用转义字符/查询字段中本身就带%字段的) 25、select ename from emp where ename like '%$%%' escape '$'; --(用转义字符/查询字段中本身就带%字段的) 26、select * from dept order by deptno desc; (使用order by desc字段 对数据进行降序排列 默认为升序asc); 27、sel

17,086

社区成员

发帖
与我相关
我的任务
社区描述
Oracle开发相关技术讨论
社区管理员
  • 开发
  • Lucifer三思而后行
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧