Find session of locked row - oracle

I am experiencing row lock contention in my oracle DB. I tried to kill some session to unlock them, but this rows are still locked.
I know exact which row are locked.
Can I find the session ID that has locked this row. I can get the ROWID of that row.

As the good folks on AskTom say, we don't maintain a list of locked rows
But, if you want to try this - it'll show you locks by USER in your database, including Row locks.
SELECT
p.username username,
p.pid pid,
s.sid sid,
s.serial# serial,
p.spid spid,
s.username ora,
DECODE(l2.type, 'TX', 'TRANSACTION ROW-LEVEL', 'RT', 'REDO-LOG', 'TS', 'TEMPORARY SEGMENT ', 'TD', 'TABLE LOCK', 'TM', 'ROW LOCK'
, l2.type) vlock,
DECODE(l2.type, 'TX', 'DML LOCK', 'RT', 'REDO LOG', 'TS', 'TEMPORARY SEGMENT', 'TD', DECODE(l2.lmode + l2.request, 4, 'PARSE '
|| u.name || '.' || o.name, 6, 'DDL', l2.lmode + l2.request), 'TM', 'DML ' || u.name || '.' || o.name, l2.type) type,
DECODE(l2.lmode + l2.request, 2, 'RS', 3, 'RX', 4, 'S', 5, 'SRX', 6, 'X', l2.lmode + l2.request) lmode,
DECODE(l2.request, 0, NULL, 'WAIT') wait
FROM
gv$process p,
gv$_lock l1,
gv$lock l2,
gv$resource r,
sys.obj$ o,
sys.user$ u,
gv$session s
WHERE
s.paddr = p.addr
AND s.saddr = l1.saddr
AND l1.raddr = r.addr
AND l2.addr = l1.laddr
AND l2.type <> 'MR'
AND r.id1 = o.obj# (+)
AND o.owner# = u.user# (+)
--AND u.name = 'GME'
AND ( :user_name IS NULL
OR s.username LIKE upper(:user_name) )
ORDER BY
p.username,
p.pid,
p.spid,
ora,
DECODE(l2.type, 'TX', 'TRANSACTION ROW-LEVEL', 'RT', 'REDO-LOG', 'TS', 'TEMPORARY SEGMENT ', 'TD', 'TABLE LOCK', 'TM', 'ROW LOCK'
, l2.type)
This is a report in SQL Developer.

Related

migrate oracle table using chunks

I am trying to download a huge table (billions of records) from oracle DB
The base can hold a session only for a few hours (no idea why)
So my idea is to split table for many peace's and download it using dynamic sql
split query:
SELECT
data_object_id,
file_id,
relative_fno,
file_batch,
subobject_name,
MIN (start_block_id) start_block_id,
MAX (end_block_id) end_block_id,
SUM (blocks) blocks
FROM
(SELECT
o.data_object_id,
e.file_id,
e.relative_fno,
e.block_id start_block_id,
e.block_id + e.blocks - 1 end_block_id,
e.blocks,
CEIL (SUM(e.blocks) OVER (PARTITION BY o.data_object_id, e.file_id ORDER BY e.block_id ASC) /
(SUM (e.blocks)OVER (PARTITION BY o.data_object_id,e.file_id) / 1)) file_batch
FROM
dba_extents e,
dba_objects o,
dba_tab_subpartitions tsp
WHERE
o.owner = :owner
AND o.object_name = :object_name
AND e.owner = :owner
AND e.segment_name = :object_name
AND o.owner = e.owner
AND o.object_name = e.segment_name
AND (o.subobject_name = e.partition_name
OR (o.subobject_name IS NULL
AND e.partition_name IS NULL))
AND o.owner = tsp.table_owner(+)
AND o.object_name = tsp.table_name(+)
AND o.subobject_name = tsp.subpartition_name(+))
GROUP BY
data_object_id,
file_id,
relative_fno,
file_batch
ORDER BY
data_object_id,
file_id,
relative_fno,
file_batch;
it splits usual table, but it doesn't work with partition or subpartition tables (when I try to download it has more or less lines than it is in DB)
the queries for download I used:
SELECT /*+ NO_INDEX(t) */ COLUMN_NAMES,'63_17' data_chunk_id
FROM OWNER.OBJECT_NAME t
WHERE ((rowid >= dbms_rowid.rowid_create(1, 846313, 63, 3057792, 0)
AND rowid <= dbms_rowid.rowid_create(1, 846313, 63, 4056447, 32767)));
Check out DBMS_PARALLEL_EXECUTE. Even if you don't use it "completely", ie, to run the extract, you can use the DBMS_PARALLEL_EXECUTE.CREATE_CHUNKS_BY_ROWID routine to generate a list of rowid ranges that you can then use to run your rowid range queries that you've already written.

