Oracle之语法类应用汇总

一、regexp在Oracle中的应用

1. 概述

分类:与下列相似,但功能更加强大(‘支持正则表达式’)
(1) regexp_substr : 同 substr 功能相似(‘截取’ 字符串)
(2) regexp_replace: 同 replace 功能相似( ‘替换’ 字符串)
(3) regexp_like : 同 like 功能相似(模糊 ‘匹配’)
(4) regexp_instr : 同 instr 功能相似(返回字符所在 ‘下标’)
– 上述 四个 函数,正则用法相似,知晓一个,其它皆可参考

2 正则匹配规则

分组元字符描述
表达式的替换和分组
|
替换,通常和分组操作符 () 一起使用
()
分组,并且 的关系;标记一个子表达式的开始和结束位置
[char]
字符列表,或者 的关系;标记一个中括号表达式
特殊的
\
转义字符。“\n”:换行,"\\n":文本 ‘\n’
.
匹配除转义字符外的任何单字符
定位元字符
^
使表达式定位至一行的开头
$
使表达式定位至一行的末尾
量词或重复操作符
*
匹配 0 次或多次(任意次数)
?
匹配 0 次或 1 次(最多 1 次)
+
匹配 1 次或多次(至少 1 次)
{m}
正好 匹配 m 次。eg:'^1[0-9]{10}'-手机号码
{m, }
至少 匹配 m 次
{m, n}
匹配 m 到 n 次。eg:'^0[0-9]{2,3}-[0-9]{6,7}'-固定电话(0755-888999)
分组元字符描述
预定义的 posix 字符类
[:alpah:]
任何字母
[:lower:]
任何小写字母
[:upper:]
任何大写字母
[:digit:]
任何数字,相当于 [0-9]
[:xdigit:]
任何 16 进制的数字,相当于 [0-9a-fA-F]
[:alnum:]
任何字符或数字字符
[:space:]
空白字符,如:回车符,换行符、竖直制表符和换页符
[:punct:]
任何标点符号

3 正则函数

oracle学习文档

3.1 REGEXP_SUBSTR(String, pattern, [position],[occurrence],[modifier],[subexpression])

3.1.1 参数解释

String: 需要进行正则处理的字符串。
pattern:正则表达式。
position:起始位置(从字符串的第几个开始正则,默认为1,注:数据库中的字符串起始位置为1)。
occurrence:获取第几组通过正则表达式分割出来的组。
modifier:模式(‘i’不区分大小写,‘c’区分大小写。其中默认没‘c’)。
subexpression: 含有子表达式 0-9, 默认 0:不含子表达式,1:第一个子表达式,以此类推

3.1.2 实际用例
eg1:参数subexpression 测试使用
select  regexp_substr('abc,CBA121ABC,cba', ',[^,]+,') rs1                 -- ,CBA121ABC,
       ,regexp_substr('1234567890', '(123)(4(56)(78))', 1, 1, 'i', 0) rs2 -- 12345678  不含子表达式
       ,regexp_substr('1234567890', '(123)(4(56)(78))', 1, 1, 'i', 1) rs3 -- 123       第一个子表达式
       ,regexp_substr('1234567890', '(123)(4(56)(78))', 1, 1, 'i', 2) rs4 -- 45678     第二个子表达式
       ,regexp_substr('1234567890', '(123)(4(56)(78))', 1, 1, 'i', 3) rs5 -- 56        依次类推
       ,regexp_substr('1234567890', '(123)(4(56)(78))', 1, 1, 'i', 4) rs6 -- 78
       ,regexp_substr('1234567890', '(123)(4(56)(78))', 1, 1, 'i', 5) rs7 --     
  from dual;
eg2:按照不同的正则使用
with temp_email as (
  select 1 user_no, 'a1@qq.com' email from dual union all
  select 2 user_no, 'bb2@sina.com' email from dual union all
  select 3 user_no, 'ccc3@aliyun.com' email from dual
)
select t.user_no 用户编号
       ,regexp_substr(t.email,'[[:alnum:]]+') 用户名
       ,regexp_substr(t.email, '\@[[:alnum:]]+\.[[:alnum:]]+') 邮箱后缀
       -- 两者等同
       ,regexp_substr(t.email,'[a-zA-Z0-9]+') 用户名2
       ,regexp_substr(t.email, '\@[a-zA-Z0-9]+\.[a-zA-Z0-9]+') 邮箱后缀2
  from temp_email t;

