在开发过程中,发现了一串代码,如下:
INSERT INTO acc_invoice_print_list (instance_id, invoice_id, charge_name,currency,unit_price,unit_num,amount,invoice_amount,unit_name,specifications)
SELECT TO_CHAR(SYSDATE,'YYYYMMDD') || seq_charge_id.nextval instance_id, invoice_id, charge_name,currency,unit_price,unit_num,amount,invoice_amount,unit_name,specifications
FROM (
SELECT #insertList[].invoice_id# invoice_id,
#insertList[].charge_name# charge_name,
#insertList[].currency# currency,
#insertList[].unit_price# unit_price,
#insertList[].unit_num# unit_num,
#insertList[].amount# amount,
#insertList[].invoice_amount# invoice_amount,
#insertList[].unit_name# unit_name,
#insertList[].specifications# specifications
FROM dual
)
在研究之后发现,这串代码中的insert语句后面没有values,而是在写好相应的字段名之后,在后面加了一个select语句,而此条select语句返回的是一个结果集,如果代码可以执行成功,也就意味着通过 insert into table_name1(column1, column2, column3) select column1, column2, column3 from table_name2;这种形式可以插入多条数据,遂自己验证了一下。
首先创建一个表;
create table test111(
job_id number(15) not null primary key,
job_no varchar2(15),
sale_corp_id number(10)
)
然后利用上面的格式写入insert语句;
insert into test111
(job_id, job_no, sale_corp_id)
select h.job_id, h.job_no, h.sale_corp_id
from job_head h
where h.create_date > to_date('2019/09/21', 'yyyy/MM/dd')
最后成功插入。
这种操作在复制表数据的时候可能会有一定的便捷性,不需使用循环等操作。
补充:
在插入数据之后,没有及时提交导致了进程死锁,下面附带解决死锁的方法。
1. 查找是否存在进程死锁;
select username, lockwait, status, machine, program
from v$session
where sid in (select session_id from v$locked_object)
其中status可能有两个值,active,inactive。其中active指的是正在执行(一直处于执行状态),inactive指的是等待执行。
例如:
--SQL1
delete from test111;
--SQL2
delete from test111;
先执行SQL1,不提交,再执行SQL2,执行查询死锁的SQL,就会发现有两条记录,一个active,一个inactive。不论是active还是inactive都是不正常的进程,应该手动清除。
2. 通过以下语句可查询到具体是那个语句造成了死锁情况。
select sql_text
from v$sql
where hash_value in
(select sql_hash_value
from v$session
where sid in (select session_id from v$locked_object))
3. 然后通过以下SQL查询到死锁进程的相关信息
select s.username,
l.object_id,
l.session_id,
s.serial#,
l.oracle_username,
l.os_user_name,
l.process
from v$locked_object l, v$session s
where l.session_id = s.sid;
4. 最后杀死进程
--session_id, serial#是上面查询到的结果中的值
alter system kill session ‘session_id,serial#’;
进程死锁参考了原文