MySQL INSERT INTO table SELECT FROM another_table, inside a PROCEDURE - mysql
I have this MySQL procedure, that makes some loops into 2 tables, prepares the Data into tblResults and then insert all data (if no errors) into a huge table after delete all rows found between 2 dates.
The problem is that after the procedure finishes to run, I receive this warning:
Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statements writing to a table with an auto-increment column after selecting from another table are unsafe because the order in which rows are retrieved determines what (if any) rows will be written. This order cannot be predicted and may differ on master and the slave.
and as a result, if I have 250 distinct rows into tblResults table, the procedure insert 250 identical rows into final table. (usualy first or last row found in tblResults, multiplied by number of records from tblResults).
The SQL code look like this:
BEGIN
-- DECLARE bDone INT;
DECLARE CustomerId INT;
DECLARE LocationId INT;
DECLARE ContractId INT;
DECLARE DatePeriod DATE;
DECLARE SerialWeight DOUBLE;
DECLARE Serial VARCHAR(150);
DECLARE EnergyZone VARCHAR(5);
DECLARE ConsDay DATE;
DECLARE T0 DOUBLE;
DECLARE T1 DOUBLE;
DECLARE T2 DOUBLE;
DECLARE T3 DOUBLE;
DECLARE T4 DOUBLE;
DECLARE T5 DOUBLE;
DECLARE T6 DOUBLE;
DECLARE T7 DOUBLE;
DECLARE T8 DOUBLE;
DECLARE T9 DOUBLE;
DECLARE T10 DOUBLE;
DECLARE T11 DOUBLE;
DECLARE T12 DOUBLE;
DECLARE T13 DOUBLE;
DECLARE T14 DOUBLE;
DECLARE T15 DOUBLE;
DECLARE T16 DOUBLE;
DECLARE T17 DOUBLE;
DECLARE T18 DOUBLE;
DECLARE T19 DOUBLE;
DECLARE T20 DOUBLE;
DECLARE T21 DOUBLE;
DECLARE T22 DOUBLE;
DECLARE T23 DOUBLE;
DECLARE QtyEstimated DECIMAL(20,4);
DECLARE QtyMeasured DECIMAL(20,4);
DECLARE POD VARCHAR(50);
DECLARE Quantity DECIMAL(20,4);
DECLARE LocationCode VARCHAR(50);
DECLARE rCustomerId INT;
DECLARE rLocationId INT;
DECLARE rContractId INT;
DECLARE rDate DATE;
DECLARE rTime INT;
DECLARE rQtyEstimated DECIMAL(20,4);
DECLARE rQtyPredicted DECIMAL(20,4);
DECLARE rQtyMeasured DOUBLE;
DECLARE rCreateUser INT;
DECLARE rUpdateUser INT;
DECLARE rFirmaId INT;
DECLARE curs CURSOR FOR
select
ec.CustomerId,
ec.LocationId,
ec.Id as ContractId,
els.Date as DatePeriod,
els.SerialWeight,
ets.Serial,
ets.EnergyZone,
ets.Date as ConsDay,
ets.T0,
ets.T1,
ets.T2,
ets.T3,
ets.T4,
ets.T5,
ets.T6,
ets.T7,
ets.T8,
ets.T9,
ets.T10,
ets.T11,
ets.T12,
ets.T13,
ets.T14,
ets.T15,
ets.T16,
ets.T17,
ets.T18,
ets.T19,
ets.T20,
ets.T21,
ets.T22,
ets.T23,
CASE substr(els.Date, 6, 2)
WHEN '01' THEN ec.Estimated1
WHEN '02' THEN ec.Estimated2
WHEN '03' THEN ec.Estimated3
WHEN '04' THEN ec.Estimated4
WHEN '05' THEN ec.Estimated5
WHEN '06' THEN ec.Estimated6
WHEN '07' THEN ec.Estimated7
WHEN '08' THEN ec.Estimated8
WHEN '09' THEN ec.Estimated9
WHEN '10' THEN ec.Estimated10
WHEN '11' THEN ec.Estimated11
WHEN '12' THEN ec.Estimated12
END as QtyEstimated
from EnergyLocationSeries els
left join EnergyTimeSeries ets ON ets.Serial = els.Serial and concat(substr(ets.Date, 1, 7), '-01') = els.Date
left join EnergyLocation el ON el.Code2 = els.LocationCode
left join EnergyContract ec ON (el.Id = ec.LocationId AND el.Codep = '') OR (ec.LocationId = (SELECT max(Id) FROM EnergyLocation WHERE Code2 = el.Codep) AND Codep !='') -- AND ec.`Status` != 'Reziliat'
where els.Date = MTH and els.EnergyZone = ZONE
order by ets.Date ASC LIMIT 10;
DECLARE pods_cursor CURSOR FOR
SELECT els.LocationCode, els.Quantity
FROM EnergyLocation el
RIGHT JOIN EnergyLocationSeries els ON els.LocationCode = el.Code2 OR els.LocationCode = el.Codep
LEFT JOIN EnergyContract ec on ec.LocationId = el.Id
WHERE el.Code2 IS NULL;
DECLARE result CURSOR FOR
SELECT `CustomerId`, `LocationId`, `ContractId`, `Date`, `Time`, `QtyEstimated`, `QtyPredicted`, `QtyMeasured`, `CreateUser`, `UpdateUser`, `FirmaId`
FROM tblResults ORDER BY CustomerId, ContractId ASC;
DROP TABLE IF EXISTS tblResultsErrors;
CREATE TABLE IF NOT EXISTS tblResultsErrors (
`POD` INT(11) NULL DEFAULT NULL,
`QtyMeasured` DECIMAL(20,4) NULL DEFAULT NULL
);
DROP TABLE IF EXISTS tblResults;
CREATE TABLE IF NOT EXISTS tblResults (
`CustomerId` INT(11) NULL DEFAULT NULL,
`LocationId` INT(11) NULL DEFAULT NULL,
`ContractId` INT(11) NULL DEFAULT NULL,
`Date` DATE NULL DEFAULT NULL,
`Time` SMALLINT(6) NULL DEFAULT NULL,
`QtyEstimated` DECIMAL(20,4) NULL DEFAULT NULL,
`QtyPredicted` DECIMAL(20,4) NULL DEFAULT NULL,
`QtyMeasured` DOUBLE NULL DEFAULT NULL,
`CreateUser` VARCHAR(32) NULL DEFAULT NULL,
`UpdateUser` VARCHAR(32) NULL DEFAULT NULL,
`FirmaId` INT(11) NULL DEFAULT NULL
);
OPEN curs;
BEGIN
DECLARE bDone INT;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1;
SET bDone = 0;
REPEAT
FETCH curs INTO
CustomerId,
LocationId,
ContractId,
DatePeriod,
SerialWeight,
Serial,
EnergyZone,
ConsDay,
T0,
T1,
T2,
T3,
T4,
T5,
T6,
T7,
T8,
T9,
T10,
T11,
T12,
T13,
T14,
T15,
T16,
T17,
T18,
T19,
T20,
T21,
T22,
T23,
QtyEstimated;
IF bDone = 0 THEN
INSERT INTO tblResults VALUES
(CustomerId,LocationId,ContractId,ConsDay,1,QtyEstimated,0,(T0 * (SerialWeight / 100)),'root','root',0),
(CustomerId,LocationId,ContractId,ConsDay,2,QtyEstimated,0,(T1 * (SerialWeight / 100)),'root','root',0),
(CustomerId,LocationId,ContractId,ConsDay,3,QtyEstimated,0,(T2 * (SerialWeight / 100)),'root','root',0),
(CustomerId,LocationId,ContractId,ConsDay,4,QtyEstimated,0,(T3 * (SerialWeight / 100)),'root','root',0),
(CustomerId,LocationId,ContractId,ConsDay,5,QtyEstimated,0,(T4 * (SerialWeight / 100)),'root','root',0),
(CustomerId,LocationId,ContractId,ConsDay,6,QtyEstimated,0,(T5 * (SerialWeight / 100)),'root','root',0),
(CustomerId,LocationId,ContractId,ConsDay,7,QtyEstimated,0,(T6 * (SerialWeight / 100)),'root','root',0),
(CustomerId,LocationId,ContractId,ConsDay,8,QtyEstimated,0,(T7 * (SerialWeight / 100)),'root','root',0),
(CustomerId,LocationId,ContractId,ConsDay,9,QtyEstimated,0,(T8 * (SerialWeight / 100)),'root','root',0),
(CustomerId,LocationId,ContractId,ConsDay,10,QtyEstimated,0,(T9 * (SerialWeight / 100)),'root','root',0),
(CustomerId,LocationId,ContractId,ConsDay,11,QtyEstimated,0,(T10 * (SerialWeight / 100)),'root','root',0),
(CustomerId,LocationId,ContractId,ConsDay,12,QtyEstimated,0,(T11 * (SerialWeight / 100)),'root','root',0),
(CustomerId,LocationId,ContractId,ConsDay,13,QtyEstimated,0,(T12 * (SerialWeight / 100)),'root','root',0),
(CustomerId,LocationId,ContractId,ConsDay,14,QtyEstimated,0,(T13 * (SerialWeight / 100)),'root','root',0),
(CustomerId,LocationId,ContractId,ConsDay,15,QtyEstimated,0,(T14 * (SerialWeight / 100)),'root','root',0),
(CustomerId,LocationId,ContractId,ConsDay,16,QtyEstimated,0,(T15 * (SerialWeight / 100)),'root','root',0),
(CustomerId,LocationId,ContractId,ConsDay,17,QtyEstimated,0,(T16 * (SerialWeight / 100)),'root','root',0),
(CustomerId,LocationId,ContractId,ConsDay,18,QtyEstimated,0,(T17 * (SerialWeight / 100)),'root','root',0),
(CustomerId,LocationId,ContractId,ConsDay,19,QtyEstimated,0,(T18 * (SerialWeight / 100)),'root','root',0),
(CustomerId,LocationId,ContractId,ConsDay,20,QtyEstimated,0,(T19 * (SerialWeight / 100)),'root','root',0),
(CustomerId,LocationId,ContractId,ConsDay,21,QtyEstimated,0,(T20 * (SerialWeight / 100)),'root','root',0),
(CustomerId,LocationId,ContractId,ConsDay,22,QtyEstimated,0,(T21 * (SerialWeight / 100)),'root','root',0),
(CustomerId,LocationId,ContractId,ConsDay,23,QtyEstimated,0,(T22 * (SerialWeight / 100)),'root','root',0),
(CustomerId,LocationId,ContractId,ConsDay,24,QtyEstimated,0,(T23 * (SerialWeight / 100)),'root','root',0);
END IF;
UNTIL bDone END REPEAT;
END;
CLOSE curs;
OPEN pods_cursor;
BEGIN
DECLARE bDone INT;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1;
SET bDone = 0;
REPEAT
FETCH pods_cursor INTO POD, QtyMeasured;
IF bDone = 0 THEN
INSERT INTO tblResultsErrors VALUES
(LocationCode, Quantity);
END IF;
UNTIL bDone END REPEAT;
END;
CLOSE pods_cursor;
IF NOT EXISTS ( SELECT * FROM tblResultsErrors ) THEN
BEGIN
DELETE FROM EnergyIbdRecord WHERE Date BETWEEN MTH AND LAST_DAY(MTH);
OPEN result;
BEGIN
DECLARE bDone INT;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = 1;
SET bDone = 0;
REPEAT
FETCH result INTO rCustomerId,rLocationId,rContractId,rDate,rTime,rQtyEstimated,rQtyPredicted,rQtyMeasured,rCreateUser,rUpdateUser,rFirmaId;
IF bDone = 0 THEN
INSERT INTO EnergyIbdRecord (`CustomerId`, `LocationId`, `ContractId`, `Date`, `Time`, `QtyEstimated`, `QtyPredicted`, `QtyMeasured`, `CreateUser`, `UpdateUser`, `FirmaId`)
VALUES (rCustomerId,rLocationId,rContractId,rDate,rTime,rQtyEstimated,rQtyPredicted,rQtyMeasured,rCreateUser,rUpdateUser,rFirmaId);
END IF;
UNTIL bDone END REPEAT;
END;
CLOSE result;
END;
ELSE
BEGIN
SELECT * FROM tblResultsErrors;
END;
END IF;
END
Any suggestion to get rid of inserting what tblResults contains?
Maybe there is necessary to run 2 separated procedures? Would be this an approach?
Wherever possible, avoid using CURSORs. SQL is designed to do things in bulk, not one row at a time.
Study constructs like
INSERT INTO ... SELECT ...;
CREATE TABLE ... SELECT ...;
For example, pods_cursor can probably be eliminated via:
INSERT INTO tblResultsErrors
(POD, QtyMeasured)
SELECT els.LocationCode, els.Quantity
FROM EnergyLocation el
RIGHT JOIN EnergyLocationSeries els
ON els.LocationCode = el.Code2 OR els.LocationCode = el.Codep
LEFT JOIN EnergyContract ec
on ec.LocationId = el.Id
WHERE el.Code2 IS NULL;
(Ouch. Mixing RIGHT and LEFT makes my head spin like an owl's.)
Using OR in ON sounds very inefficient. What is the intent?
Related
Insert multiple entries into table using procedure in MySQL
I have created a procedure in mysql to insert into table as below. DELIMITER $$ CREATE PROCEDURE createOrderPR ( IN iv_productID INT, IN iv_orderDate DATE, IN iv_orderTime TIME, IN iv_shopID INT, IN iv_mobileNo varchar(10), IN iv_quantity smallint, IN iv_total float(10,2), IN iv_discount float(10,2), IN iv_taxable float(10,2), IN iv_CGST float(10,2), IN iv_SGST float(10,2) ) BEGIN DECLARE availQty smallint default 0; SELECT stockCount INTO availQty FROM product WHERE productID = iv_productID; SET availQty = availQty - iv_quantity; start transaction; set autocommit =0; INSERT INTO orders(orderNo,productID,orderDate,orderTime,shopID,mobileNo,quantity,total,discount,taxable,CGST,SGST,orderStatus,deletionMark) VALUES( null,iv_productID,iv_orderDate,iv_orderTime,iv_shopID,iv_mobileNo,iv_quantity,iv_total,iv_discount,iv_taxable,iv_CGST,iv_SGST,'Open',null); UPDATE product SET stockCount = availQty WHERE productID = iv_productID; COMMIT; SELECT MAX(orderNo) FROM orders WHERE shopID = shopID AND mobileNo = mobileNo; END $$ Currently it will only allow single record.now I need to insert multiple records in that case how to define the IN parameter of the procedure. Please suggest.
Solved the issue by using the JSON IN parameter these are the sample code (Note:new column added in the table rest all no change) DELIMITER $$ CREATE PROCEDURE createOrderMulti ( IN orderJson JSON, IN length INT ) BEGIN -- Date Declaration DECLARE availQty smallint default 0; DECLARE iv_productID INT; DECLARE iv_orderDate DATE; DECLARE iv_orderTime TIME; DECLARE iv_shopID INT; DECLARE iv_mobileNo varchar(10); DECLARE iv_quantity smallint; DECLARE iv_total float(10,2); DECLARE iv_discount float(10,2); DECLARE iv_taxable float(10,2); DECLARE iv_CGST float(10,2); DECLARE iv_SGST float(10,2); DECLARE counter smallint default 0; DECLARE item INT; DECLARE orderNo INT DEFAULT null; start transaction; set autocommit = 0; WHILE counter < length DO -- Extract the JSON value SELECT JSON_VALUE(orderJson, CONCAT('$[', counter, '].productID')) INTO iv_productID; SELECT JSON_VALUE(orderJson, CONCAT('$[', counter, '].orderDate')) INTO iv_orderDate; SELECT JSON_VALUE(orderJson, CONCAT('$[', counter, '].orderTime')) INTO iv_orderTime; SELECT JSON_VALUE(orderJson, CONCAT('$[', counter, '].shopID')) INTO iv_shopID; SELECT JSON_VALUE(orderJson, CONCAT('$[', counter, '].mobileNo')) INTO iv_mobileNo; SELECT JSON_VALUE(orderJson, CONCAT('$[', counter, '].quantity')) INTO iv_quantity; SELECT JSON_VALUE(orderJson, CONCAT('$[', counter, '].total')) INTO iv_total; SELECT JSON_VALUE(orderJson, CONCAT('$[', counter, '].discount')) INTO iv_discount; SELECT JSON_VALUE(orderJson, CONCAT('$[', counter, '].taxable')) INTO iv_taxable; SELECT JSON_VALUE(orderJson, CONCAT('$[', counter, '].CGST')) INTO iv_CGST; SELECT JSON_VALUE(orderJson, CONCAT('$[', counter, '].SGST')) INTO iv_SGST; SELECT stockCount INTO availQty FROM product WHERE productID = iv_productID; SET availQty = availQty - iv_quantity; SET item = counter + 1; INSERT INTO orders(orderNo,item,productID,orderDate,orderTime,shopID,mobileNo,quantity,total,discount,taxable,CGST,SGST,orderStatus,deletionMark) VALUES( orderNo,item,iv_productID,iv_orderDate,iv_orderTime,iv_shopID,iv_mobileNo,iv_quantity,iv_total,iv_discount,iv_taxable,iv_CGST,iv_SGST,'Open',null); SET orderNo = LAST_INSERT_ID(); UPDATE product SET stockCount = availQty WHERE productID = iv_productID; SET counter = counter + 1; END WHILE; COMMIT; --SELECT MAX(orderNo) FROM orders WHERE shopID = shopID AND mobileNo = mobileNo; SELECT orderNo as orderNo; END $$
MySQL stores procedure cannot add values
DELIMITER $$ CREATE PROCEDURE GetCustomerLevel(p_barcode int) BEGIN DECLARE q1 int; DECLARE q2 int; DECLARE q3 int; DECLARE total int; SET total :=0; SELECT sum(adjustment_quantity) INTO q1 FROM adjustment_inventory WHERE item_barcode = p_barcode group by adjustment_quantity; SELECT sum(opening_stock) INTO q2 FROM openingstock WHERE item_barcode = p_barcode group by opening_stock; SELECT sum(inwardquantity) INTO q3 FROM inwardmaster WHERE item_barcode = p_barcode group by inwardquantity; IF q1 IS NULL THEN SET q1 := 0; END IF; IF q2 IS NULL THEN SET q2 := 0; END IF; IF q3 IS NULL THEN SET q3 := 0; END IF; SELECT q1; SELECT q2; SELECT q3; SELECT q1+q2+q3; END$$ It's return wrong answer everytime. For example q1=100 q2=200 q3=100 its return 100
you dont need to use stored procedure for this set #barcode = '1234'; select coalesce(( SELECT sum(coalesce(adjustment_quantity,0)) FROM adjustment_inventory WHERE item_barcode = #p_barcode ),0) + coalesce(( SELECT sum(opening_stock) FROM openingstock WHERE item_barcode = #p_barcode ), 0) + coalesce(( SELECT sum(coalesce(inwardquantity,0)) FROM inwardmaster WHERE item_barcode = #p_barcode ), 0) res From Dual ; If you really want to use procedure then check the code below DELIMITER $$ CREATE PROCEDURE GetCustomerLevel(p_barcode int) BEGIN DECLARE q1 int; DECLARE q2 int; DECLARE q3 int; DECLARE total int; SET total :=0; SELECT coalesce(sum(adjustment_quantity), 0) INTO q1 FROM adjustment_inventory WHERE item_barcode = p_barcode; SELECT coalesce(sum(opening_stock), 0) INTO q2 FROM openingstockWHERE item_barcode = p_barcode; SELECT coalesce(sum(inwardquantity), 0) INTO q3 FROM inwardmaster WHERE item_barcode = p_barcode; SELECT q1; SELECT q2; SELECT q3; set total = q1+q2+q3; SELECT total; END$$
Loop based on parameter value
I need to create a temporary table that is populated based on two parameters: declare #Start date = '01/01/2015' declare #End date = '12/31/2015' The temporary table should have a column that will capture YYYYMM for all the years and month that are between #Start and #End parameter. Here's what I have so far. I want to stop it at 201412 and then start again at 201501. Instead, this loop keeps going in increment of plus 1 (I do not want to see 201413..so on): declare #Start date = '01/01/2014' declare #End date = '12/31/2015' declare #monthstart as int declare #monthend as int declare #increment as int set #monthstart = (SELECT LEFT(CONVERT(varchar, #Start,112),6)) set #monthend = (SELECT LEFT(CONVERT(varchar, #End,112),6)) create table #datetemp (RelevantYYYYMM int) insert into #datetemp values (#monthstart) set #increment = #monthstart While #increment < #monthend BEGIN set #increment = (select Max(RelevantYYYYMM) + 1 from #datetemp) insert into #datetemp values (#increment) set #increment = (select Max(RelevantYYYYMM) from #datetemp) IF (select Max(RelevantYYYYMM) from #datetemp) > #monthend Break else continue END select * from #datetemp
You can use tally table and avoid loop: CREATE TABLE #datetemp (RelevantYYYYMM INT); DECLARE #Start DATE = '01/01/2015', #End DATE = '12/31/2015'; WITH tally_table AS ( SELECT TOP 1000 rn = ROW_NUMBER() OVER(ORDER BY name) - 1 FROM master..spt_values ) INSERT INTO #datetemp(RelevantYYYYMM) SELECT LEFT(CONVERT(varchar, DATEADD(month, rn, #Start),112),6) FROM tally_table WHERE YEAR(DATEADD(month, rn, #Start)) <= YEAR(#End) AND MONTH(DATEADD(month, rn, #Start)) <= MONTH(#End) SELECT * FROM #datetemp; LiveDemo
Cursor in stored procedure of mysql not working
I am using following stored procedure and calling a cursor inside it but it is returning me zero data fetched or processed what is wrong in the procedure ? DELIMITER $$ CREATE DEFINER=`root`#`localhost` PROCEDURE `sp_ProcessData`( DummyDate datetime ) BEGIN DECLARE MONTH BIGINT; DECLARE YEAR BIGINT; declare LBrCode VARCHAR(100); declare EntryDate datetime; declare VcrAcctId char(32); declare DrCr VARCHAR(100); declare FcyTrnAmt VARCHAR(100); DECLARE CustName char(50); DECLARE CreditAmount decimal(18,2); DECLARE DebitAmount decimal(18,2); DECLARE BatchCd char(15); DECLARE SetNo BIGINT; DECLARE ScrollNo BIGINT; DECLARE BookType char(10); DECLARE ActualAcctId varchar(50); DECLARE ActualBrCode varchar(50); DECLARE ActualBookType varchar(50); declare curProcessAMLData cursor for select distinct * from DummyTable WHERE EntryDate = DummyDate AND (ActualBookType = 'XX'); open curProcessAMLData; fetch next from curProcessAMLData into LBrCode,EntryDate,VcrAcctId,DrCr,FcyTrnAmt,BatchCd,SetNo,ScrollNo,BookType,ActualAcctId,ActualBrCode,ActualBookType; while fetch_status = 0 DO SET MONTH = MONTH(DummyDate); SET YEAR = MONTH(DummyDate); IF(DrCr = 'C') THEN SET CreditAmount = FcyTrnAmt; IF NOT EXISTS (SELECT * FROM Master WHERE BranchCode = ActualBrCode AND AccNo = ActualAcctId AND TransMonth = MONTH and TransYear = YEAR) THEN INSERT INTO Master ( TransDate, BranchCode, AccNo, Credit, TransMonth, TransYear ) SELECT EntryDate, ActualBrCode, ActualAcctId, CreditAmount, MONTH, YEAR END; ELSE UPDATE Master SET Credit = IFNULL(Credit,0) + CreditAmount WHERE BranchCode = ActualBrCode AND AccNo = ActualAcctId AND MONTH(TransDate) = MONTH AND YEAR(TransDate) = YEAR; END IF; ELSE SET DebitAmount = FcyTrnAmt; IF NOT EXISTS (SELECT * FROM Master WHERE BranchCode = ActualBrCode AND AccNo = ActualAcctId AND TransMonth = MONTH and TransYear = YEAR) THEN INSERT INTO Master ( TransDate, BranchCode, AccNo, Debit, TransMonth, TransYear ) SELECT EntryDate, ActualBrCode, ActualAcctId, DebitAmount, MONTH, YEAR END; ELSE UPDATE Master SET Debit = IFNULL(Debit,0) + DebitAmount WHERE BranchCode = #ActualBrCode AND AccNo = ActualAcctId AND MONTH(TransDate) = MONTH AND YEAR(TransDate) = YEAR; END IF; END IF; SET FcyTrnAmt = 0 ; END WHILE; fetch next from curProcessAMLData into LBrCode,EntryDate,VcrAcctId,DrCr,FcyTrnAmt,BatchCd,SetNo,ScrollNo,BookType,ActualAcctId,ActualBrCode,ActualBookType; CLOSE curProcessAMLData; END What changes will i have to make to make it working ?
Need help to inserting 100 records in loop, continue where it stop from and break once the records are completed.
Need help to inserting 100 records in loop, continue where it stop from and break once the records are completed. Alter PROCEDURE ETL.ETLPurge #PurgeYear INT AS BEGIN DECLARE #BatchId INT = (SELECT BatchId FROM Tracker) declare #Count int declare #batchsize int set #batchsize = 100 --set #Count = ##rowcount SELECT DISTINCT IDENTITY(INT,1,1) AS ID, MC.ID INTO #tmp FROM Contact MC JOIN Extract CE ON MC.ExtractID = CE.ExtractID LEFT JOIN Application A ON MC.ID = A.ID WHERE CE.Year < #PurgeYear AND A.ApplicationId IS NULL --declare #counter bigint --set #counter = 1 --while #counter < 500 --Begin --while 1 = 1 --begin Create NONCLUSTERED INDEX nix_ID on #tmp(ID) --while 1=1 --begin INSERT --Top (#batchsize) INTO Table1 (Values ………) ( SELECT top (#batchsize) #BatchID, Values ……..) FROM Contact MC inner join #tmp TK on MC.ContactID = TK.ContactID --where TK.ID between #batchsize and #ctr + 1 ) if ##ROWCOUNT < #batchsize break end -- --continue -- --if ##ROWCOUNT = 0 -- Break end --end --number of rows inserted should equal number of rows deleted.
Ok. Here is my sample. What happened to me is that my dba "team" .. screwed up setting Replication for us. So .. over the weekend, working like dogs.... we had to write some code to "pull over" records from a source database to a destination database, where the structure of the database was the same. We had to fake-out some replication. We had 8,000,000 rows, and we would pull them over 10,000 at a time. Below, I have about 1000 rows, and set the "number of rows to pull at one time" to 333. I also put a #MaximumLoopCounter as a "just in case". I didn't want to accidentally create a endless loop. The sample below bases its "while" logic on "while exists (some records on the source-database-table that are not in the destination-database-table)"...keep grabbing those records. I'm trying to help you answer your question. In our case, we finally got replication working correctly, and we were able to abandon these scripts. It was NOT a fun weekend. /* SETUP */ if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[CodeCategorySourceTable]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) BEGIN DROP TABLE [dbo].[CodeCategorySourceTable] END GO CREATE TABLE [dbo].[CodeCategorySourceTable] ( CodeCategoryUUID [uniqueidentifier] not null default NEWSEQUENTIALID() , CodeCategoryName varchar(64) not null ) GO ALTER TABLE [dbo].[CodeCategorySourceTable] ADD CONSTRAINT PK_CodeCategorySourceTable_CodeCategoryUUID PRIMARY KEY CLUSTERED (CodeCategoryUUID) GO ALTER TABLE [dbo].[CodeCategorySourceTable] ADD CONSTRAINT CK_CodeCategorySourceTable_CodeCategoryName_UNIQUE UNIQUE (CodeCategoryName) GO if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[CodeCategoryDestinationTable]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) BEGIN DROP TABLE [dbo].[CodeCategoryDestinationTable] END GO CREATE TABLE [dbo].[CodeCategoryDestinationTable] ( CodeCategoryUUID [uniqueidentifier] not null default NEWSEQUENTIALID() , CodeCategoryName varchar(64) not null ) GO ALTER TABLE [dbo].[CodeCategoryDestinationTable] ADD CONSTRAINT PK_CodeCategoryDestinationTable_CodeCategoryUUID PRIMARY KEY CLUSTERED (CodeCategoryUUID) GO ALTER TABLE [dbo].[CodeCategoryDestinationTable] ADD CONSTRAINT CK_CodeCategoryDestinationTable_CodeCategoryName_UNIQUE UNIQUE (CodeCategoryName) GO declare #AlreadyExistingCodeCategoryUUID01 uniqueidentifier declare #AlreadyExistingCodeCategoryUUID03 uniqueidentifier declare #AlreadyExistingCodeCategoryUUID02 uniqueidentifier declare #AlreadyExistingOldCodeCategoryName01 varchar(64) declare #AlreadyExistingOldCodeCategoryName02 varchar(64) declare #AlreadyExistingOldCodeCategoryName03 varchar(64) declare #AlreadyExistingNewCodeCategoryName01 varchar(64) declare #AlreadyExistingNewCodeCategoryName02 varchar(64) declare #AlreadyExistingNewCodeCategoryName03 varchar(64) select #AlreadyExistingCodeCategoryUUID01 = NEWID(), #AlreadyExistingCodeCategoryUUID02 = NEWID(), #AlreadyExistingCodeCategoryUUID03 = NEWID() select #AlreadyExistingNewCodeCategoryName01 = 'NewOne', #AlreadyExistingNewCodeCategoryName02 = 'NewTwo', #AlreadyExistingNewCodeCategoryName03 = 'NewThree' select #AlreadyExistingOldCodeCategoryName01 = 'OldOne', #AlreadyExistingOldCodeCategoryName02 = 'OldTwo', #AlreadyExistingOldCodeCategoryName03 = 'OldThree' Insert Into [dbo].[CodeCategorySourceTable] ( CodeCategoryUUID , CodeCategoryName ) Select top 1000 NEWID() , convert(varchar(40), NEWID()) + 'Name' from dbo.sysobjects so1 cross join dbo.sysobjects so2 Insert Into [dbo].[CodeCategorySourceTable] ( CodeCategoryUUID , CodeCategoryName ) select #AlreadyExistingCodeCategoryUUID01, #AlreadyExistingNewCodeCategoryName01 UNION ALL select #AlreadyExistingCodeCategoryUUID02, #AlreadyExistingNewCodeCategoryName02 UNION ALL select #AlreadyExistingCodeCategoryUUID03, #AlreadyExistingNewCodeCategoryName03 select count(*) from [dbo].[CodeCategorySourceTable] as CodeCategorySourceTableCOUNT Insert Into [dbo].[CodeCategoryDestinationTable] ( CodeCategoryUUID , CodeCategoryName ) select #AlreadyExistingCodeCategoryUUID01, #AlreadyExistingOldCodeCategoryName01 UNION ALL select #AlreadyExistingCodeCategoryUUID02, #AlreadyExistingOldCodeCategoryName02 UNION ALL select #AlreadyExistingCodeCategoryUUID03, #AlreadyExistingOldCodeCategoryName03 select count(*) from [dbo].[CodeCategoryDestinationTable] as CodeCategoryDestinationTableCOUNT /* USP */ print '[uspCodeCategoryReplicateReplacer]' go IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[uspCodeCategoryReplicateReplacer]') AND type in (N'P', N'PC')) DROP PROCEDURE [dbo].[uspCodeCategoryReplicateReplacer] Go /* declare #numberRowsAffected int declare #ErrorNumber int exec [dbo].[uspCodeCategoryReplicateReplacer] #numberRowsAffected output , #ErrorNumber output print #numberRowsAffected print #ErrorNumber print '' */ CREATE PROCEDURE [dbo].[uspCodeCategoryReplicateReplacer] ( #numberRowsAffected int output , #ErrorNumber int output ) AS SET NOCOUNT ON select #ErrorNumber = 0 declare #ErrorTracker int declare #insertRowCount int declare #updateRowCount int select #insertRowCount = 0 select #updateRowCount = 0 declare #CurrentInsertCount int declare #ManualReplicationRowCount int select #ManualReplicationRowCount = 333 declare #MaximumLoopCounter int select #MaximumLoopCounter = 10000 while (#MaximumLoopCounter > 0) and exists ( Select TOP 1 null from [dbo].[CodeCategorySourceTable] sourceTable with (nolock) where not exists ( select null from [dbo].[CodeCategoryDestinationTable] destinationTable with (nolock) Where destinationTable.CodeCategoryUUID = sourceTable.CodeCategoryUUID ) ) BEGIN select #MaximumLoopCounter = #MaximumLoopCounter - 1 /* DELETE FROM [dbo].[CodeCategoryDestinationTable] */ SET NOCOUNT OFF Insert into [dbo].[CodeCategoryDestinationTable] ( CodeCategoryUUID, CodeCategoryName ) Select TOP (#ManualReplicationRowCount) CodeCategoryUUID, CodeCategoryName from [dbo].[CodeCategorySourceTable] sourceTable with (nolock) where not exists ( select null from [dbo].[CodeCategoryDestinationTable] destinationTable with (nolock) Where destinationTable.CodeCategoryUUID = sourceTable.CodeCategoryUUID ) SELECT #CurrentInsertCount = ##ROWCOUNT , #ErrorTracker = ##ERROR select #insertRowCount = #insertRowCount + #CurrentInsertCount if #ErrorTracker <> 0 BEGIN select #ErrorNumber = #ErrorTracker select #MaximumLoopCounter = 0 /*Bail Out !!!*/ END SET NOCOUNT ON END /*End While Loop*/ print '/Before Look [dbo].[CodeCategoryDestinationTable] */' select * from [dbo].[CodeCategoryDestinationTable] SET NOCOUNT OFF /* A little extra. Update any non-surrogate-key values... We did not do this, but I leave it here as for kicks */ Update [dbo].[CodeCategoryDestinationTable] Set /*CodeCategoryUUID = vart.CodeCategoryUUID,*/ CodeCategoryName = sourceTable.CodeCategoryName From [dbo].[CodeCategoryDestinationTable] destinationTable, [dbo].[CodeCategorySourceTable] sourceTable Where /*Relationship*/ destinationTable.CodeCategoryUUID = sourceTable.CodeCategoryUUID /*Filter*/ and destinationTable.CodeCategoryName <> sourceTable.CodeCategoryName SELECT #updateRowCount = ##ROWCOUNT SET NOCOUNT ON print '/After Look [dbo].[CodeCategoryDestinationTable] */' select * from [dbo].[CodeCategoryDestinationTable] print '/#insertRowCount COUNT/' print #insertRowCount print '-------------------------' print '/#updateRowCount COUNT/' print #updateRowCount print '-------------------------' SELECT #numberRowsAffected = #insertRowCount + #updateRowCount print '/ [dbo].[CodeCategoryDestinationTable] COUNT/' print #numberRowsAffected print '-------------------------' SET NOCOUNT OFF GO /*GRANT EXECUTE ON dbo.uspCodeCategoryReplicateReplacer TO $(DBUSERNAME)*/ GO /* Improvement , encapsulate the ManualReplicationRowCount "getter" so it can be changed in one place */ IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[uspInternalSettingGetManualReplicationRowCount]') AND type in (N'P', N'PC')) DROP PROCEDURE [dbo].[uspInternalSettingGetManualReplicationRowCount] GO /* --START TEST declare #returnCode int declare #ManualReplicationRowCount int EXEC #returnCode = dbo.uspInternalSettingGetManualReplicationRowCount #ManualReplicationRowCount output print #ManualReplicationRowCount print '/#returnCode/' print #returnCode */ CREATE PROCEDURE [dbo].[uspInternalSettingGetManualReplicationRowCount] ( #ManualReplicationRowCount int output --return ) AS SET NOCOUNT ON select #ManualReplicationRowCount = 333 SET NOCOUNT OFF GO