How to segregate a stored procedure into a table row by row? - asp.net

There is a stored procedure which contains many insert, update, delete and truncate statements. I want to group all the statements one by one into a table.
For example:
create proc Get_Tables as
begin
UPDATE BB_FMCTransactionsTwo SET wsTradeDate = wsSettleDate WHERE wsEntryCode = 'NRT'
UPDATE BB_FMCTransactionsTwo SET wsOK = 1, wsSpecialLogic = SpecialLogic FROM BB_EntryCode INNER JOIN BB_FmcTransactionsTwo ON EntryCode = wsEntryCode
UPDATE BB_FMCTransactionsTwo SET wsFMCFtNt = '' FROM BB_EntryCode INNER JOIN BB_FmcTransactionsTwo ON EntryCode = wsEntryCode WHERE wsBS <> 'B' AND ( FMCFtNtB IS NULL OR FMCFtNtB = 'PR' )
UPDATE BB_B204_Tran SET AMOUNT = dbo.BCA_AMT(Desc1, Desc2, Desc3, Udesc1, Udesc2, Udesc3) WHERE TRANIND = 14 AND PORTTYPE IN (2,3)
DELETE BB_B204_Tran WHERE TRANIND = 14 AND PORTTYPE IN(2,3) AND (Quantity IS NULL OR ISNUMERIC(Quantity) = 0 OR Quantity = -1 OR ISNUMERIC(AMOUNT) = 0
end
Required:
I want to insert the update statements, delete statements into a table one by one...
Create a stored procedure which divides the stored procedure based on type of statements (Insert, Update, Truncate) and inserts that into a table row by row. So that the table looks like below.
Table:
Sl.No Statement
1 UPDATE BB_FMCTransactionsTwo SET wsTradeDate = wsSettleDate WHERE wsEntryCode = 'NRT'
2 DELETE BB_B204_Tran WHERE TRANIND = 14 AND PORTTYPE IN(2,3)

I have implemented for your first update statement and assume that your AuditTable will have one column SQLData and so you need to store these SQL Statements in your store procedure and if you have used any variable then you need to store into SQL Data variable and insert into Audit Table. it may help you.
declare ##SQL1 varchar(max)
UPDATE BB_FMCTransactionsTwo SET wsTradeDate = wsSettleDate WHERE wsEntryCode = 'NRT'
set ##SQL1 = 'UPDATE BB_FMCTransactionsTwo SET wsTradeDate = wsSettleDate WHERE wsEntryCode = ''NRT'''
insert into AuditTable (SQLData) values(##SQL1)
For Variable:
DECLARE ##wsEntryCode VARCHAR(100)
SET ##wsEntryCode='NRT'
PRINT 'UPDATE BB_FMCTransactionsTwo SET wsTradeDate = wsSettleDate WHERE wsEntryCode = ''' + ##wsEntryCode + ''''
insert into AuditTable (SQLData) values(##SQL1)

Related

Error while deleting row from table color: sub-select returns 3 columns - expected 1

I am trying to write a trigger so that whenever a change occurs in any table in the db the trigger records the changes in a sql table with schema
I am trying to run this script
def log_changes(db_path):
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
cursor.execute(
"SELECT name FROM sqlite_master WHERE type='table' AND name NOT IN ('changes', 'sqlite_sequence');")
tables = cursor.fetchall()
for table in tables:
table_name = table[0]
column_names = ', '.join([f"{col[1]} as '{col[0]}'" for col in cursor.execute(
f"PRAGMA table_info({table_name})").fetchall()])
# print(column_names)
cursor.execute(f"DROP TRIGGER IF EXISTS log_{table_name}_insert")
cursor.execute(f"DROP TRIGGER IF EXISTS log_{table_name}_update")
cursor.execute(f"DROP TRIGGER IF EXISTS log_{table_name}_delete")
# create trigger so that when a row is inserted, the row is logged in the changes table with the action 'insert' and the current timestamp and the new data is the row that was inserted (NEW)
insert_trigger = f"CREATE TRIGGER IF NOT EXISTS log_{table_name}_insert AFTER INSERT ON {table_name} BEGIN INSERT INTO changes (table_name, action, timestamp, old_data, new_data) VALUES ('{table_name}', 'insert', datetime('now','localtime'), null, (SELECT {column_names} FROM {table_name} WHERE rowid = NEW.rowid)); END;"
# print(insert_trigger)
delete_trigger = f"CREATE TRIGGER IF NOT EXISTS log_{table_name}_delete AFTER DELETE ON {table_name} BEGIN INSERT INTO changes (table_name, action, timestamp, old_data, new_data) VALUES ('{table_name}', 'delete', datetime('now','localtime'), (SELECT {column_names} FROM {table_name} WHERE rowid = OLD.rowid), null); END;"
# print(delete_trigger)
update_trigger = f"CREATE TRIGGER IF NOT EXISTS log_{table_name}_update AFTER UPDATE ON {table_name} BEGIN INSERT INTO changes (table_name, action, timestamp, old_data, new_data) VALUES ('{table_name}', 'update', datetime('now','localtime'), (SELECT {column_names} FROM {table_name} WHERE rowid = OLD.rowid), (SELECT {column_names} FROM {table_name} WHERE rowid = NEW.rowid)); END;"
# print(update_trigger)
cursor.execute(insert_trigger)
cursor.execute(delete_trigger)
cursor.execute(update_trigger)
conn.commit()
conn.close()
this query works but the trigger is not working properly.
I want to insert the row data that has been modified in the new data column so I am using rowid are the queries correct?

PLSQL Procedure to load data into dimension table from multiple tables

I have a requirement to load distinct costcenternum and a seq_key to be inserted. I wrote a procedure but this is failing one is distinct and even after removing distinct not able to run this procedure.
Please help me to correct this query to generate a seq key and also distinct cost numbers into the division table.
CREATE OR REPLACE
PROCEDURE POPULATE_DIVISION_DIM AS
BEGIN
INSERT INTO DIVISION(
"COST_CENTER_KEY"
,"COST_CENTER_NUM"
,"COST_CENTER_DESC"
,"DIVISION_CODE"
,"DIVISION_DESC"
,"COMPANY_CODE"
,"INSERT_DT"
,"UPDATE_DT"
)
(
SELECT
cc_sequence.nextval cost_center_key
, distinct (pcaf.segment4) costcenter_num
,ffvv.description costcenter_desc
,hoi.org_information9 division
,(SELECT description
FROM hr_lookups
WHERE lookup_type = 'CAT'
AND lookup_code = hoi.org_information9)
division_desc
, ppg.segment1 company
,TRUNC(SYSDATE) insert_dt
,TRUNC(SYSDATE) update_dt
FROM
hr_organization_information hoi
, hr_all_organization_units haou
, pay_cost_allocation_keyflex pcaf
, fnd_flex_values_vl ffvv
, per_all_assignments_f paaf
, pay_people_groups ppg
WHERE 1=1
AND paaf.people_group_id = ppg.people_group_id
AND haou.cost_allocation_keyflex_id =
pcaf.cost_allocation_keyflex_id(+)
AND pcaf.segment4 = ffvv.flex_value(+)
AND (ffvv.FLEX_VALUE_SET_ID is null or ffvv.FLEX_VALUE_SET_ID=
(SELECT FLEX_VALUE_SET_ID FROM FND_FLEX_VALUE_SETS WHERE
FLEX_VALUE_SET_NAME = 'ABCD'))
AND ffvv.enabled_flag(+) = 'Y'
AND haou.organization_id = hoi.organization_id
AND hoi.org_information_context = 'XX'
)
;
COMMIT;
END POPULATE_DIVISION_DIM;

SQLite trigger to update a column on editing updates the column for all records in table

Hypothetical table x, with columns (all of type text):
name
sname
sqlmodded
I'd like to create a trigger to set the value of sqlmodded to '1' if any column in the record is updated.
My trigger is as follows:
CREATE TRIGGER trigger1
AFTER UPDATE
ON x
FOR EACH ROW
WHEN old.sqlmodded IS NULL
BEGIN
UPDATE x
SET sqlmodded = '1';
END;
When I run an update statement to change a value of name or sname, the trigger kicks in but alters sqlmodded for all records in the table.
Here's code to reproduce:
CREATE TABLE "x"(
"NAME" Text,
"SNAME" Text,
"sqlmodded" Text );
CREATE TRIGGER "trigger1"
AFTER UPDATE
ON "x"
FOR EACH ROW
WHEN old.sqlmodded is null
BEGIN UPDATE x SET sqlmodded = '1'; END;
Now insert a few records:
INSERT INTO x
(
name
, sname
) VALUES
(
"Joe"
, "Bloggs"
)
;
INSERT INTO x
(
name
, sname
) VALUES
(
"Joline"
, "Bloggs"
)
;
Now run an update:
UPDATE x
SET
name = "Justine"
WHERE name = "Joline"
;
If you view the resulting two records both records will have had sqlmodded set to 1.
The trigger runs this command:
UPDATE x
SET sqlmodded = '1';
This statement indeed updates all rows in the table. This is how SQL works.
If you want to update only a specific row, you have to tell the database which row that would be:
UPDATE x
SET sqlmodded = '1'
WHERE rowid = NEW.rowid;
Here's the working code:
CREATE TRIGGER sqlmods
AFTER UPDATE
ON x
FOR EACH ROW
WHEN old.sqlmodded IS NULL
BEGIN
UPDATE x
SET sqlmodded = TRUE
WHERE rowid = NEW.rowid;
END;

equivalent to INSERT INTO TABLE SET in Oracle

I want to add data to table STATISTICS using INSERT statements.
I also want to move new counts to old counts and new date to old date as the new data comes in.
This is where it gets lil tricky because I don't know if there is such a thing as INSERT INTO table with SET in Oracle.
INSERT INTO STATISTICS
SET
MODEL = '&MY_MODEL',
NEW_COUNT =
(
SELECT COUNT(*)
FROM TABLE CLIENTS
),
NEW_DATE = SYSDATE,
OLD_COUNT = NEW_COUNT,
OLD_DATE = NEW_DATE,
PRNCT_CHANGE = ((NEW_COUNT) - (OLD_COUNT)) / (NEW_COUNT)*100
);
How do I accomplish this in Oracle?
This should upsert statistics, adding new ones as you go. It presumes a unique key on MODEL; if that's not true, then you'd have to do inserts as Angelina said, getting only the most recent row for a single MODEL entry.
MERGE INTO STATISTICS tgt
using (SELECT '&MY_MODEL' AS MODEL,
(SELECT COUNT(*) FROM CLIENTS) AS NEW_COUNT,
SYSDATE AS DATE_COUNT,
NULL AS OLD_COUNT,
NULL OLD_DATE,
NULL AS PRCNT_CHANGE
FROM DUAL) src
on (TGT.MODEL = SRC.MODEL)
WHEN MATCHED THEN UPDATE
SET TGT.NEW_COUNT = SRC.NEW_COUNT,
TGT.NEW_DATE = SRC.NEW_DATE,
TGT.OLD_COUNT = TGT.NEW_COUNT,
TGT.OLD_DATE = TGT.NEW_DATE,
TGT.PRCNT_CHG = 100 * (SRC.NEW_COUNT - TGT.NEW_COUNT) / (SRC.NEW_COUNT)
-- NEEDS DIV0/NULL CHECKING
WHEN NOT MATCHED THEN INSERT
(MODEL, NEW_COUNT, NEWDATE, OLD_COUNT, OLD_DATE, PRCNT_CHANGE)
VALUES
(src.MODEL, src.NEW_COUNT, src.NEWDATE, src.OLD_COUNT, src.OLD_DATE, src.PRCNT_CHANGE);
INSERT INTO STATISTICS(MODEL,NEW_COUNT,NEW_DATE,OLD_COUNT,OLD_DATE,PRNCT_CHANGE)
SELECT MODEL,
( SELECT COUNT(*)
FROM TABLE(USERS)
),
SYSDATE,
NEW_COUNT,
NEW_DATE,
(((NEW_COUNT) - (OLD_COUNT)) / (NEW_COUNT)*100)
FROM SEMANTIC.COUNT_STATISTICS
WHERE MODEL = '&MY_MODEL'
AND trunc(NEW_DATE) = trunc(NEW_DATE -1)
;

passing list of name/value pairs to stored procedure

I have a name/value pair in a List<T> and needing to find the best way to pass these to a stored procedure.
Id Name
1 abc
2 bbc
3 cnn
....
...
What is the best way to accomplish this?
One way to handle this in SQL Server 2005 (prior to the availability of table valued parameters) was to pass a delimited list and use a Split function. If you are using a two-column array, you would want to use two different delimiters:
Declare #Values varchar(max)
Set #Values = '1,abc|2,bbc|3,cnn'
With SplitItems As
(
Select S.Value As [Key]
, S2.Value
, Row_Number() Over ( Partition By S.Position Order By S2.Position ) As ElementNum
From dbo.Split(#Values,'|') As S
Outer Apply dbo.Split(S.Value, ',') As S2
)
Select [Key]
, Min( Case When S.ElementNum = 1 Then S.Value End ) As ListKey
, Min( Case When S.ElementNum = 2 Then S.Value End ) As ListValue
From SplitItems As S
Group By [Key]
Create Function [dbo].[Split]
(
#DelimitedList nvarchar(max)
, #Delimiter nvarchar(2) = ','
)
RETURNS TABLE
AS
RETURN
(
With CorrectedList As
(
Select Case When Left(#DelimitedList, Len(#Delimiter)) <> #Delimiter Then #Delimiter Else '' End
+ #DelimitedList
+ Case When Right(#DelimitedList, Len(#Delimiter)) <> #Delimiter Then #Delimiter Else '' End
As List
, Len(#Delimiter) As DelimiterLen
)
, Numbers As
(
Select Row_Number() Over ( Order By c1.object_id ) As Value
From sys.columns As c1
Cross Join sys.columns As c2
)
Select CharIndex(#Delimiter, CL.list, N.Value) + CL.DelimiterLen As Position
, Substring (
CL.List
, CharIndex(#Delimiter, CL.list, N.Value) + CL.DelimiterLen
, CharIndex(#Delimiter, CL.list, N.Value + 1)
- ( CharIndex(#Delimiter, CL.list, N.Value) + CL.DelimiterLen )
) As Value
From CorrectedList As CL
Cross Join Numbers As N
Where N.Value < Len(CL.List)
And Substring(CL.List, N.Value, CL.DelimiterLen) = #Delimiter
)
Another way to handle this without table-valued parameters is to pass Xml as an nvarchar(max):
Declare #Values nvarchar(max)
Set #Values = '<root><Item Key="1" Value="abc"/>
<Item Key="2" Value="bbc"/>
<Item Key="3" Value="cnn"/></root>'
Declare #docHandle int
exec sp_xml_preparedocument #docHandle output, #Values
Select *
From OpenXml(#docHandle, N'/root/Item', 1)
With( [Key] int, Value varchar(10) )
Take a look at Arrays and Lists in SQL Server 2008 to get some ideas
SQL Server 2008 also supports this multi row values syntax
create table #bla (id int, somename varchar(50))
insert #bla values(1,'test1'),(2,'Test2')
select * from #bla
i endup using foreach <insert>
This could done through three ways.
User Defined Table Type
Json Object Parsing
XML Parsing
I tried with the first option and passed a list of pairs in User Defined Table Type. This works for me. I am posting here, it might help someone else.
The first challenge for me was to pass the list of key value pair data structure and second to loop through the list and insert the record in a table.
Step 1 : Create a User Defined Table Type. I have created with a name 'TypeMetadata'. As it is custom type, I created two attributes of type nvarchar. You can create one of type integer and second of type nvarchar.
-- Type: metadata ---
IF EXISTS(SELECT * FROM SYS.TYPES WHERE NAME = 'TypeMetadata')
DROP TYPE TypeMetadata
GO
CREATE TYPE TypeMetadata AS TABLE (
mkey nvarchar (50),
mvalue nvarchar (50)
);
GO
Step 2 : Then I created a stored procedure with name 'createfiled'
-- Procedure: createtext --
CREATE PROCEDURE [dbo].[createfield]
#name nvarchar(50),
#text nvarchar(50),
#order int,
#type nvarchar(50),
#column_id int ,
#tid int,
#metadataList TypeMetadata readonly
AS
BEGIN
--loop through metadata and insert records --
DECLARE #mkey nvarchar(max);
DECLARE #mvalue nvarchar(max);
DECLARE mCursor CURSOR LOCAL FAST_FORWARD
FOR
SELECT mkey, mvalue
FROM #metadataList;
OPEN mCursor;
FETCH NEXT FROM mCursor INTO #mkey, #mvalue; -- Initial fetch attempt
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO template_field_metadata (name, value, template_field_id, isProperty) values (#mkey, #mvalue, 1, 0)
PRINT 'A new metadata created with id : ' + cast(SCOPE_IDENTITY() as nvarchar);
FETCH NEXT FROM mCursor INTO #mkey, #mvalue; -- Attempt to fetch next row from cursor
END;
CLOSE mCursor;
DEALLOCATE mCursor;
END
GO
Step 3: finally I executed the stored procedure like;
DECLARE #metadataToInsert TypeMetadata;
INSERT INTO #metadataToInsert VALUES ('value', 'callVariable2');
INSERT INTO #metadataToInsert VALUES ('maxlength', '30');
DECLARE #fid INT;
EXEC [dbo].[createfield] #name = 'prefagent', #text = 'Pref Agent', #order = 1 , #type= 'prefagent', #column_id = 0, #tid = 49, #metadataList =#metadataToInsert;

Resources