–执行结果

   	用户编号	用户名	邮箱后缀	用户名2	邮箱后缀2
1	1	        a1	    @qq.com	    a1	    @qq.com
2	2	        bb2	    @sina.com	bb2	    @sina.com
3	3	        ccc3	@aliyun.com	ccc3	@aliyun.com

eg3:配合CONNECT BY使用----小数据量
SELECT REGEXP_SUBSTR('四,五,六,七', '[^,]+', 1, LEVEL, 'i') AS STR
  FROM DUAL
CONNECT BY LEVEL <= LENGTH('四,五,六,七') - LENGTH(REPLACE('四,五,六,七', ',', '')) + 1
--connect by level <= REGEXP_COUNT('四,五,六,七','[^,]+')

eg4:配合CONNECT BY使用----大数据量优化版

如果数据量小的话,这样来操作是没问题的,一旦数据量上来了,并且再加上多表联查,查询的速度就会非常慢(非常非常慢!),所以就有了下面的内容,优化.

WITH NEWS_TYPE AS
 (SELECT '1' AS Id, 'A,B,C,D' AS Attach_Id
    FROM DUAL
  UNION ALL
  SELECT '2', 'E,F,G,D'
    FROM DUAL
  UNION ALL
  SELECT '3', 'H,R,K,T'
    FROM DUAL)
SELECT ID, REGEXP_SUBSTR(ATTACH_ID, '[^,]+', 1, l) AS FILE_ONE
  FROM NEWS_TYPE,
       (SELECT LEVEL l
          FROM DUAL
        CONNECT BY LEVEL  <= 100 --此处的100,可以通过取 REGEXP_COUNT(NEWS_TYPE.ATTACH_ID,'[^,]+')的最大值来代替
        ) b
 WHERE l <= REGEXP_COUNT(NEWS_TYPE.ATTACH_ID, '[^,]+')
   AND regexp_like(id, '^[0-9]+');




–执行结果

   	STR
1234

3.2 regexp_replace(Srcstr, pattern, [replacestr],[position],[occurrence],[modifier])

3.2.1 参数解释

Srcstr:需要进行正则处理的字符串。
pattern:正则表达式。
replacestr:需要替换成什么字段
position:起始位置(从字符串的第几个开始正则,默认为1,注:数据库中的字符串起始位置为1)。
occurrence:bigint类型常量,必须大于等于0,
大于0:表示将第几次匹配替换成replace_string,
等于0:表示替换掉所有的匹配子串。
其它类型或小于0抛异常。
modifier:模式(‘i’不区分大小写,‘c’区分大小写。其中默认没‘c’)。

3.2.2 实际用例
eg1:按照规则替换字符
with temp_strings as (   
  select 'abc123' str from dual union all
  select '123abc' str from dual union all
  select 'adf13994893964adf13453983743 ' str from dual union all
  select '2020年09月17日' str from dual union all
  select 'a1b2c3' str from dual
)   
select t.str 源字符串,
       regexp_replace(t.str, '[0-9]', '', 1)              as  无数字字符串,
	   regexp_replace(str, '.*(1[[:digit:]]{10}).*','\1') as  截取手机号,
	   REGEXP_REPLACE(T2.PAY_END_DT, '[^0-9]')            as  截取所有的数字
  from temp_strings t;

执行结果

	源字符串	无数字字符串
1	abc123	abc
2	123abc	abc
3	a1b2c3	abc

eg2: regexp_replace和listagg组合使用,实现对分组聚合后的结果进行去重
eg2.1 :数字汇总去重
 WITH NEWS_TYPE_VARCHAR AS
 (SELECT 't1' AS ID, 'A' AS Attach_Id
    FROM DUAL
  UNION ALL
  SELECT 't1', 'A'
    FROM DUAL
  UNION ALL
  SELECT 't1', 'C'
    FROM DUAL
  UNION ALL
  SELECT 't2', 'A'
    FROM DUAL
  UNION ALL
  SELECT 't2', 'B'
    FROM DUAL),
NEWS_TYPE_NUMBER AS
 (SELECT 't1' AS ID, '11' AS Attach_Id
    FROM DUAL
  UNION ALL
  SELECT 't1', '12'
    FROM DUAL
  UNION ALL
  SELECT 't1', '12'
    FROM DUAL
  UNION ALL
  SELECT 't2', '1'
    FROM DUAL
  UNION ALL
    SELECT 't2', '1'
    FROM DUAL)
select 'VARCHAR' AS QULB,
       T.ID,
       listagg(T.Attach_Id, ',') within group(order by 1),
       regexp_replace((listagg(T.Attach_Id, ',') within group(order by 1)),
                      '(,[[:digit:]]+)(\1)+',
                      '\1') GROUP_CODE
  from NEWS_TYPE_VARCHAR t
 GROUP BY T.ID
UNION ALL
select 'NUMBER',
       T.ID,
       listagg(T.Attach_Id, ',') within group(order by 1),
       regexp_replace((listagg(T.Attach_Id, ',') within group(order by 1)),
                      '(,[[:digit:]]+)(\1)+',
                      '\1') GROUP_CODE
  from NEWS_TYPE_NUMBER t
 GROUP BY T.ID;

–执行结果:只对数字生效,字符串无效



1	VARCHAR	t1	A,A,C	A,A,C
2	VARCHAR	t2	A,B	A,B
3	NUMBER	t1	11,12,12	11,12
4	NUMBER	t2	1,1	1,1
eg2.2:对任何以逗号隔开的任何字符串(包括数字)去重

//注意:这只能对相邻的字符串去重,因此要对字符串去重,必须先通过order by排序后去重

WITH NEWS_TYPE_VARCHAR AS
 (SELECT 't1' AS ID, 'A' AS Attach_Id
    FROM DUAL
  UNION ALL
  SELECT 't1', 'A'
    FROM DUAL
  UNION ALL
  SELECT 't1', 'C'
    FROM DUAL
  UNION ALL
  SELECT 't2', 'A'
    FROM DUAL
  UNION ALL
  SELECT 't2', 'B'
    FROM DUAL),
NEWS_TYPE_NUMBER AS
 (SELECT 't1' AS ID, '11' AS Attach_Id
    FROM DUAL
  UNION ALL
  SELECT 't1', '12'
    FROM DUAL
  UNION ALL
  SELECT 't1', '12'
    FROM DUAL
  UNION ALL
  SELECT 't2', '1'
    FROM DUAL
  UNION ALL
    SELECT 't2', '1'
    FROM DUAL)
select 'VARCHAR' AS QULB,
       T.ID,
       listagg(T.Attach_Id, ',') within group(order by 1),
       regexp_replace((listagg(T.Attach_Id, ',') within group(order by 1)),
                      '([^,]+)(,\1)*(,|$)',
                      '\1\3') GROUP_CODE
  from NEWS_TYPE_VARCHAR t
 GROUP BY T.ID
UNION ALL
select 'NUMBER',
       T.ID,
       listagg(T.Attach_Id, ',') within group(order by 1),
       regexp_replace((listagg(T.Attach_Id, ',') within group(order by 1)),
                      '([^,]+)(,\1)*(,|$)',
                      '\1\3') GROUP_CODE
  from NEWS_TYPE_NUMBER t
 GROUP BY T.ID;

–执行结果

1	VARCHAR	t1	A,A,C	A,C
2	VARCHAR	t2	A,B	A,B
3	NUMBER	t1	11,12,12	11,12
4	NUMBER	t2	1,1	1
eg2.3:以+号分割

WITH NEWS_TYPE_VARCHAR AS
 (SELECT 't1' AS ID, 'A' AS Attach_Id
    FROM DUAL
  UNION ALL
  SELECT 't1', 'A'
    FROM DUAL
  UNION ALL
  SELECT 't1', 'C'
    FROM DUAL
  UNION ALL
  SELECT 't2', 'A'
    FROM DUAL
  UNION ALL
  SELECT 't2', 'B'
    FROM DUAL)
select 'VARCHAR' AS QULB,
       T.ID,
       listagg(T.Attach_Id, '+') within group(order by 1),
       regexp_replace((listagg(T.Attach_Id, '+') within group(order by 1)),
                      '([^\+]+)(\+\1)*(\+|$)'
					  ,'\1\3') GROUP_CODE
	   --,to_char(rtrim(xmlagg(xmlparse(content upper(Attach_Id) || '+' wellformed) order by 1).getclobval() ,'+')) item_name  未能实现去重
  from NEWS_TYPE_VARCHAR t
 GROUP BY T.ID;

–执行结果:

1	VARCHAR	t1	A+A+C	A+C
2	VARCHAR	t2	A+B	    A+B
eg2.4 特殊情况,未实操演示

//如果遇到字符串过长,则可以使用如下语句

regexp_replace(rtrim(xmlagg(xmlparse(content upper(product_id) || ',' wellformed) order by product_id).getclobval() ,','),'([^,]+)(,\1)*(,|$)', '\1\3') product_id,

//如果是mybatis中使用如下语句,否则会报错

regexp_replace((listagg(product_id, ',') within group(order by product_id)),  '([^,]+)(,\1)*(,|$)','\1\3') product_id

eg3:取正则的不同部分处理
SELECT regexp_replace('+86 13811112222',
                      '(\+[0-9]{2})( )([0-9]{3})([0-9]{4})([0-9]{4})',
                      '(\1)\3-\4-\5'),  				   --格式化手机号 ’+‘在正则表达式中有定义,需要转义。\1表示引用的第一个组 (+86)138-1111-2222
	   regexp_replace('123.456.7890',
                      '([[:digit:]]{3})\.([[:digit:]]{3})\.([[:digit:]]{4})',
                      '(\1)\2-\3'),  			      	   --(123)456-7890
       regexp_replace('123.456.7890',
                      '([0-9]{3})\.([0-9]{3})\.([0-9]{4})',
                      '(\1)\2-\3'),						   --(123)456-7890
	   regexp_replace('abcdefg123456ABC', '(.)', '\1 ',1), --a b c d e f g 1 2 3 4 5 6 A B C
	   regexp_replace('abcdefg123456ABC', '(.)', '\1 ',2)  --ab c d e f g 1 2 3 4 5 6 A B C 
       regexp_replace('abcd','(.*)(.)$','\1',1)            --abc
	   regexp_replace('abcd','(.*)(.)$','\1-\2',1)         --abc-d
	   
  from dual;
eg4: 其他案例:
SELECT regexp_replace('abcd','(.)','\2',1)         --结果为'',因为pattern中只定义了一个组,引用的第二个组不存在。
      ,regexp_replace('abcd','(.*)(.)$','\2',1)    --结果为'd'
      ,regexp_replace('abcd','(.*)(.)$','\1',1)    --结果为'abc'
      ,regexp_replace('abcd','(.*)(.)$','\1-\2',1) --结果为'abc-d'
      ,regexp_replace('abcd','a','\1',1)           --,结果为” \1bcd”,因为在pattern中没有组的定义,所以\1直接输出为字符。
from dual;

3.3 regexp_like(Srcstr, pattern, [replacestr],[position],[occurrence],[modifier])

3.3.1 参数解释

Srcstr:需要进行正则处理的字符串。
pattern:正则表达式。
replacestr:需要替换成什么字段
position:起始位置(从字符串的第几个开始正则,默认为1,注:数据库中的字符串起始位置为1)。
occurrence:bigint类型常量,必须大于等于0,
大于0:表示将第几次匹配替换成replace_string,
等于0:表示替换掉所有的匹配子串。
其它类型或小于0抛异常。
modifier:模式(‘i’不区分大小写,‘c’区分大小写。其中默认没‘c’)。

