Skip to content

Instantly share code, notes, and snippets.

@forstie
Last active September 29, 2021 08:18
Show Gist options
  • Save forstie/bac9f12528e8420737e754f17b9f7c2e to your computer and use it in GitHub Desktop.
Save forstie/bac9f12528e8420737e754f17b9f7c2e to your computer and use it in GitHub Desktop.
I had a client ask me... how do we see who is executing SQL INSERT, UPDATE, or DELETE statements? There are different approaches to this topic, with the best of breed answers including Guardium's Database Activity Monitor support for Db2 for i. That being said, if you want instance insight, look at your SQL Plan Cache. (before IPL'ing please)
--
-- Title: Capture detail where SQL DML is being used
-- Author: Scott Forstie
-- Date: April 15, 2020
--
-- Resources:
-- https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_74/rzajq/rzajqprocdumppc.htm
-- https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_74/rzajq/rzajqprocextractpcstatements.htm
-- https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_74/rzajq/t1000.htm
-- https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_74/rzajq/rzajqudfparsestatement.htm
-- Description: Dump the SQL Plan Cache
cl: crtlib COOLSTUFF;
-- Naming scheme: PC<MMDDYYYY>
-- Extract the SQL Plan Cache details into a permanent form
-- Note... use all UPPERCASE for the 2 parameters
CALL QSYS2.DUMP_PLAN_CACHE(fileschema => 'COOLSTUFF',
filename => 'PC04152020');
-- Extract the instances of use of Data Manipulation Language (DML)
-- Note that this will also include some rows that are not DML
-- Naming scheme: EX<MMDDYYYY>
-- Note... use all UPPERCASE for the first 2 parameters
call qsys2.extract_statements('COOLSTUFF', 'PC04152020', ' QQI6 AS TOTAL_TIME, QVC102 AS USER_NAME, qqc21 as operation, qqi2 as rows_changed,
qqjnum as jobno, qquser as jobuser, qqjob as jobname, QQC104 as pgmlib, QQC103 as pgm, QVC3001 as Client_Applname,
QVC3002 as Client_Userid, QVC3003 as Client_Wrkstnname, QVC3005 as Client_Acctng, QVC3006 as Client_Progamid ',
' AND QQI2 > 0 and qvc102 <> ''QSYS'' and qq1000l not like ''Non SQL%'' ',
' ORDER BY QQI2 DESC ', 'COOLSTUFF', 'EX04152020');
-- Extract the report of use of SQL Data Manipulation Language (DML)
-- Naming scheme: RP<MMDDYYYY>
create or replace table coolstuff.rp04152020 as
(with dml (when, sql_statement, total_time, user_name, operation, rows_changed,
jobno, jobuser, jobname, pgmlib, pgm, client_applname, client_userid,
client_wrkstnname, client_acctng, client_progamid) as (
select "Start Time" as when, sql_statement, total_time, user_name, operation,
rows_changed, jobno, jobuser, jobname, pgmlib, pgm, client_applname,
client_userid, client_wrkstnname, client_acctng, client_progamid
from coolstuff.ex04152020
where 1 = (select 1
from table (
qsys2.parse_statement(sql_statement => sql_statement)
)
where sql_statement_type in ('INSERT', 'DELETE', 'UPDATE', 'MERGE')
limit 1)
)
select when, sql_statement, schema as dml_target_schema,
name as dml_target_table, total_time, user_name, operation, rows_changed,
jobno, jobuser, jobname, pgmlib, pgm, client_applname, client_userid,
client_wrkstnname, client_acctng, client_progamid
from dml, lateral (
select *
from table (
qsys2.parse_statement(sql_statement => sql_statement)
)
where usage_type = 'TARGET TABLE'
and name_type = 'TABLE'
))
with data
on replace delete rows;
stop;
-- Review the detail
select when, sql_statement, dml_target_schema, dml_target_table, total_time, user_name,
operation, rows_changed, jobno, jobuser, jobname, pgmlib, pgm, client_applname,
client_userid, client_wrkstnname, client_acctng, client_progamid
from coolstuff.rp04152020
order by when;
stop;
-- basic test
call qsys.create_sql_sample('DOGBIZ1');
create or replace table dogbiz1.sales2 as (select * from dogbiz1.sales) with data on replace delete rows;
insert into dogbiz1.sales2 select * from dogbiz1.sales2 ;
update dogbiz1.sales2 set sales = sales + 11;
delete from dogbiz1.sales2 limit 5;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment