I created my DB with microsoft sql server 2012 and now I need to get a value from procedure I'm using this query :
begin try
begin tran
-- Insert statements for procedure here
Insert Into dbo.parents
(FatherFirstName,FatherLastName,MotherFirstName,MotherLastName,ParentIdNum,VolunteerId,Address)
values
(#FFname,#FLname,#MFname,#MLname,#IDnum,#VolunteerId,#add)
set #returnVal = 'good'
commit tran
end try
begin catch
rollback tran
set #returnVal = 'error!'
end catch
and then I use :
declare #param sysname
exec dbo.uspCreateNewParents 1,'xxxxx','xxxxx','xxxxx','xxxxx','xxxxx','xxxxx',#param
select #param
and all I get is null values and the column name is the value of #param....
please help me how can I retrieve the value of the variable ??!
Related
I need to create two procedures in a SQL Server transaction. If failure, I need to rollback the create(s) and any other executed queries in this transaction. I know the create statement must be the first statement in query batch, but I need to know how handle the transaction with multiple batches.
BEGIN TRANSACTION
CREATE PROCEDURE [dbo].[SP_SP-1]
#id BIGINT
AS
BEGIN
SET NOCOUNT ON;
-- SQL statements
END
GO
CREATE PROCEDURE [dbo].[SP_SP-2]
#id BIGINT
AS
BEGIN
SET NOCOUNT ON;
-- SP-2 statements
END
GO
UPDATE Table
SET Value = '1.0.0.5'
COMMIT TRANSACTION / ROLLBACK TRANSACTION
Below is one method to execute multiple batches in a transaction. This uses a temp table to indicate if any batch erred and perform a final COMMIT or ROLLLBACK accordingly.
Another method is to encapsulate statements that must be in single-statement batch (CREATE PROCEDURE, CREATE VIEW, etc.) but that can get rather ugly when quotes within the literal text must be escaped.
CREATE TABLE #errors (error varchar(5));
GO
BEGIN TRANSACTION
GO
CREATE PROCEDURE [dbo].[USP_SP-1]
#id bigint
AS
BEGIN
SET NOCOUNT ON;
-- SP Statments
END;
GO
IF ##ERROR <> 0 INSERT INTO #errors VALUES('error');
GO
CREATE PROCEDURE [dbo].[USP_SP-2]
#id BIGINT
AS
BEGIN
SET NOCOUNT ON;
-- SP-2 Statments
END;
GO
IF ##ERROR <> 0 INSERT INTO #errors VALUES('error');
GO
UPDATE Table SET Value='1.0.0.5'
GO
IF ##ERROR <> 0 INSERT INTO #errors VALUES('error');
GO
IF EXISTS(SELECT 1 FROM #errors)
BEGIN
IF ##TRANCOUNT > 0 ROLLBACK;
END
ELSE
BEGIN
IF ##TRANCOUNT > 0 COMMIT;
END;
GO
IF OBJECT_ID(N'tempdb..#errors', 'U') IS NOT NULL
DROP TABLE #errors;
GO
I suggest you to study more about this subject in Handling Transactions in Nested SQL Server Stored Procedures.
From the beginning, your syntax is wrong. You cannot begin a transaction and then create a procedure, you need to do just the opposite:
CREATE PROCEDURE [dbo].[SP_SP-1]
#id bigint
AS
BEGIN
BEGIN TRY
BEGIN TRANSACTION
SET NOCOUNT ON;
-- SP-2 Statments
Update Table set Value='1.0.0.5'
END TRY
BEGIN CATCH
--handle error and perform rollback
ROLLBACK
SELECT ERROR_NUMBER() AS ErrorNumber
SELECT ERROR_MESSAGE() AS ErrorMessage
END CATCH
END
It is best practice to use TRY and CATCH when attempting to perform update inside transaction scope.
Please read more and investigate using the link I provided to get a bigger picture.
To use Transaction, you need to know what is the meaning of transaction. It's meaning of 'Unit of work either in commit state or rollback state'.
So when you use transaction, you must know that where you declare and where you close. So you must start and end transaction in the parent procedure only than it will work as a unit of work i.e. whatever no of query execute of DML statement, it uses the same transaction.
I do not understand why your update statement outside of procedure and transaction portion too.
It should be (See my comments, you can use TRY Catch same as c sharp) :
Create PROCEDURE [dbo].[SP_SP-1]
#id bigint
AS
BEGIN
Begin Transaction
SET NOCOUNT ON;
-- SP Statments
Exec SP_SP-2 #id --here you can pass the parameter to another procedure, but do not use transaction in another procedure, other wise it will create another transaction
If ##Error > 0 than
Rollback
Else
Commit
End
END
GO
--Do not use transaction in another procedure, otherwise, it will create another transaction which has own rollback and commit and do not participate in the parent transaction
Create PROCEDURE [dbo].[SP_SP-2]
#id BIGINT
AS
BEGIN
SET NOCOUNT ON;
-- SP-2 Statments
END
GO
i find this solution to execute the procedure as string execution , it`s a workaround to execute what i want
Begin Try
Begin Transaction
EXEC ('
Create PROCEDURE [dbo].[SP_1]
#id bigint
AS
BEGIN
SET NOCOUNT ON;
SP-1
END
GO
Create PROCEDURE [dbo].[SP_Inc_Discovery_RunDoc]
#id bigint
AS
BEGIN
SET NOCOUNT ON;
Sp-2
END')
Update Table set Value='1.0.0.5'
Commit
End Try
Begin Catch
Rollback
Declare #Msg nvarchar(max)
Select #Msg=Error_Message();
RaisError('Error Occured: %s', 20, 101,#Msg) With Log;
End Catch
I have a stored procedure called clients with 3 parameters: the first one for user input, and the last two are OUTPUT parameters.
This is the code:
CREATE PROCEDURE clients
(#name NVARCHAR(100),
#id_client int OUTPUT,
#messg varchar(1) OUTPUT)
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
BEGIN TRAN
IF NOT EXISTS (SELECT name FROM client WHERE name = #name)
BEGIN
INSERT INTO client(name) VALUES (#name);
SET #id_client = SCOPE_IDENTITY();
SET #messg = 'o'
COMMIT TRAN
END
ELSE
BEGIN
SELECT #id_client = id_client
FROM client
WHERE name = #name;
SET #messg = 'o'
COMMIT TRAN
END
END TRY
BEGIN CATCH
SET #messg = 'e'
ROLLBACK TRAN
END CATCH
END
I need to call this stored procedure from another the second one is called updateS, and I'm trying the following:
CREATE PROCEDURE updateS
(#clientname VARCHAR(100))
AS
BEGIN
SET NOCOUNT ON;
DECLARE #id INT;
DECLARE #msg VARCHAR(1);
EXEC clients #clientname, #id, #msg; --Problem here to retrieve the id
END
This stored procedure has a parameter for the name of the client, but I need to retrieve the id of the client, but it doesn't work as I'm trying.
Basically I need to get the id and use it in the second stored procedure.
Any question post on comments.
You need to specify OUTPUT when you execute the stored procedure as well as when you define it:
EXEC clients #clientname, #id OUTPUT, #msg OUTPUT;
Did you miss the output keyword while passing the parameter to the stored procedure? Moreover, I would change the clients stored procedure and make the parameter as char(1) rather like #messg char(1) OUTPUT
I have a stored procedure with Dynamic SQL. Is it possible to include a batch of dynamic SQL inside an explicit transaction with COMMIT or ROLLBACK depending on the value of ##ERROR?
Following similar stored procedure. It is simplified in order to demonstration purpose.
CREATE PROCEDURE [dbo].[sp_Example]
AS
BEGIN
BEGIN TRANSACTION
DECLARE #ID VARCHAR(10)
INSERT INTO [dbo].[Deparment] (Name,Location,PhoneNumber) VALUES ('DeparmentName','DeparmentLocation','0112232332')
SELECT #ID =SCOPE_IDENTITY()
IF ##ERROR <> 0
BEGIN
ROLLBACK
RAISERROR ('Error in Inserting Deparment.', 16, 1)
RETURN
END
SET #InsertQuery = '
DECLARE #Name varchar(100)
SELECT #Name = Name
FROM dbo.[Deparment]
WHERE DepartmentId= ''' + #ID +'''
INSERT INTO [dbo].[Employee](Name,Age,Salary,DepartmentName)VALUES(''EMPLOYEE NAME'',''25'',''200000'','''+#NAME'')''
EXEC(#InsertQuery)
IF ##ERROR <> 0
BEGIN
ROLLBACK
RAISERROR ('Error in Inserting Employee.', 16, 1)
RETURN
END
COMMIT
END
Does outer Transaction scope applies to Dynamic query ?
The "outer" transaction will apply to everything that is executed. There is no way in SQL Server to not execute under the running transaction (which can be annoying of you want to log errors).
I am working on a project and am using stored procedure. I'm getting this error:
Line: 939
Error: Sys.WebForms.PageRequestManagerServerErrorException: Invalid object name 'IT_Assets'.
Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 0, current count = 1.
Please find below my stored procedure code:
alter PROCEDURE [ITAssets_sp_IT_Assets]
-- Add the parameters for the stored procedure here
(#Mode varchar(12)='ADD',
#ID integer , #AssetCode nvarchar(20)=null, #Description nvarchar(70)=null,
#Site nvarchar(10)=null)
AS
Begin
IF #Mode='ADD'
Begin
Begin Tran
INSERT INTO [IT_Assets]
([ID]
,[AssetCode]
,[Description]
,[Site])
values
(#ID, #AssetCode, #Description, #Site
)
If ##ERROR <> 0
ROLLBACK TRAN
Else
COMMIT TRAN
Select #ID
End
ELSE
Begin
Begin Tran
UPDATE [IT_Assets]
SET
AssetCode = #AssetCode, Description = #Description, Site = #Site
WHERE ID = #ID
If ##ERROR <> 0
ROLLBACK TRAN
Else
COMMIT TRAN
Select #ID
End
End
I didn't understand the error and I don't know exactly where is the problem? Would someone please help me in sloving this problem?
From the error Invalid object name 'IT_Assets' I believe that the table/view 'IT_Assets' is present in a diferent database than the stored procedure (assuming that the object exist and you are using the correct name).
Then you need to fully quaify it wih Db name like
UPDATE [DB_NAME].[dbo].[IT_Assets] (assuming `dbo` is the owner)
Try using your database name at top of procedure using use statement like
use [DB_NAME]
GO
alter PROCEDURE [ITAssets_sp_IT_Assets]
-- Add the parameters for the stored procedure here
(#Mode varchar(12)='ADD',
...
Also change you transaction handling using TRY .. CATCH consruct like below
Begin Tran
BEGIN TRY
INSERT INTO [IT_Assets]
([ID]
,[AssetCode]
,[Description]
,[Site])
values
(#ID, #AssetCode, #Description, #Site);
COMMIT TRAN;
END TRY
BEGIN CATCH
ROLLBACK TRAN ;
END CATCH
I'm creating a stored procedure that will create 3 triggers (insert, update, delete) given a table name.
Here is an example to illustrate the issue I'm experiencing :
CREATE PROCEDURE [dbo].[sp_test]
AS
BEGIN
BEGIN TRAN
-- Create trigger 1
DECLARE #sql NVARCHAR(MAX) = 'CREATE TRIGGER test1 ON TableXML AFTER INSERT AS BEGIN END'
EXEC sp_executesql #sql
-- Create trigger 2, but this one will fail because Table_1 contain an ntext field.
SET #sql = 'CREATE TRIGGER test1 ON Table_1 AFTER INSERT AS
BEGIN
select * from inserted
END'
EXEC sp_executesql #sql
COMMIT TRAN
END
So I thought that wrapping the call in a transaction, the first trigger won't be created. Since the second will fail. BUT the first trigger is created anyway .... How can I prevent this from happening. I want the whole thing to be atomics.
Try this, with BEGIN TRY
CREATE PROCEDURE [dbo].[sp_test]
AS
BEGIN
BEGIN TRY
BEGIN TRAN
DECLARE #sql NVARCHAR(MAX) = 'CREATE TRIGGER test1 ON TableXML AFTER INSERT AS BEGIN END'
EXEC sp_executesql #sql
SET #sql = 'CREATE TRIGGER test1 ON Table_1 AFTER INSERT AS
BEGIN
select * from inserted
END'
EXEC sp_executesql #sql
COMMIT TRAN
END TRY
BEGIN CATCH
RAISERROR('Errormessage', 18, 1)
ROLLBACK TRAN
END CATCH
END
You have no error handling or rollback statement in your procedure.
In some databases, DDL statements such as CREATE TRIGGER will automatically commit themselves; if sql-server is one of them, you can't. (This is true of Oracle and MySQL; not true of RDB; not sure about sql-server.)
You don't have a Rollback call on an error.
Using SQL Server's Try/Catch, you could do something like what Vidar mentioned, or you if Sql Server automatically commits triggers (as Brian H mentioned as a posibility) you could instead have in your Catch block:
BEGIN CATCH
RAISERROR('Errormessage', 18, 1)
DROP Trigger test1
END CATCH