sp_send_dbmail stuck in loop sending hundreds of emails - sql-server-2008

I have a trigger set up to insert into a table and then want to have a broker job scheduled to send emails from said table. I have the trigger working and I thought I had the SP to send emails working right but my loop gets stuck and sends hundreds of emails before I cancel the SP. Any thoughts on what I've done wrong? I'm using BatchEmailID as the flag to know what needs to be sent and what doesn't where '0' = it hasn't been sent and needs to go and '1' = it has been sent so ignore.
Create Table:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[tb_BatchEmail](
[BatchEmailID] [bit] NULL,
[To] [varchar](50) NULL,
[Body] [varchar](255) NULL,
[Subject] [varchar](20) NULL,
[Profile] [varchar](50) NULL,
[OrderID] [varchar](25) NULL,
[OrderDateTime] [datetime] NULL,
[SentDateTime] [datetime] NULL
) ON [PRIMARY]
GO
insert values:
INSERT INTO tb_BatchEmail
VALUES (
'0'
,'someemail#address.com'
,'msg body'
,'Test Subject'
,'dbmail profile'
,'123456.001'
,'6/4/2015'
,NULL
),
(
'0'
,'someemail#address.com'
,'msg body'
,'Test Subject'
,'dbmail profile'
,'123456.002'
,'6/4/2015'
,NULL
)
sp_send_dbmail:
while 1=1
begin
declare #BatchEmailID bit
declare #To varchar (25)
declare #Body varchar (250)
declare #Subject varchar (25)
declare #ProfileName varchar (20)
select top 1
#BatchEmailID = BatchEmailID,
#To = [To],
#Body = Body,
#Subject = [Subject],
#ProfileName = [Profile]
from tb_BatchEmail
where BatchEmailID = 0
if(#BatchEmailID is null)
break;
EXEC msdb.dbo.sp_send_dbmail #recipients = #To
,#body = #Body
,#subject = #Subject
,#profile_name = #ProfileName
update tb_BatchEmail
set BatchEmailID = 1, SentDateTime = GETDATE()
where BatchEmailID = #BatchEmailID
end

OK first off, to update the table, you need a unique value on each row.
Alter your table as follows:
CREATE TABLE [dbo].[tb_BatchEmail](
[Id] int identity(1,1),
[BatchEmailID] [bit] NULL,
[To] [varchar](50) NULL,
[Body] [varchar](255) NULL,
[Subject] [varchar](20) NULL,
[Profile] [varchar](50) NULL,
[OrderID] [varchar](25) NULL,
[OrderDateTime] [datetime] NULL,
[SentDateTime] [datetime] NULL
) ON [PRIMARY]
GO
The new [Id] column will be used to reference back the row in question.
The your loop becomes this (with a test table used), just comment out my select, and uncomment the email bit:
declare #tb_BatchEmail table (Id int identity(1,1),
BatchEmailID bit,
[To] varchar(25),
Body varchar(250),
[Subject] varchar(25),
[Profile] varchar(20),
SentDateTime datetime)
insert into #tb_BatchEmail
select 0,'joe#domain.com','just a test','test','myprofile',null
declare #Id int
declare #To varchar (25)
declare #Body varchar (250)
declare #Subject varchar (25)
declare #ProfileName varchar (20)
while (select count(*) from #tb_BatchEmail where BatchEmailID=0) > 0
begin
select top 1
#Id = Id,
#To = [To],
#Body = Body,
#Subject = [Subject],
#ProfileName = [Profile]
from #tb_BatchEmail
where BatchEmailID = 0
--EXEC msdb.dbo.sp_send_dbmail #recipients = #To
-- ,#body = #Body
-- ,#subject = #Subject
-- ,#profile_name = #ProfileName
select #Id, #To, #Body, #Subject, #ProfileName
update #tb_BatchEmail
set BatchEmailID = 1, SentDateTime = GETDATE()
where Id = #Id
end

Related

Converting Oracle SQL Procedure into MySQL Stored Procedure

I am trying to convert a complex oracle sql procedure to mysql. The procedure contains of many differenct selects, cursors etc. I already wrote a version of it in mysql, but it does not work and only gives some error messages. I hope on could help me.
Tables
CREATE TABLE IF NOT EXISTS `NutritionalInformation`
(
`idNuIn` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
`calories` FLOAT NULL,
`saturatedFat` FLOAT NULL,
`transFat` FLOAT NULL,
`carbohydrates` FLOAT NULL,
`sugar` FLOAT NULL,
`protein` FLOAT NULL,
`salt` FLOAT NULL
);
CREATE TABLE IF NOT EXISTS `Inventory`
(
`idInventory` INT NOT NULL,
`idIngredient` INT NOT NULL,
`idStore` INT NOT NULL,
`expiryDate` DATE NULL,
`deliveryDate` DATE NOT NULL,
`amount` INT NOT NULL,
`isAccessible` INT NOT NULL,
CONSTRAINT `fk_Inventory_Ingredient`
FOREIGN KEY (`idIngredient`)
REFERENCES `Ingredient` (`idIngredient`),
CONSTRAINT `fk_Inventory_StoreA`
FOREIGN KEY (`idStore`)
REFERENCES `WaffleStore` (`idStore`),
CONSTRAINT pk_Inventory
PRIMARY KEY (idInventory)
);
CREATE TABLE IF NOT EXISTS `Inventory`
(
`idInventory` INT NOT NULL,
`idIngredient` INT NOT NULL,
`idStore` INT NOT NULL,
`expiryDate` DATE NULL,
`deliveryDate` DATE NOT NULL,
`amount` INT NOT NULL,
`isAccessible` INT NOT NULL,
PRIMARY KEY (`idIngredient`, `idStore`),
CONSTRAINT `fk_Inventory_Ingredient`
FOREIGN KEY (`idIngredient`)
REFERENCES `Ingredient` (`idIngredient`),
CONSTRAINT `fk_Inventory_StoreA`
FOREIGN KEY (`idStore`)
REFERENCES `WaffleStore` (`idStore`)
);
CREATE TABLE IF NOT EXISTS `Product`
(
`idProduct` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
`idNuIn` INT NOT NULL,
`price` FLOAT NOT NULL,
`name` VARCHAR(255) NOT NULL,
CONSTRAINT `fk_Product_NutritionalInformation1`
FOREIGN KEY (`idNuIn`)
REFERENCES `NutritionalInformation` (`idNuIn`)
);
CREATE TABLE IF NOT EXISTS `Waffle`
(
`idWaffle` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
`creatorName` VARCHAR(255) NULL,
`creationDate` DATE NOT NULL,
`processingTimeSec` INT,
`healty` VARCHAR(255),
CONSTRAINT `fk_Waffle_Product1`
FOREIGN KEY (`idWaffle`)
REFERENCES `Product` (`idProduct`)
);
CREATE TABLE IF NOT EXISTS `WaffleIngredient`
(
`idIngredient` INT NOT NULL,
`idWaffle` INT NOT NULL,
`amount` INT NOT NULL,
PRIMARY KEY (`idIngredient`, `idWaffle`),
CONSTRAINT `fk_WaffleRecept_Ingredient1`
FOREIGN KEY (`idIngredient`)
REFERENCES `Ingredient` (`idIngredient`),
CONSTRAINT `fk_WaffleRecept_Waffle1`
FOREIGN KEY (`idWaffle`)
REFERENCES `Waffle` (`idWaffle`)
);
CREATE TABLE IF NOT EXISTS `WaffleStore`
(
`idStore` INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
`name` VARCHAR(255) NULL,
`areaCode` VARCHAR(15) NULL,
`location` VARCHAR(255) NULL,
`streetName` VARCHAR(255) NULL,
`houseNumber` VARCHAR(45) NULL
);
Example Inserts
INSERT INTO NutritionalInformation (idNuIn, calories, saturatedFat, transFat, carbohydrates, sugar, protein, salt)
VALUES (4, 60, 0, 0, 0, 0, 0, 0);
INSERT INTO NutritionalInformation (idNuIn, calories, saturatedFat, transFat, carbohydrates, sugar, protein, salt)
VALUES (5, 350, 3, 3, 5, 5, 3, 1);
INSERT INTO INGREDIENT (idIngredient, idNuIn, name, unit, price, processingTimeSec)
VALUES (3, 4, 'Apfel', 'g', 0.5, 3);
INSERT INTO PRODUCT (idProduct, idNuIn, price, name)
VALUES (4, 5, 3.5, 'ApfelWaffel');
INSERT INTO WAFFLE (idWaffle, creatorName, creationDate, processingTimeSec, healty)
VALUES (4, 'Berndt', '2020-12-01', NULL, NULL);
INSERT INTO WAFFLEINGREDIENT(idIngredient, idWaffle, amount)
VALUES (3, 4, 2);
INSERT INTO WaffleStore (idStore, name, areaCode, location, streetName, houseNumber)
VALUES (1, 'Waffle GMBH', '50000', 'TEST', 'TEST', '38');
INSERT INTO INVENTORY(idInventory, idIngredient, idStore, expiryDate, deliveryDate, amount, isAccessible)
VALUES (2, 3, 1, '3032-12-30', '3032-12-30', 100, 1);
INSERT INTO WaffleOrder(idOrder, idStore, totalAmount, paymentStatus, orderDate)
VALUES (1, 1, 2, 0, '2020-12-30');
Oracle SQL PROCEDURE
CREATE OR REPLACE PROCEDURE OnInventoryAdd (
s_idProduct IN INT,
s_idOrder IN INT,
s_extenal_amount IN INT
)
IS
v_store INT;
v_waffle_id INT;
v_cursor_ingredientid INT;
v_cursor_amount INT;
v_cursor_expiryDate DATE;
v_cursor_deliveryDate DATE;
v_operator VARCHAR(3) := 'add';
CURSOR v_Ingredient_Cursor_On_Insert(w_Id INT) IS
SELECT idIngredient, amount FROM WAFFLEINGREDIENT WHERE idWaffle = w_Id;
CURSOR v_Ingredient_Cursor_On_Delete(i_id INT) IS
SELECT expiryDate, deliveryDate FROM Inventory WHERE idIngredient = i_id;
BEGIN
SELECT idStore INTO v_store FROM WAFFLEORDER WHERE idOrder = s_idOrder;
SELECT w.idWaffle INTO v_waffle_id FROM Waffle w WHERE w.idProduct = s_idProduct;
-- If more than one waffle is bought
FOR x IN 1..s_extenal_amount LOOP
-- Get all ingredient information of waffle
OPEN v_Ingredient_Cursor_On_Insert(v_waffle_id);
LOOP
FETCH v_Ingredient_Cursor_On_Insert INTO v_cursor_ingredientId, v_cursor_amount;
EXIT WHEN v_Ingredient_Cursor_On_Insert%NOTFOUND;
-- Get all old expirydate and deliverydate information
OPEN v_Ingredient_Cursor_On_Delete(v_cursor_ingredientId);
LOOP
FETCH v_Ingredient_Cursor_On_Delete INTO v_cursor_expiryDate, v_cursor_deliveryDate;
EXIT WHEN v_Ingredient_Cursor_On_Delete%NOTFOUND;
END LOOP;
CLOSE v_Ingredient_Cursor_On_Delete;
END LOOP;
CLOSE v_Ingredient_Cursor_On_Insert;
-- Update the Inventory
InventoryUpdate(v_store, v_cursor_ingredientId, v_cursor_amount, v_operator, v_cursor_expiryDate, v_cursor_deliveryDate);
END LOOP;
END;
/
Current Version
DROP PROCEDURE IF EXISTS `OnInventoryAdd`;
DELIMITER //
CREATE PROCEDURE `OnInventoryAdd` (
s_idProduct INT,
s_idOrder INT,
s_extenal_amount INT
)
BEGIN
DECLARE loop_counter INT DEFAULT s_extenal_amount;
DECLARE v_store INT;
DECLARE v_waffle_id INT;
DECLARE v_cursor_ingredientid INT;
DECLARE v_cursor_amount INT;
DECLARE v_cursor_expiryDate DATE;
DECLARE v_cursor_deliveryDate DATE;
DECLARE v_operator VARCHAR(3) DEFAULT 'add';
DECLARE v_c_insert_done, v_c_delete_done BOOLEAN DEFAULT FALSE;
DECLARE v_Ingredient_Cursor_On_Insert CURSOR FOR
SELECT idIngredient, amount FROM WAFFLEINGREDIENT WHERE idWaffle = v_waffle_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_c_insert_done = TRUE;
SELECT idStore INTO v_store FROM WAFFLEORDER WHERE idOrder = s_idOrder;
SELECT idWaffle INTO v_waffle_id FROM Waffle WHERE idWaffle = s_idProduct;
WHILE loop_counter > 0 DO
SET loop_counter = loop_counter - 1;
OPEN v_Ingredient_Cursor_On_Insert;
curr_insert_loop: LOOP
FETCH FROM v_Ingredient_Cursor_On_Insert INTO v_cursor_ingredientId, v_cursor_amount;
IF v_c_insert_done THEN
CLOSE v_Ingredient_Cursor_On_Insert;
LEAVE curr_insert_loop;
END IF;
BLOCK2 : BEGIN
DECLARE v_Ingredient_Cursor_On_Delete CURSOR FOR
SELECT expiryDate, deliveryDate FROM Inventory WHERE idIngredient = v_cursor_ingredientid;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET v_c_delete_done = TRUE;
OPEN v_Ingredient_Cursor_On_Delete;
curr_delete_loop : LOOP
FETCH FROM v_Ingredient_Cursor_On_Delete INTO v_cursor_expiryDate, v_cursor_deliveryDate;
IF v_c_delete_done THEN
CLOSE v_Ingredient_Cursor_On_Delete;
LEAVE curr_delete_loop;
END IF;
END LOOP curr_delete_loop;
END BLOCK2;
END LOOP curr_insert_loop;
CALL InventoryUpdate(v_store, v_cursor_ingredientId, v_cursor_amount, v_operator, v_cursor_expiryDate, v_cursor_deliveryDate);
END WHILE;
END //
DELIMITER ;
Error
4 row(s) affected, 2 warning(s): 1264 Out of range value for column 'expiryDateOnInsert' at row 2 1264 Out of range value for column 'deliveryDateOnInsert' at row 1
Even tho I wrote the Oracle Procedure, I have zero clue how to write the same behavior in MYSQL and more over how to fix this error. If there is a alternative to do the same without cursors, then it would be fine too
Ok, I've managed to convert the oracle procedure into mysql stored procedure, here is the working code:
Code
CREATE PROCEDURE `OnInventoryAdd` (
s_idProduct INT,
s_idOrder INT,
s_extenal_amount INT
)
BEGIN
DECLARE loop_counter INT DEFAULT s_extenal_amount;
DECLARE done1, done2 BOOLEAN DEFAULT FALSE;
DECLARE v_store INT;
DECLARE v_waffle_id INT;
DECLARE v_operator VARCHAR(3) DEFAULT 'add';
DECLARE v_cursor_ingredientid INT;
DECLARE v_cursor_amount INT;
DECLARE v_cursor_expiryDate DATE;
DECLARE v_cursor_deliveryDate DATE;
DECLARE v_Ingredient_Cursor_On_Insert CURSOR FOR
SELECT idIngredient, amount FROM WAFFLEINGREDIENT WHERE idWaffle = v_waffle_id;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done1 = TRUE;
SELECT idStore INTO v_store FROM WAFFLEORDER WHERE idOrder = s_idOrder;
SELECT idWaffle INTO v_waffle_id FROM Waffle WHERE idWaffle = s_idProduct;
REPEAT
OPEN v_Ingredient_Cursor_On_Insert;
loop1 : LOOP
FETCH FROM v_Ingredient_Cursor_On_Insert INTO v_cursor_ingredientId, v_cursor_amount;
IF done1 THEN
CLOSE v_Ingredient_Cursor_On_Insert;
LEAVE loop1;
END IF;
BLOCK1 : BEGIN
DECLARE v_Ingredient_Cursor_On_Delete CURSOR FOR
SELECT expiryDate, deliveryDate FROM Inventory WHERE idIngredient = v_cursor_ingredientid;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done2 = TRUE;
OPEN v_Ingredient_Cursor_On_Delete;
loop2 : LOOP
FETCH FROM v_Ingredient_Cursor_On_Delete INTO v_cursor_expiryDate, v_cursor_deliveryDate;
IF done2 THEN
SET done2 = FALSE; -- This was the solution
LEAVE loop2;
END IF;
END LOOP loop2;
END BLOCK1;
END LOOP loop1;
CALL InventoryUpdate(v_store, v_cursor_ingredientId, v_cursor_amount, v_operator, v_cursor_expiryDate, v_cursor_deliveryDate);
SET loop_counter = loop_counter - 1;
UNTIL loop_counter = 0
END REPEAT;
END //
DELIMITER ;

Stored Procedure Updating more than one time MySQL

I have a stored procedure to update some rows in MySQL. But when I call the stored procedure, it affects more than actual rows.
Here is my stored procedure:
CREATE DEFINER=`root`#`localhost` PROCEDURE `SP_INSERT_DATA`(
IN `incoming_data` TEXT,
IN `value_array` TEXT,
IN `serial_number` VARCHAR(50),
IN `data_timestamp` VARCHAR(50),
OUT `result_id` INT,
OUT `result_message` VARCHAR(500)
)
LANGUAGE SQL
NOT DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
BEGIN
DECLARE i INT;
DECLARE value_iteration VARCHAR(50);
DECLARE lcl_data_type_id INT;
DECLARE arr_data_type_name VARCHAR(50);
DECLARE affected_data_row_count INT;
DECLARE cstmr_id INT;
DECLARE exit handler FOR 40001
BEGIN
GET DIAGNOSTICS CONDITION 1
#p1 = MYSQL_ERRNO, #p2 = MESSAGE_TEXT;
SET result_id = -2;
SET result_message = CONCAT('RETURNED ERROR NO : ', #p1 , '\r\nMESSAGE TEXT : ',#p2);
ROLLBACK;
END;
DECLARE exit handler for sqlexception
BEGIN
GET DIAGNOSTICS CONDITION 1
#p1 = MYSQL_ERRNO, #p2 = MESSAGE_TEXT;
SET result_id = -999;
SET result_message = CONCAT('RETURNED ERROR NO : ', #p1 , '\r\nMESSAGE TEXT : ',#p2);
ROLLBACK;
END;
START TRANSACTION;
SET i = 1;
SET affected_data_row_count = 0;
SET cstmr_id = 0;
SET result_id = 0;
SET result_message = 'Success';
SELECT id INTO cstmr_id FROM templaricustomers WHERE templaricustomers.customer_serial_number = serial_number LIMIT 1;
IF(cstmr_id <> 0) THEN
WHILE (LOCATE(',', value_array) > 0)
DO
SET arr_data_type_name = SUBSTRING_INDEX(value_array,',',i);
SET value_array = SUBSTRING(value_array, LOCATE(',',value_array) + 1);
SELECT JSON_EXTRACT(incoming_data, arr_data_type_name) INTO value_iteration;
SET arr_data_type_name := SUBSTRING_INDEX(arr_data_type_name, ".", -1);
IF (SELECT COUNT(id) FROM datatypes WHERE datatypes.data_name = arr_data_type_name) > 0 THEN
SELECT id INTO lcl_data_type_id FROM datatypes WHERE datatypes.data_name = arr_data_type_name LIMIT 1;
ELSE
INSERT INTO datatypes (datatypes.data_name,datatypes.description ,datatypes.inserted_date) VALUES(arr_data_type_name,arr_data_type_name,NOW());
SELECT id INTO lcl_data_type_id FROM datatypes WHERE datatypes.data_name = arr_data_type_name LIMIT 1;
END IF;
IF (SELECT COUNT(id) FROM mqttpacket WHERE mqttpacket.data_type_id = lcl_data_type_id AND mqttpacket.customer_id = cstmr_id) > 0 THEN
UPDATE mqttpacket SET mqttpacket.data_value = value_iteration , mqttpacket.inserted_time = data_timestamp WHERE mqttpacket.data_type_id = lcl_data_type_id AND mqttpacket.customer_id = cstmr_id;
ELSE
INSERT INTO mqttpacket (mqttpacket.data_type_id,mqttpacket.customer_id,mqttpacket.data_value,mqttpacket.inserted_time) VALUES(lcl_data_type_id,cstmr_id,value_iteration,data_timestamp);
END IF;
SET affected_data_row_count = affected_data_row_count +1;
END WHILE;
SET result_id = 0;
SET result_message = CONCAT('Query performed successfully. Effected rows : ',CAST(affected_data_row_count AS CHAR));
ELSE
SET result_id = -1;
SET result_message = 'Customer Serial Number not found.';
END IF;
COMMIT;
END
Here is how I call it:
CALL `SP_INSERT_DATA`('{"subcooling":-40,"B1":113,"B2":206,"B3":471,"B4":226,"B5":8,"B6":380,"B7":210,"B8":187,"Discharge":135,"Suction":120,"High_Pressure":90,"Low_Pressure":90,"Evaporation":73,"Condensation":73,"MAX_CMP_SPEED":1100,"Thermal_Limit":748,"SH":46,"EEV_pct":0,"COP":0,"DSH":60,"WaterFlux":8,"FanPower":1,"DeltaTtoStart":0,"DeltaPtoStart":60,"CMP_ROTOR_RPS":0,"SET_CH_FLASH":120,"SET_HP_FLASH":350,"SET_DHW_FLASH":470,"Defrosting":0,"B8_AVERAGE":63,"SET_PLANT":0,"SET_CH_BMS":160,"SET_HP_BMS":200,"SET_DHW_BMS":480,"SET_ACTIVE":200,"SET_DSH":250,"EEV_INJ_pct":0,"LPT":0,"HPT":0,"PLANT_MODE_MANUAL":0,"DHW_MODE_MANUAL":0,"WATER_FLOW":8,"DISCHARGE_TMP":135,"INVERTER_TMP":8,"ENVELOP_ZONE":1,"EEV_A_STEPS":0,"EBM_POWER":1,"EBM_MAX_POWER":106,"COMP_pct_FINAL":0,"TOTAL_POWER_ABSORBED":10,"POWER_OUT_KW":0,"COOLINGCAPACITY":0}' , '$.subcooling,$.B1,$.B2,$.B3,$.B4,$.B5,$.B6,$.B7,$.B8,$.Discharge,$.Suction,$.High_Pressure,$.Low_Pressure,$.Evaporation,$.Condensation,$.MAX_CMP_SPEED,$.Thermal_Limit,$.SH,$.EEV_pct,$.COP,$.DSH,$.WaterFlux,$.FanPower,$.DeltaTtoStart,$.DeltaPtoStart,$.CMP_ROTOR_RPS,$.SET_CH_FLASH,$.SET_HP_FLASH,$.SET_DHW_FLASH,$.Defrosting,$.B8_AVERAGE,$.SET_PLANT,$.SET_CH_BMS,$.SET_HP_BMS,$.SET_DHW_BMS,$.SET_ACTIVE,$.SET_DSH,$.EEV_INJ_pct,$.LPT,$.HPT,$.PLANT_MODE_MANUAL,$.DHW_MODE_MANUAL,$.WATER_FLOW,$.DISCHARGE_TMP,$.INVERTER_TMP,$.ENVELOP_ZONE,$.EEV_A_STEPS,$.EBM_POWER,$.EBM_MAX_POWER,$.COMP_pct_FINAL,$.TOTAL_POWER_ABSORBED,$.POWER_OUT_KW,$.COOLINGCAPACITY,', '123456', '2021-02-24 10:43:00.00' ,#result_id, #result_message);
The table mqttpacket is a system versioned table. Here are the table creation queries.
CREATE TABLE test_database.MQTTPacket(
id INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
data_type_id INT NOT NULL,
customer_id INT NOT NULL,
data_value INT NULL,
row_start TIMESTAMP(6) GENERATED ALWAYS AS ROW START INVISIBLE,
row_end TIMESTAMP(6) GENERATED ALWAYS AS ROW END INVISIBLE,
inserted_time TIMESTAMP(6) NULL DEFAULT NULL,
PERIOD FOR SYSTEM_TIME(row_start,row_end),
FOREIGN KEY (data_type_id) REFERENCES test_database.DataTypes(id),
FOREIGN KEY (customer_id) REFERENCES test_database.templaricustomers(id)
)WITH SYSTEM VERSIONING;
CREATE TABLE `datatypes` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`data_name` VARCHAR(50) NOT NULL COLLATE 'latin1_general_ci',
`inserted_date` DATE NULL DEFAULT NULL,
`description` VARCHAR(50) NULL DEFAULT NULL COLLATE 'latin1_general_ci',
`device_id` INT(11) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `device_id` (`device_id`) USING BTREE,
CONSTRAINT `datatypes_ibfk_1` FOREIGN KEY (`device_id`) REFERENCES `test_database`.`devices` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT
)
CREATE TABLE `templaricustomers` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`customer_serial_number` VARCHAR(50) NOT NULL COLLATE 'latin1_general_ci',
`customer_name` VARCHAR(50) NULL DEFAULT NULL COLLATE 'latin1_general_ci',
`inserted_date` TIMESTAMP(6) NOT NULL DEFAULT current_timestamp(6),
PRIMARY KEY (`id`) USING BTREE
)
So, when I first call the stored procedure, my result_message variable returns "Query performed successfully. Effected rows : 53" however MySql says
Affected rows: 107 Found rows: 0 Warnings: 0 Duration for 1 query: 0.015 sec.
In the second call of the SP, it says
Affected rows: 160 Found rows: 0 Warnings: 0 Duration for 1 query: 0.031 sec.
Thankful for any help in advance.

MySQL stored procedure anomaly: One line gets executed, another skipped?

I have a stored procedure, that checks if there is a user with the same e-mail address as the input, if not, then registeres one.
Here is the table:
CREATE TABLE IF NOT EXISTS `overkill`.`accounts` (
`accountID` INT NOT NULL AUTO_INCREMENT ,
`email` VARCHAR(64) NOT NULL ,
`firstName` VARCHAR(32) NOT NULL ,
`lastName` VARCHAR(32) NOT NULL ,
`passSaltedSHA` BINARY(20) NOT NULL ,
`salt` BINARY(20) NOT NULL ,
`gender` ENUM('m','f') NOT NULL ,
`birthDate` DATE NOT NULL ,
`regTime` TIMESTAMP NOT NULL ,
PRIMARY KEY (`accountID`) )
ENGINE = InnoDB;
Here is the stored procedure:
DELIMITER $$
CREATE PROCEDURE `overkill`.`registerUser` (
IN emailIN VARCHAR(64),
IN passwordIN VARCHAR(16),
IN firstNameIN VARCHAR(32),
IN lastNameIn VARCHAR(32),
IN birthIN DATE,
IN genderIN ENUM('f','m'))
BEGIN
DECLARE existingMailAccLOG INT DEFAULT NULL;
DECLARE saltLOC CHAR(40);
DECLARE regSuccessLOC BOOLEAN DEFAULT FALSE;
SELECT COUNT(*) INTO existingMailAccLOG FROM `overkill`.`accounts` WHERE `accounts`.`email` = emailIN;
IF existingMailAccLOG = 0 THEN
SET saltLOC = SHA1(rand());
SET regSuccessLOC = TRUE;
INSERT INTO `overkill`.`accounts` (`email`, `firstName`, `lastName`, `passSaltedSHA`, `salt`, `gender`, `birthDate`) VALUES(emailIN, firstNameIN, lastNameIn, UNHEX(SHA1(CONCAT(passwordIN, saltLOC))), UNHEX(saltLOC), genderIN, birthIN);
END IF;
SELECT regSuccessLOC AS `registered`, saltLOC AS `salt`;
END
If I call:
CALL registerUser("abc#def.com", "pass", "firstn", "lastn", "2012-01-01", "f");
It inserts a line into the accounts table, but forgets to return the proper values that I set inside the IF
SET saltLOC = SHA1(rand());
SET regSuccessLOC = TRUE;
How is it even possible? Why are theese lines skipped and INSERT still gets executed, without mistake?
Try to add "#" in front of your variable names after DECLARE keyword. It can cause some confusion, as it is described here: MySQL: #variable vs. variable. Whats the difference? (Part2) and here: MySQL: #variable vs. variable. Whats the difference?

SSRS data driven subscription with dynamic pivot table as the return value

I have a rather complex message queue system where in the end I do a dynamic pivot to pass back the TO as well as all the report parameters. I'm using SSRS as my mail message format provider and data driven subscriptions to auto deliver my e-mails.
My problem is that when I am using the UI to set up my data driven subscription, SSRS prevents me from moving on with an error.
The dataset cannot be generated. An
error occurred while connecting to a
data source, or the query is not valid
for the data source.
(rsCannotPrepareQuery)
Here's a basic rundown of what I'm doing. I have these tables for my message queuing system.
CREATE TABLE MessageParameters
(
SequenceId int IDENTITY(1,1) NOT NULL,
MessageQueueId int NOT NULL,
ParameterName varchar(50) NOT NULL,
ParameterValue varchar(300) NOT NULL,
CONSTRAINT PK_MessageParameters PRIMARY KEY CLUSTERED(SequenceId)
)
CREATE TABLE MessageRecipients
(
SequenceId int IDENTITY(1,1) NOT NULL,
MessageQueueId int NOT NULL,
ProfileId int NOT NULL,
CONSTRAINT PK_MessageRecipients PRIMARY KEY CLUSTERED(SequenceId)
)
CREATE TABLE MessageTypes
(
Id int NOT NULL,
ReportName varchar(50) NOT NULL,
CONSTRAINT PK_MessageTypes PRIMARY KEY CLUSTERED(Id)
)
CREATE TABLE MessageStatus
(
Id int NOT NULL,
StatusName varchar(50) NOT NULL,
CONSTRAINT PK_MessageStatus PRIMARY KEY CLUSTERED(Id)
)
CREATE TABLE MessageQueue
(
SequenceId int IDENTITY(1,1) NOT NULL,
MessageType int NOT NULL,
[Status] int DEFAULT(0) NOT NULL,
Created datetime DEFAULT(GETDATE()) NOT NULL,
Modified datetime DEFAULT(GETDATE()) NOT NULL,
CONSTRAINT PK_MessageQueue PRIMARY KEY CLUSTERED(SequenceId)
)
Fairly simple to understand. Each message can have more than one parameter and more than one recipient.
Then, I have a sproc that gets me all of the pending messages in the queue by message type.
CREATE PROCEDURE GetPendingMessageRecipients
#MessageType int
AS
BEGIN
SELECT
SequenceId
INTO
#Messages
FROM
MessageQueue
WHERE
MessageType = #MessageType
AND
[Status] = 0
--###############################################################
--###############################################################
DECLARE #ParameterList varchar(max)
DECLARE #To varchar(max)
SELECT
r.MessageQueueId,
ISNULL(#To, '') + p.EmailAddress + ',' AS [TO]
INTO
#Recipients
FROM
MessageRecipients r
JOIN
WebProfiles p
ON
r.ProfileId = p.Id
JOIN
#Messages m
ON
r.MessageQueueId = m.SequenceId
--remove the last comma
UPDATE
#Recipients
SET
[TO] = LEFT([TO], LEN([TO]) - 1)
--###############################################################
--###############################################################
SELECT
p.MessageQueueId,
p.ParameterName,
p.ParameterValue
INTO
#Params
FROM
MessageParameters p
JOIN
#Messages m
ON
p.MessageQueueId = m.SequenceId
INSERT INTO #Params
SELECT
MessageQueueId, 'TO', [TO]
FROM
#Recipients
--###############################################################
--###############################################################
SELECT #ParameterList = ISNULL(#ParameterList, '') +
'[' + ParameterName + '],'
FROM
#Params
GROUP BY
ParameterName
-- Remove last comma
SET #ParameterList = LEFT(#ParameterList, LEN(#ParameterList) - 1)
DECLARE #Query varchar(max)
SET #Query = 'SELECT * ' +
'FROM #Params ' +
'PIVOT ( ' +
' max([ParameterValue]) ' +
' for [ParameterName] ' +
' in (' + #ParameterList + ') ' +
') AS pvt'
EXEC (#Query)
END
It works like a champ inside management studio. I get the messageid, the recipients in a comma delimted list as the TO field, and then all the report parameters with the correct field names. But, SSRS doesn't like it one bit when I try to enter it as my recipient data source.
If you put
SET FMTONLY OFF
at the top of your stored procedure, SSRS skips the validation so that you can use temp tables in your query.

Transaction count exception in vb.net (SQL Exception)

I am getting below exception when i am going to enter record in a table through StoredProceduer of sqlserver
i have a field which i need u update immediately after insert of new record in table.
for that i created a sotredprocedure in which i wrote insert command first and after that i wrote a update command for same recored but it gave me below error
SQlException:
Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 1, current count = 2. Uncommittable transaction is detected at the end of the batch. The transaction is rolled back. Some Error in stored procedure execution
i tried in another way also like: i just wrote insert command in storedprocedure and i created a afterInsert trigger in which i am firing update command. but still i am facing above exception
Details:
Table structure:
CREATE TABLE [dbo].[TabStoreGRNMaster](
[pk_grnm_id] [bigint] IDENTITY(1,1) NOT NULL,
[fk_col_id] [bigint] NULL,
[fk_sup_id] [bigint] NULL,
[grnm_grnno] [varchar](50) NULL,
[grnm_date] [nvarchar](10) NULL,
[grnm_partyinvno] [varchar](50) NULL,
[grnm_invdate] [nvarchar](10) NULL,
[grnm_freight] [numeric](7, 2) NULL,
[grnm_otherchrg] [numeric](7, 2) NULL,
[grnm_roundoff] [bit] NULL,
[Fk_User_Id] [bigint] NULL,
[grnm_EntryDate] [nvarchar](8) NULL,
CONSTRAINT [PK_TabStoreGRNMaster] PRIMARY KEY CLUSTERED
(
[pk_grnm_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
storedprocedure:
USE [Kollege]
GO
/****** Object: StoredProcedure [dbo].[StoreGRNMaster] Script Date: 11/27/2009 10:20:37 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[StoreGRNMaster]
(
#pk_grnm_id [bigint] output ,
#fk_col_id [bigint] = 0 ,
#fk_sup_id [bigint] = 0 ,
#grnm_grnno [varchar](50) = '',
#grnm_date [nvarchar](10) = null,
#grnm_partyinvno [varchar](50) = '',
#grnm_invdate [nvarchar](10) = null,
#grnm_freight [numeric] = 0 ,
#grnm_otherchrg [numeric] = 0 ,
#grnm_roundoff [bit] = 0 ,
#Fk_User_Id [bigint] = 0 ,
#grnm_EntryDate [nvarchar](8) = null,
#opt [BIGINT] =0,
#del [bit] =0
)
as
begin
SET NOCOUNT ON;
BEGIN TRY
begin transaction
if isnull(#opt,0) = 0 begin
INSERT INTO TabStoreGRNMaster
(
fk_col_id,
fk_sup_id,
grnm_grnno,
grnm_date,
grnm_partyinvno,
grnm_invdate,
grnm_freight,
grnm_otherchrg,
grnm_roundoff,
Fk_User_Id,
grnm_EntryDate
)
VALUES
(
#fk_col_id,
#fk_sup_id,
#grnm_grnno,
#grnm_date,
#grnm_partyinvno,
#grnm_invdate,
#grnm_freight,
#grnm_otherchrg,
#grnm_roundoff,
#Fk_User_Id,
#grnm_EntryDate
)
set #pk_grnm_id = ##identity
end
else
begin
if #del = 0
UPDATE TabStoreGRNMaster
SET
fk_col_id = #fk_col_id,
fk_sup_id = #fk_sup_id,
grnm_grnno = #grnm_grnno,
grnm_date = #grnm_date,
grnm_partyinvno = #grnm_partyinvno,
grnm_invdate = #grnm_invdate,
grnm_freight = #grnm_freight,
grnm_otherchrg = #grnm_otherchrg,
grnm_roundoff = #grnm_roundoff,
Fk_User_Id = #Fk_User_Id,
grnm_EntryDate = #grnm_EntryDate
WHERE
(
pk_grnm_id = #opt
)
if #del=1 and isnull(#opt,0) <> 0
DELETE from [TabStoreGRNMaster]
WHERE
( [pk_grnm_id] = #opt)
end
commit transaction
END TRY
BEGIN CATCH
raiserror ('Some Error in stored procedure execution',1,1)
END CATCH;
END
Trigger:
alter TRIGGER TGRStoreGRNMasterCode
ON tabStoreGRNMaster
AFTER INSERT
AS
begin
declare #pk varchar(10)
declare #colcode varchar(10)
declare #current_session varchar(20)
declare #colid bigint
set #pk = (select pk_grnm_id from Inserted)
--set #colid = (select fk_col_id from Inserted)
set #colcode= 'jiet'--(select col_code from tabcollegemaster where pk_col_id =5) (when i replace word 'Jiet' with commented qry i gets sql exception otherwise its working fine)
select #current_session = Ses_abbrev from TabAcaSessionMast where ses_current = 1
--update tabStoreGRNMaster set grnm_grnno= #colcode +'/' +#current_session+ '/' + #pk where pk_grnm_id=convert(bigint,#pk)
update tabStoreGRNMaster set grnm_grnno= (select col_code from tabcollegemaster where pk_col_id=5) +'/' +#current_session+ '/' + #pk where pk_grnm_id=convert(bigint,#pk)
end
Your comment to another answer mentioned "I am maintain Transactions from Vb.net also while calling this stored procedure". This is the cause
You have to balance your BEGIN TRAN and COMMITs/ROLLBACKs so ##TRANCOUNT starts and finishes with the same value for the same scope.
Either do it all in the stored proc or do it all in the client
It looks to me like you're not doing anything with the open transaction if an error is found in your TRY block - the COMMIT would not run, but your CATCH block has no ROLLBACK.