DBMS_LOCK how to find LOCKID by NAME

My task is to show for oracle forms user session id of some locked object in oracle database. It is possible get from select (l1.name is known value):
SELECT l2.SID
FROM SYS.DBMS_LOCK_ALLOCATED l1,
gv$lock l2
WHERE l1.lockid = l2.ID1
AND l1.name = 'OBJECT_NAME'
The problem is that our oracle forms users have not access to the table SYS.DBMS_LOCK_ALLOCATED. Package DBMS_LOCK has no function to find SYS.DBMS_LOCK_ALLOCATED.LOCKID by SYS.DBMS_LOCK_ALLOCATED.NAME.
Someone have ideas on how to solve this problem?
You can use the following query to get lock status of object:
select oracle_username || ' (' || s.osuser || ')' username
, s.sid || ',' || s.serial# sess_id
, owner || '.' || object_name object
, object_type
, decode( l.block
, 0, 'Not Blocking'
, 1, 'Blocking'
, 2, 'Global') status
, decode(v.locked_mode
, 0, 'None'
, 1, 'Null'
, 2, 'Row-S (SS)'
, 3, 'Row-X (SX)'
, 4, 'Share'
, 5, 'S/Row-X (SSX)'
, 6, 'Exclusive', TO_CHAR(lmode)) mode_held
from v$locked_object v
, dba_objects d
, v$lock l
, v$session s
where v.object_id = d.object_id
and v.object_id = l.id1
and v.session_id = s.sid
and d.object_name = '<My table>'
and d.owner = '<Owner>'
Note: I left v$-views but if You are using RAC and want to see all the instances here then just change v$ on gv$.
You can check output of the query above after doing:
create table my_table as select 1 val from dual;
lock table my_table in exclusive mode;
P.S. Don't forget to hit commit to unlock my_table.

ORA-01427 Single row subquery return more than one row

