Last active
September 29, 2021 08:18
-
-
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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- | |
-- 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