I am try to execute below code for my stored procedure and it throws error at line number 14. I am unable to locate what is error, help me to resolve.
DELIMITER $$
CREATE PROCEDURE usp_SetGems (
-- Add the parameters for the stored procedure here
p_requestid int/* =null */,
p_akcija int/* =null */)
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
-- Insert statements for procedure here
if p_akcija = 0 then
declare #v_userId char(36);
declare #v_vingems int;
select #v_userId:=r.user_id, #v_vingems := r.value from Requests r
where r.Id=p_requestid;
update Users
set balance=balance+#v_vingems
where id=v_userId;
else
declare #v_userrId longtext;
declare #v_vingemss int;
select #v_userrId.user_id:=r.user_id, #v_vingemss := r.value from Requests r
where r.Id=p_requestid;
update Users
set balance=balance-#v_vingems
where id=v_userrId;
end if;
end; $$
DELIMITER ;
Your Declare statement are wrong (declare #v_userId char(36),declare #v_vingems int; ..... ). Below is correct code of your procedure:-
DELIMITER $$
CREATE PROCEDURE usp_SetGems (
-- Add the parameters for the stored procedure here
p_requestid int/* =null */,
p_akcija int/* =null */)
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
-- Insert statements for procedure here
if p_akcija = 0 then
BEGIN
select r.user_id, r.value INTO #v_userId, #v_vingems from Requests r
where r.Id=p_requestid;
update Users
set balance=balance+#v_vingems
where id=v_userId;
END;
else
BEGIN
select r.user_id, r.value INTO #v_userId, #v_vingems from Requests r
where r.Id=p_requestid;
update Users
set balance=balance-#v_vingems
where id=v_userrId;
END;
end if;
end $$
DELIMITER ;
You have a reserved word in your select. "into"
select r.user_id,r.value **into** v_userrId, v_vingems from Requests r
where r.Id=p_requestid;
Hi i have one sp where i used try catch with transaction. below is the code
USE [Securtimeweb2.1]
GO
/****** Object: StoredProcedure [dbo].[UpdateCompany] Script Date: 7/6/2015 12:14:27 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
ALTER PROCEDURE [dbo].[UpdateCompany]
(
#CompanyCode varchar(max),
#NewCompCode varchar(max)=null,
#TRANSVAL VARCHAR(MAX)
)
as
BEGIN
BEGIN TRY
BEGIN TRAN #TRANSVAL
update BranchMaster set CompanyCode=#NewCompCode Where CompanyCode=#CompanyCode
COMMIT TRAN #TRANSVAL
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() AS strMessage
ROLLBACK TRAN #TRANSVAL
END CATCH
END
then i use this code to run this sp in another query window
EXEC UpdateCompany '002','003','TRAN1'
so after using this in one another query window i am trying to rollback the transaction which is
DECLARE #TRAN VARCHAR(MAX)='TRAN1'
BEGIN TRAN #TRAN
ROLLBACK TRAN #TRAN
so here we can see i given some name for the transaction and trying to rollback with the same name but it's not getting rollback.
Am i doing anything wrong here??
Use This Links To Know How Transaction Works
http://www.sqlservercurry.com/2011/01/rollback-transaction-in-sql-server.html
I use following standard, maybe it can help :
BEGIN TRAN
BEGIN TRY
--YOUR SQL STATEMENTS
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() AS [STATUS]
ROLLBACK TRAN
END CATCH
IF ##TRANCOUNT > 0
BEGIN
COMMIT TRAN
SELECT 'SUCCESS' AS [STATUS]
END
I am looking for help with my sql procedure.
I would like to substring in loop each username, and alias from two input arguments and add it into table users. I have two procedures.
Sorry for Polish variable names and procedure names.
My first procedure is
CREATE DEFINER=`root`#`localhost` PROCEDURE `dodajZawodnika`(IN `dane` VARCHAR(50), IN `wyswietlanie` VARCHAR(50))
NO SQL
BEGIN
IF (SELECT 1 = 1 from zawodnicy where danezawodnika = dane AND dowyswietlenia=wyswietlanie) THEN
BEGIN
Select id from zawodnicy where danezawodnika=dane AND dowyswietlenia=wyswietlanie;
END;
ELSE
BEGIN
Insert INTO zawodnicy (danezawodnika, dowyswietlenia) VALUES(dane, wyswietlanie);
SELECT last_insert_id() AS ID;
END;
END IF;
END;
My second procedure is
CREATE DEFINER=`root`#`localhost` PROCEDURE `stworzSklad`(IN `dane` VARCHAR(1500), IN `pseudo` VARCHAR(1000))
NO SQL
BEGIN
DECLARE counter INTEGER;
DECLARE zawodnik VARCHAR(1500);
DECLARE pseudonim VARCHAR(1000);
DECLARE zawodnicy VARCHAR(1500);
DECLARE pseudonimy VARCHAR(1000);
DECLARE exit handler for sqlexception
BEGIN
-- ERROR
ROLLBACK;
END;
DECLARE exit handler for sqlwarning
BEGIN
-- WARNING
ROLLBACK;
END;
set counter = 0;
set #zawodnicy = dane;
set #pseudonimy = psuedo;
select #zawodnicy, #pseudonimy;
REPEAT
set zawodnik=(SELECT TRIM(SUBSTRING_INDEX(#zawodnicy, ',', 1)));
set pseudonim=(SELECT TRIM(SUBSTRING_INDEX(#pseudonimy, ',', 1)));
call dodajZawodnika(zawodnik, pseudonim);
SELECT RIGHT(#zawodnicy, TRIM(length(#zawodnicy) - length(SUBSTRING_INDEX(#zawodnicy, ',', 1)) - 1)) into #zawodnicy;
SELECT RIGHT(#pseudonimy, TRIM(length(#pseudonimy) - length(SUBSTRING_INDEX(#pseudonimy, ',', 1)) - 1)) into #pseudonimy;
select zawodnik as 'zawodnik', pseudonim as 'pseudonim', dane as 'dane', pseudo as 'pseudo', #zawodnicy as 'zawodnicy', #pseudonimy as 'pseudonimy';
set counter = counter + 1;
UNTIL (#zawodnicy = '' or counter = 30)
END REPEAT;
select counter;
END
I am fighting with it from about 2 hours.
I would like to use also transaction for this insert.
Please help me with this little problem.
How to make this in proper way?
Now, calling stworzSklad procedure make endless loop (ofc without counter in until condition) and any of user was not inserted in my table.
Cheers!
Why would my SQL throw an error like LEAVE with no matching label: tableList
DELIMITER $$
DROP PROCEDURE IF EXISTS CountSignatures$$
CREATE PROCEDURE CountSignatures()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE signatureCount INT;
DECLARE tableName CHAR(100);
DECLARE tableList CURSOR FOR Select table_name from information_schema.tables where table_schema="LogData" and table_name like "%FAULT_20150320%";
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN tableList;
tableListLoop: LOOP
SET done = FALSE ;
FETCH tableList INTO tableName;
IF done THEN
LEAVE tableListLoop;
END IF;
***select signatureCount := signatureCount + count(distinct signature) from tableList;*** Line giving syntax error
END LOOP;
CLOSE tableList;
END$$
DELIMITER;
leave lable:
This statement is used to exit the flow control construct that has the
given label. If the label is for the outermost stored program block,
LEAVE exits the program.
In your code tableList is a cursor, you should leaved the tableListLoop not tableList, so try:
LEAVE tableListLoop;
I'm not sure why it would generate that particular error, but this line is not correct:
signatureCount = signatureCount + Select count (distinct signature) from tableList;
If you want to update the variable, try:
set signatureCount = (signatureCount +
(select count(distinct signature)
from tableList));
However, you don't initialize the variable, so this will just produce NULL anyway.
Lets say this is the situation:
[Stored Proc 1]
BEGIN
BEGIN TRANSACTION
...
exec sp 2
COMMIT
END
Now, if SP 2 - rolls back for whatever reason, does SP 1 - commit or rollback or throw exception?
Thanks.
It is possible for the work done by SP2 to be rolled back and not loose the work done by SP1. But for this to happen, you must write your stored procedures using a very specific pattern, as described in Exception handling and nested transactions:
create procedure [usp_my_procedure_name]
as
begin
set nocount on;
declare #trancount int;
set #trancount = ##trancount;
begin try
if #trancount = 0
begin transaction
else
save transaction usp_my_procedure_name;
-- Do the actual work here
lbexit:
if #trancount = 0
commit;
end try
begin catch
declare #error int, #message varchar(4000), #xstate int;
select #error = ERROR_NUMBER(), #message = ERROR_MESSAGE(), #xstate = XACT_STATE();
if #xstate = -1
rollback;
if #xstate = 1 and #trancount = 0
rollback
if #xstate = 1 and #trancount > 0
rollback transaction usp_my_procedure_name;
raiserror ('usp_my_procedure_name: %d: %s', 16, 1, #error, #message) ;
end catch
end
Not all errors are recoverable, there are a number of error conditions that a transaction cannot recover from, the most obvious example being deadlock (your are notified of the deadlock exception after the transaction has already rolled back). Both SP1 and SP# have to be written using this pattern. If you have a rogue SP, or you want to simple leverage existing stored procedures that nilly-willy issue ROLLBACK statements then your cause is lost.
There are no autonomous transactions in SQL Server. You may see ##TRANCOUNT increase beyond 1, but a rollback affects the whole thing.
EDIT asked to point to documentation. Don't know of the topic that documents this explicitly, but I can show it to you in action.
USE tempdb;
GO
Inner proc:
CREATE PROCEDURE dbo.sp2
#trip BIT
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRANSACTION;
PRINT ##TRANCOUNT;
IF #trip = 1
BEGIN
IF ##TRANCOUNT > 0
ROLLBACK TRANSACTION;
END
ELSE
BEGIN
IF ##TRANCOUNT > 0
COMMIT TRANSACTION;
END
PRINT ##TRANCOUNT;
END
GO
Outer proc:
CREATE PROCEDURE dbo.sp1
#trip BIT
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRANSACTION;
PRINT ##TRANCOUNT;
BEGIN TRY
EXEC dbo.sp2 #trip = #trip;
END TRY
BEGIN CATCH
PRINT ERROR_MESSAGE();
END CATCH
PRINT ##TRANCOUNT;
IF ##TRANCOUNT > 0
COMMIT TRANSACTION;
PRINT ##TRANCOUNT;
END
GO
So now let's call it and let everything commit:
EXEC dbo.sp1 #trip = 0;
Results:
12110
Now let's call it and roll back the inner procedure:
EXEC dbo.sp1 #trip = 1;
Results:
120 <-- notice that a rollback here rolled back both
Transaction count after EXECUTE indicates a mismatching number
of BEGIN and COMMIT statements. Previous count = 1, current count = 0.
00
If SP2 rolls back the transaction, SP1 will rollback as well.
See: http://msdn.microsoft.com/en-US/library/ms187844(v=sql.105).aspx for details.
In nested transactions, if any of the inner transations rolls back, all its outer transaction will rollback.
Here is a quick and dirty way to nest transactions in stored procedures (using the code from Aaron's answer) that can be useful sometimes. It uses a default parameter to indicate to the inner procedure if it is a nested call, and returns a success/fail result to the outer procedure.
CREATE PROCEDURE dbo.sp2
#trip BIT,
#nested BIT = 0
AS
BEGIN
SET NOCOUNT, XACT_ABORT ON
IF #nested = 0 BEGIN TRAN
PRINT ##TRANCOUNT
IF #trip = 1
BEGIN
IF #nested = 0 ROLLBACK
RETURN 1
END
ELSE
BEGIN
IF #nested = 0 COMMIT
END
PRINT ##TRANCOUNT
RETURN 0
END
GO
The outer procedure checks the success/fail an rolls back the transaction if appropriate.
CREATE PROCEDURE dbo.sp1
#trip BIT
AS
BEGIN
DECLARE #result INT
SET NOCOUNT, XACT_ABORT ON
BEGIN TRAN
PRINT ##TRANCOUNT
BEGIN TRY
EXEC #result = dbo.sp2 #trip = #trip, #nested = 1
IF #result <> 0
BEGIN
ROLLBACK
RETURN 1
END
END TRY
BEGIN CATCH
PRINT ERROR_MESSAGE()
END CATCH
PRINT ##TRANCOUNT
COMMIT
PRINT ##TRANCOUNT
RETURN 0
END
GO
Every stored procedure must end with the same transaction count with which it entered. If the count does not match, SQL Server will issue error 266, "Transaction count after EXECUTE indicates that a COMMIT or ROLLBACK TRANSACTION statement is missing."
If a stored procedure does not initiate the outermost transaction, it should not issue a ROLLBACK.
If a nested procedure begin a new transaction; but if it detects the need to roll back and the ##TRANSACTION value is greater than 1, it raises an error, returns an error message to the caller via out parameter or return value, and issues a COMMIT instead of a ROLLBACK.
CREATE PROCEDURE [dbo].[Pinner]
-- Add the parameters for the stored procedure here
#ErrorMessage varchar(max) out
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
begin tran
begin try
throw 51000, 'error occured', 1
commit tran
set #ErrorMessage = ''
end try
begin catch
set #ErrorMessage = ERROR_MESSAGE();
if ##TRANCOUNT = 1
rollback tran
if ##TRANCOUNT > 1
commit tran
end catch
END
create PROCEDURE [dbo].[Pouter]
-- Add the parameters for the stored procedure here
#ErrorMessage varchar(max) out
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
begin tran
begin try
EXECUTE [dbo].[Pinner]
#ErrorMessage OUTPUT
if #ErrorMessage <> '' begin
throw 51000, #ErrorMessage, 1
end
commit tran
set #ErrorMessage = ''
end try
begin catch
set #ErrorMessage = ERROR_MESSAGE();
if ##TRANCOUNT = 1
rollback tran
if ##TRANCOUNT > 1
commit tran
end catch
END
DECLARE #ErrorMessage varchar(max)
EXEC [dbo].[Pouter]
#ErrorMessage = #ErrorMessage OUTPUT
SELECT #ErrorMessage as N'#ErrorMessage'
https://www.codemag.com/article/0305111/handling-sql-server-errors-in-nested-procedures
USE [DemoProject]
GO
/****** Object: StoredProcedure [dbo].[Customers_CRUD] Script Date: 11-Jan-17 2:57:38 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[Customers_CRUD]
#Action VARCHAR(10)
,#BId INT = NULL
,#Username VARCHAR(50) = NULL
,#Provincename VARCHAR(50) = NULL
,#Cityname VARCHAR(50) = NULL
,#Number VARCHAR(50) = NULL
,#Name VARCHAR(50) = NULL
,#ContentType VARCHAR(50) = NULL
,#Data VARBINARY(MAX) = NULL
AS
BEGIN
SET NOCOUNT ON;
--SELECT
IF #Action = 'SELECT'
BEGIN
SELECT BId , Username,Provincename,Cityname,Number,Name,ContentType, Data
FROM tblbooking
END
--INSERT
IF #Action = 'INSERT'
BEGIN
INSERT INTO tblbooking(Username,Provincename,Cityname,Number,Name,ContentType, Data)
VALUES (#Username ,#Provincename ,#Cityname ,#Number ,#Name ,#ContentType ,#Data)
END
--UPDATE
IF #Action = 'UPDATE'
BEGIN
UPDATE tblbooking
SET Username = #Username,Provincename = #Provincename,Cityname = #Cityname,Number = #Number,Name = #Name,ContentType = #ContentType,Data = #Data
WHERE BId = #BId
END
--DELETE
IF #Action = 'DELETE'
BEGIN
DELETE FROM tblbooking
WHERE BId = #BId
END
END
GO