oracle group by for update以及笛卡尔积

--如果要用到集合函数的结果那么就需要在获取集合函数结果的时候后把分组的依据也要查询出来
--当然如果用不到的话就不需要再查出来的只需要group by 分组依据的行 就行了


group:除了集合函数本身所查询的字段之外,其他的字段都是查什么(查询的字段)分什么(对应的查询的字段),而且不管是单表查询还是多表联合查询也是一样的。


笛卡尔积:
比如有两张表:
student
id    name
1     jack
2     tom
3     lily


course
id    name
1     math
2     english


我们知道如果我们这样查询:
select * from student结果会有三条语句,也就结果把student表里面的每一条记录都查询出来了
同理当我们把两个表进行联合查询的时候 比如:
select s.id,s.name,c.id,c.name from student s,course c;
这个时候两张表里面同时满足条件的分别是3条和2条
这个时候要把这几条数据进行组合之后返回,自然是3*2=6了,因为id为1的既可以和name为math的course组合又可以和name为english的记录进行组合,因为它们是符合条件的。




for update的用法


for update 的作用是锁住当前的线程正在修改的数据。


串行:相当于是两个线程排队前进,前面的走不了,后面的也走不了。
并行:相当于是两个线程并排前进,谁也不会阻挡谁。


当一些数据被for update的时候,其他的线程是无法修改当前的数据的,比如:


declare 
  v_sal emp1.sal%type;
  cursor c_emp1 is select sal from emp1 
  for update;
begin
  --打开游标
  open c_emp1;
  loop
    fetch c_emp1 into v_sal; 
    exit when c_emp1%notfound;
    update emp1 set sal = sal * 1.1
    where current of c_emp1;
  end loop;
  commit;
  --关闭游标
  close c_emp1;
end;


这个游标执行的期间其他的线程是不可以修改当前游标所锁定的数据的;
因为锁住了之后就相当于是串行了,只有当前的线程修改完了其他的线程才能执行。


不同的线程:比如同一个session下同时打开两个SQL Window这个时候它们就是同一个session下的两个不通的线程了,
比如现在打开两个 win1和win2
在win1中执行语句:select * from emp where empno=7369 for update;
在win2中执行语句:update emp set comm=100 where empno=7369;


这个时候就会看到那个运行的齿轮图标变成了灰色了,因为这个时候发生了死锁了,因为win1中的语句还没有执行完毕,没有commit,所以它没有释放对这一行的锁,而这个时候win2中的进程要修改这个条数据,前面的不放,后面的却要修改它所以就产生了死锁。


如果只是在同一个win1或者是win2下同时执行上面的两句话是没有问题的,因为它们是同一个线程。
当然在不通的session中执行这两条语句就更会发生死锁了。




在oracle中“+”号的作用是计算两个数字之和的,所以不可以在oracle中使用这一用 'bac'+'def'这样做oracle会把它们两个字符串都当做是数字进行处理,结果就是出错,正确的做法是concat('abc','def')或者是'abc'||'def',如果要想把数字和字符串进行连接的话,如果使用concat首先还要把数字转换为字符串:concat('abc',to_char(123)),或者是'abc'||123都是可以的。


批量的处理数据需要用到游标:


--在emp1表中找出5位工资最低者,加薪20%
--显示雇员编号,姓名,部门编号,部门名称,
--加薪前工资等级,工资,最高工资,最低工资
--加薪后显示同样内容
--从这儿例子可以看出游标取值的时机并不是在我们定义完了之后就去取数据的,而是在我们使用游标的时候才会去取数据的。


create table emp1 as select * from emp;


declare
cursor c_emp1 is select * from emp1 order by sal for update;
cursor c_emp2 is select * from emp1 order by sal;


begin


dbms_output.put_line('加薪前:');
for i in c_emp1 loop
exit when c_emp1%rowcount>5 ;
dbms_output.put_line('员工号:'||i.empno||'姓名:'||i.ename||'工资:'||i.sal);
update emp1 set sal=i.sal*1.2 where current of c_emp1;
end loop;


for j in c_emp2 loop
exit when c_emp2%rowcount>5;
dbms_output.put_line('员工号:'||j.empno||'姓名:'||j.ename||'工资:'||j.sal);
end loop;


end;
















































  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值