I have the below query once I run it, it's exceeded successfully without error, but when I run it inside a procedure, I got the single error.
CREATE OR REPLACE PROCEDURE ABLEA_NEW.AB_VATFILE
IS
fHandle UTL_FILE.FILE_TYPE;
err varchar2(200);
v_str VARCHAR2(4000);
CURSOR VAT1 IS
SELECT (SELECT cif_no
FROM nbfc_customer_m
WHERE customerid = a.bpid) ||
(SELECT EXTRACT_ACCT(HOST_ACCT_INFO, 'SUFFIX')
FROM LEA_AGREEMENT_GROUPGL_MAP A, FA_ACCTCATG_M B
WHERE EXTRACT_ACCT(A.HOST_ACCT_INFO, 'ACCTCATG') = B.ACCTCATG
AND B.GROUPID = 'FA'
AND A.ACTIVE_FLAG = 'Y'
and AGREEMENTID = a.caseid)
"Account No",lpad(a.caseid,6,0) Loan_No
,
(SELECT AGREEMENTNO
FROM lea_agreement_dtl
WHERE AGREEMENTID = a.caseid)
AGREEMENTNO
,
LPAD(A.productid,3,0) Scheme_ID,
(SELECT rpad(schemedesc,35,' ')
FROM lea_scheme_m
WHERE schemeid = a.productid)
SchemeDesc,
to_char(a.advicedate,'ddmmyyyy') advicedate,
it_conv(a.adviceamt) adviceamt,
rpad(a.chargeid,6,' ')chargeid,
(SELECT rpad(chargedesc,35,' ')
FROM nbfc_charges_m
WHERE chargeid = a.chargeid)
"Charge Description",
IT_CONV(a.chargeamt)chargeamt,
(SELECT
decode(count(1),0,'N','Y')
FROM nbfc_pmnt_dtl y
WHERE a.txnadviceid = y.txnadviceid
AND a.status = 'A'
AND y.status IS NULL
--and TRUNC(y.pmntdate) between :p_datefrom and :p_dateto
AND a.tax_applicable = 'Y'
AND a.ptxnadviceid IS NULL)Paid,
LPAD(b.chargeid,6,0)
"VAT ChargeID",
(SELECT RPAD(chargedesc,35,' ')
FROM nbfc_charges_m
WHERE chargeid = b.chargeid)
"VAT Charge Description",
IT_CONV(b.chargeamt)
"VAT Amount"
FROM (SELECT *
FROM nbfc_txn_advice_dtl
WHERE status = 'A' AND tax_applicable = 'Y' AND ptxnadviceid IS NULL)
a,
(SELECT *
FROM nbfc_txn_advice_dtl
WHERE status = 'A' AND ptxnadviceid IS NOT NULL) b
WHERE a.txnadviceid = b.ptxnadviceid;
BEGIN
fHandle := UTL_FILE.FOPEN('UAEDB', 'VAT', 'W');
FOR I IN VAT1
LOOP
v_str:= null;
v_str:= I."Account No"||I.Loan_No||I.AGREEMENTNO || I.Scheme_ID ||I.SchemeDesc|| I.advicedate|| I.adviceamt|| I.chargeid||I."Charge Description"||I.chargeamt||I.Paid||
I."VAT ChargeID" ||I."VAT Charge Description"||I."VAT Amount";
UTL_FILE.PUTF(fHandle,v_str);
UTL_FILE.PUTF(fHandle, '\n');
END LOOP;
UTL_FILE.FCLOSE(fHandle);
END ;
/
How can I solve this?
Note: the query return mor than 10000 record.
comment or un-comment the "(select from )as ColumnAlias" query column one by one, you can find which sub query column return more than one row

Oracle Not exists

Hi All I have written a query that returns some results based on completions of classes. I'm having trouble writing an exception report based on the same classes. I think I need to use a "NOT EXISTS" subquery but am not sure how.
Here is the completions query
select papf.employee_number
, papf.full_name
, haou.name
, oe.title
, oe.course_end_date completed_date
, oav.version_name
from per_all_people_f papf
, per_all_assignments_f paaf
, hr_all_organization_units haou
, ota_events oe
, ota_delegate_bookings odb
, ota_activity_versions oav
where papf.person_id = paaf.person_id
and paaf.organization_id = haou.organization_id
and odb.event_id = oe.event_id
and odb.booking_status_type_id in (1006, 1004)
and odb.delegate_person_id = paaf.person_id
and oe.activity_version_id in (3, 1001, 2, 8, 2001)
and oe.activity_version_id = oav.activity_version_id
and haou.organization_id = 4729
and trunc(sysdate) between papf.effective_start_date and papf.effective_end_date
and trunc(sysdate) between paaf.effective_start_date and paaf.effective_end_date
order by papf.employee_number;
I want to return results for papf.employee_number, papf.full_name,and oav.version_name for employees who have not completed these courses.
So oe.activity_version_id not exists(3, 1001, 2, 8, 2001)
I'm kind of confused as to where I should do this?
Thanks
Try:
select papf.employee_number
, papf.full_name
, haou.name
, oe.title
, oe.course_end_date completed_date
, oav.version_name
from per_all_people_f papf
, per_all_assignments_f paaf
, hr_all_organization_units haou
, ota_events oe
, ota_delegate_bookings odb
, ota_activity_versions oav
where papf.person_id = paaf.person_id
and paaf.organization_id = haou.organization_id
and odb.event_id = oe.event_id
and odb.booking_status_type_id in (1006, 1004)
and odb.delegate_person_id = paaf.person_id
/* and oe.activity_version_id in (3, 1001, 2, 8, 2001) */
and NOT EXISTS(
SELECT null FROM ota_events oe1
WHERE oe1.activity_version_id = oav.activity_version_id
AND odb.event_id = oe1.event_id
AND oe1.activity_version_id in (3, 1001, 2, 8, 2001)
)
and oe.activity_version_id = oav.activity_version_id
and haou.organization_id = 4729
and trunc(sysdate) between papf.effective_start_date and papf.effective_end_date
and trunc(sysdate) between paaf.effective_start_date and paaf.effective_end_date
order by papf.employee_number;
Based on what you've mentioned (and as user symcbean pointed out, to avoid contradicting the logic in the initial SQL), you may need a separate query as shown below to get your results. Try using NOT IN.
select papf.employee_number
, papf.full_name
, haou.name
, oe.title
, oe.course_end_date completed_date
, oav.version_name
from per_all_people_f papf
, per_all_assignments_f paaf
, hr_all_organization_units haou
, ota_events oe
, ota_delegate_bookings odb
, ota_activity_versions oav
where papf.person_id = paaf.person_id
and paaf.organization_id = haou.organization_id
and odb.event_id = oe.event_id
and odb.booking_status_type_id in (1006, 1004)
and odb.delegate_person_id = paaf.person_id
and oe.activity_version_id NOT IN (3, 1001, 2, 8, 2001)
and oe.activity_version_id = oav.activity_version_id
and haou.organization_id = 4729
and trunc(sysdate) between papf.effective_start_date and papf.effective_end_date
and trunc(sysdate) between paaf.effective_start_date and paaf.effective_end_date
order by papf.employee_number;
HTH