3.3.2 实际用例
with regexp_like_temp_table as (
select 'adf13994893964ad f13453983743' str from dual
union all
select '1222260' str from dual
union all
select '122a260' str from dual
union all
select '1badfadfa' str from dual
union all
select '1Badfadfa' str from dual
union all
select 'adfsdfsfadf adadf' str from dual
union all
select 'adfsdfsfC,adfadadf' str from dual

)
 select *
   from regexp_like_temp_table
  where regexp_like(str, '.*(1[[:digit:]]{10}).*')    --查询包含以1开头的11位数据
     or (regexp_like(str, '1....60')                   
         or str like '1____60' )                      --"____"表示4个"_"  以 1 开头 60 结尾的记录并且长度是 7 位
     or (regexp_like(str, '^1[0-9]{4}60$') 
	 	 or regexp_like(str, '^1[[:digit:]]{4}60$'))  --以 1 开头 60 结尾的记录并且长度是 7 位且全部是数字的记录
     or regexp_like(str, '^[^[:digit:]]+$')           --[] 内的 ^ 表示 '非' 查询 str 中不包含任何数字的记录
	 or not regexp_like(str, '^[[:digit:]]+$')        --查询 str 中不是纯数字的记录
	 or (regexp_like(str, '^(12)|^(1b)')  
         or regexp_like(str, '^1[2b]'))	              --查询以 12 或 1b 开头的记录,区分大小写
	 or regexp_like(str, '^1[2b]', 'i')               --以 12 或 1b 开头的记录,不区分大小写
	 OR regexp_like(str, '^([a-z]+|[0-9]+)$')         --查询所有均为 小写字母 或 数字的记录
	 OR regexp_like(str, '[[:space:]]')               --查询包含 空白 的记录
	 OR regexp_like(str, '[[:punct:]]')               --查询包含 标点符号 的记录
	 	 OR REGEXP_LIKE(lkm_mobile,'[1][1234567890]{10}') --手机号必须是11位数字,开头是1
     OR REGEXP_LIKE(lkm_tel,'[0][1234567890]2,3[0][1234567890]2,3-[1234567890]{7,8}') --电话号码必须是(010)-1234567,区号3,4位,座机号7,8位
	 OR REGEXP_LIKE(test,'[0][0123456789]2,3[0][0123456789]2,3-[0123456789]{7,8}') --验证必须是电话号码:例:(010)-6666666
 ;

3.4 regexp_instr(String, pattern, [position],[occurrence],[retrurnparam],[modifier],[subexpression])

3.4.1 参数解释

srcstr : 源字符串 – source string
pattern : 正则表达式
position : 起始位置,默认 1
occurrence : 第几次出现,默认 1(匹配成功的次数,依次递增)
returnparam : 返回参数对应的下标(0:第一个位置的下标,非0:最后一个位置的下标)
modifier : 模式(‘i’: 不区分大小写,‘c’: 区分大小写。 默认 ‘c’)
subexpression: 含有子表达式 0-9, 默认 0:不含子表达式,1:第一个子表达式,以此类推

3.4.2 实际用例
select regexp_instr('1,23,456,7890', '[0-9]+', 1, 3)    				--匹配到的第一个字符下标,   --查询结果: 6
      ,regexp_instr('1,23,456,7890', '[0-9]+', 1, 3, 1) 				--最后一个字符后一位的下标, --查询结果: 9
      ,regexp_instr('1234567890', '(123)(4)(56)(78)', 1, 1, 0, 'i', 4)  --匹配到的第四个子表达式    --查询结果: 7
  from dual;

二、DBMS_RANDOM随机函数应用

1.DBMS_RANDOM.STRING (opt IN CHAR,len IN NUMBER) RETURN VARCHAR2;

1.1 参数解释

参数len指定生成的字符串的长度。
参数opt指定生成的字符串的样式,允许的取值及其表示的含义

1.2 参数用例含义

取值含义
‘u’或’U’
返回一个由大写字母组成的字符串
‘l’或’L’
返回一个由小写字母组成的字符串
‘a’或’A’
返回一个由大写字母和小写字母组成的字符串
‘x’或’X’
返回一个由大写字母和数字组成的字符串
‘p’或’P’
返回一个由任意的可打印字符组成的字符串

1.3 执行示例

select 
 DBMS_RANDOM.STRING ('u',6) --JETRGA
,DBMS_RANDOM.STRING ('l',6) --akntyk
,DBMS_RANDOM.STRING ('a',6) --iWWCkT
,DBMS_RANDOM.STRING ('x',6) --0D4N24
,DBMS_RANDOM.STRING ('p',6) --TUB=rF
,DBMS_RANDOM.STRING ('U',6) --LNDYKS
,DBMS_RANDOM.STRING ('L',6) --mlajxi
,DBMS_RANDOM.STRING ('A',6) --MqgIaR
,DBMS_RANDOM.STRING ('X',6) --H53KN4
,DBMS_RANDOM.STRING ('P',6) --M3[.ig
from dual;

三、窗口分析函数的应用:FIRST_VALUE\LAST_VALUE\lag\lead

1 概述

1.1 说明

(1) 均属于 ‘分析函数’: 每行一条记录(不聚合)
(2) + over(partition by 列1 order by 列2) – 一同使用

1.2 含义

first_value() – 第一个
last_value() – 最后一个 特别注意:是 ‘第一个’ 到 ‘当前记录’ 排行中的 ‘最后一个’ rows between unbounded preceding and current row
lag() – 上一个
lead() – 下一个

2 应用实例

2.1 first_value()和last_value()的使用

with student_info as (
  select 1 sno, 'a' sname, 18 age, date '2020-01-01' create_date from dual union all
  select 2 sno, 'b' sname, 18 age, date '2020-02-01' create_date from dual union all
  select 3 sno, 'c' sname, 18 age, date '2020-03-01' create_date from dual
)
select si.sno,
       si.sname,
       si.age,
       si.create_date,
       first_value(si.sname) over(partition by si.age order by si.create_date) 第一条记录,
       last_value(si.sname) over(partition by si.age order by si.create_date) 至当前最后一条记录,
       first_value(si.sname) over(partition by si.age order by si.create_date desc) 所有记录中最后一条
  from student_info si;

–执行结果


sno		sname	age		create_date		第一条记录	至当前最后一条记录		所有记录中最后一条
1		a		18		2020/1/1		a			a					c
2		b		18		2020/2/1		a			b					c
3		c		18		2020/3/1		a			c					c

2.2 lag() + lead()

with student_info as (
  select 1 sno, 'a' sname, 18 age, date '2020-01-01' create_date from dual union all
  select 2 sno, 'b' sname, 18 age, date '2020-02-01' create_date from dual union all
  select 3 sno, 'c' sname, 18 age, date '2020-03-01' create_date from dual
)
select si.sno,
       si.sname,
       si.age,
       si.create_date,
       lag(si.sname) over(partition by si.age order by si.create_date) 上一条记录,
       lead(si.sname) over(partition by si.age order by si.create_date) 下一条记录
  from student_info si;

–执行结果



sno   sname age   create_date   上一条记录 下一条记录
1       a   18    2020/1/1                   b
2       b   18    2020/2/1             a     c
3       c   18    2020/3/1             b

3 扩展

3.1 保持排序,且避免返回多行 keep()


/*
   要点:在子查询中 既能达到排序的目的,又不用担心 '返回多行'
   示例:查询各部门第一个入司的人
*/
select d.*,
       (select max(e.ename) keep(dense_rank first order by e.hiredate) 
               -- 报错:子查询返回多行
               -- max(e.ename) over(partition by e.deptno order by e.hiredate)
          from scott.emp e
         where e.deptno = d.deptno) 第一个入司的人
  from scott.dept d;

四、Execute immediate语句和using关键字实现动态SQL

1 概述

1.1 Execute immediate 动态SQL语句 into 出参1,出参2… using 形参1,形参2…

insert、update 是提取 操作后 的数据,delete 是提取 操作前 的数据。

1.2 Execute immediate 动态SQL语句 using 形参1,形参2… returning into 出参1,出参2…

returning 子句只能用于insert、update、delete。
returning into 在 动态sql内部和外面都要写,内部变量需要加上标识符“:”,外面不用,且外面的 returning 后面不加字段直接 into。
returning 不支持 record

2 应用实例

准备测试表

create table test1 (id number(2));
create table test2 (id number(2));
--向测试表中添加数据
begin
  for i in 1..50 loop
    insert into test1 values(round(dbms_random.value()*10));
  end loop;
  commit;
end;

begin
  for i in 1..100 loop
    insert into test2 values(round(dbms_random.value()*10));
  end loop;
  commitend;

2.1 into的使用

--目标:根据test1表的ID,查询在test2表出现的次数并输出。
declare
  flag number;
begin
  --循环获取test1表的数据
  --可以在SQL后面用||拼接形参,也可以使用 :参数名 作为占位符
  for test1 in (select distinct id from test1 order by id) loop
    execute immediate 'select count(1) from test2 where id = :1'
      into flag
        --注意占位符和using后的参数绑定是按照前后顺序的
      using test1.id;
    dbms_output.put_line('ID为'||test1.id||'的数量为:'||flag);
  end loop;
end;


–执行结果

ID为0的数量为:5
ID为1的数量为:10
ID为2的数量为:11
ID为3的数量为:15
ID为4的数量为:12
ID为5的数量为:7
ID为6的数量为:8
ID为7的数量为:15
ID为8的数量为:9
ID为9的数量为:10
ID为10的数量为:5

2.2 returning的使用

--目标:根据传入的ID删除test2表的数并输出删除条数。
declare
  type v_table_id is table of test1.id%type;
  v_id v_table_id;
  flag number := 1;
begin
  execute immediate 'delete test1 where id =' || flag ||
                    'returning id into :v_id'
    returning bulk collect into v_id; --v_id 是一个list集合
    rollback;
    dbms_output.put_line('总删除数:'||v_id.count);
    for i in 1..v_id.count loop
      dbms_output.put_line('删除值'||i||':'||v_id(i));
      end loop;
end;


–执行结果

总删除数:6
删除值11
删除值21
删除值31
删除值41
删除值51
删除值61

五、约束的应用:FIRST_VALUE\LAST_VALUE\lag\lead

1 概述 Oracle数据库中的约束有五种约束,分别是:

1.1 实体完整性:主键约束、唯一性约束(可以为空)

Constraint Primary Key|Unique (<column_name>)

1.2 域完整性:check约束

Constraint Check (列条件表达式)

1.3 引用完整性:Foreign KEY约束

Constraint Foreign key (<column_name>) references <table_name>(<column_name>)

1.4 默认约束(默认值)

column_name column_type default ‘默认值’ --创建表或修改表字段

2 约束增删改查

2.1 删除约束

alter table 表名 drop constraint 约束名称;

2.2 禁用/启用约束

alter table 表名 disable/enable constraint 约束名称;

2.3 修改约束名称

alter table 表名 rename constraint 旧约束名称 to 新约束名称;

2.4 添加约束

alter table test add constraint test_pk primary key(id); --添加主键约束(非空,不重复)(给test表的id这一列添加主键约束)
alter table test add constraint test_unique_name unique(name); --添加唯一性约束(不重复,可以为空)(给test表name这一列添加唯一性约束)
alter table test add constraint test_cus_no_fk_1  foreign key(cus_no) references cus_info (cus_no)--添加外键约束(保证外键的值取关联表里关联字段的值)(给表test的列cus_no设为外键,关联表cus_info的列cus_no
alter table test add constraint test_name_check check(name in ('a','b','c') ) /* check(REGEXP_LIKE(lkm_mobile,'[1][1234567890]{10}')) */; --完整性约束(代表一个字段或者多个字段的取值是有限定范围的)
create table t1 (tname varchar2(20) default 'yang');--默认约束-创建表
alter table test_table add (TEST_D VARCHAR2(100) NOT NULL default 'yang' );--默认约束-修改列属性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值