ORA-00907: missing right parenthesis

SELECT DISTINCT( EMP.EMPLOYEEID ),
EMP.EMPLOYEECODE,
EMP.EMPLOYEENAME,
EMP.HOMEADDRESS,
DESIG.DESIGNATIONNAME
FROM HRM_EMPLOYEE EMP,
COM_DESIGNATION DESIG,
COM_DEPARTMENT DEPT,
COM_COMPANY COMP,
HRM_EMPLOYEEDEPARTMENTS EMPDEPT,
USR_USERS USRS
WHERE EMP.EMPLOYEEID = EMPDEPT.EMPLOYEEID AND
EMP.DESIGNATIONID = DESIG.DESIGNATIONID AND
DESIG.DEPARTMENTID = EMPDEPT.DEPARTMENTID AND
EMP.STATUS IN (SELECT STAT STAT
FROM
(
CASE
When (:status = 0) THEN
SELECT 1 STAT FROM dual
UNION ALL
SELECT 2 STAT FROM dual
else
Select :status STAT from dual
end
)
xx
)
Actually my need is: stow the records according to the parameter passing. if tat parameter i wish to show all records.
You cannot have a CASE statement as a table expression (unless perhaps if using nested table types). But why so complicated? Instead of this:
EMP.STATUS IN (SELECT STAT STAT
FROM
(
CASE
When (:status = 0) THEN
SELECT 1 STAT FROM dual
UNION ALL
SELECT 2 STAT FROM dual
else
Select :status STAT from dual
end
)
xx
)
Write this:
(EMP.STATUS IN (1, 2) AND :status = 0) OR
(EMP.STATUS = :status)
SELECT DISTINCT( EMP.EMPLOYEEID ),
EMP.EMPLOYEECODE,
EMP.EMPLOYEENAME,
EMP.HOMEADDRESS,
DESIG.DESIGNATIONNAME
FROM HRM_EMPLOYEE EMP,
COM_DESIGNATION DESIG,
COM_DEPARTMENT DEPT,
COM_COMPANY COMP,
HRM_EMPLOYEEDEPARTMENTS EMPDEPT,
USR_USERS USRS
WHERE EMP.EMPLOYEEID = EMPDEPT.EMPLOYEEID AND
EMP.DESIGNATIONID = DESIG.DESIGNATIONID AND
DESIG.DEPARTMENTID = EMPDEPT.DEPARTMENTID AND
(
(EMP.STATUS IN (1, 2) and :status = 0)
or :status <> 0 --This will not filter your status, as I expect you want it to do so
)

Resources