I have a stored procedure with custom table data type like this :
CREATE TYPE VALUE_BIGINT AS TABLE (VALUE BIGINT NOT NULL)
and this is the stored procedure code:
CREATE PROCEDURE spCalculate (#EmpIds VALUE_BIGINT READONLY)
AS
BEGIN
SELECT
*,
(ROW_NUMBER() OVER (ORDER BY VALUE)) AS RowIndex
INTO #Tmp
FROM #EmpIds
DECLARE #RowCount = ##ROWCOUNT
DECLARE #I INT = 1
WHILE #I <= #RowCount
BEGIN
--Executing query(about 2 sec long)
--!!!SEND Live Signal To C#!!!
SET #I = #I + 1
END
DROP TABLE #Tmp
END
I know that I can set infinity timeout for this stored procedure to ensure execute success but I don't want do this! Because of network issue. I want to send alive signal or something like this to sure my stored procedure is still running ("SqlCommand be patient don't throw timeout exception")
I know we can do this because SQL Server Management Studio can do this! But how?
Related
I have two stored procedures, one AddReportsApi for inserting data with a BEGIN TRANSACTION and COMMIT TRANSACTION, and the other GetReportsApi for selecting the data for inserted row.
I call the INSERT stored procedure first, then I call the SELECT stored procedure but sometimes it does not return any rows for the passed in SearchItemId which is used in the WHERE predicate.
If I execute the SELECT stored procedure a second time, it returns the expected rows.
Is there a delay in inserting the data to the table? Please note that the stored procedures are called from HangFire background job framework. From my test, HangFire should not affect the INSERT and SELECT stored procedure calls. The INSERT stored procedure is called multiple times within a minute to insert the records into the ReprotsApi table.
Insert stored procedure:
CREATE PROCEDURE [dbo].[AddReportsApi]
#OrderID nvarchar(50),
#SearchItemId nvarchar(50),
#SubjectID nvarchar(50),
#SearchType nvarchar(50),
#ApiName nvarchar(50),
#ApiRequest text,
#ApiResponse text,
#IsActive bit,
#CreatedOn datetime,
#CreatedBy nvarchar(50),
#ModifyOn datetime,
#ModifyBy nvarchar(50),
#HitType nvarchar(2)
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRANSACTION
INSERT INTO [dbo].[ReportsApi] ([OrderID], [SearchItemId], [SubjectID], [SearchType],
[ApiName], [ApiRequest], [ApiResponse], [IsActive],
[CreatedOn], [CreatedBy],
[ModifyOn], [ModifyBy], [HitType])
VALUES (#OrderID, #SearchItemId, #SubjectID, #SearchType,
#ApiName, #ApiRequest, #ApiResponse, #IsActive,
#CreatedOn, #CreatedBy,
#ModifyOn, #ModifyBy, #HitType)
IF (##ERROR != 0)
BEGIN
ROLLBACK TRANSACTION
END
ELSE
COMMIT TRANSACTION
END
SELECT stored procedure:
CREATE PROCEDURE [dbo].[GetReportsApi]
#OrderID nvarchar(50)
,#SearchItemId nvarchar(50)
,#SubjectID nvarchar(50)
,#CreatedBy nvarchar(50)
AS
BEGIN
SET NOCOUNT ON;
SELECT [Id]
,[OrderID]
,[SearchItemId]
,[SubjectID]
,[SearchType]
,[ApiName]
,[ApiRequest]
,[ApiResponse]
,[IsActive]
,[CreatedOn]
,[CreatedBy]
,[ModifyOn]
,[ModifyBy]
,[HitType]
FROM [dbo].[ReportsApi] WHERE [SearchItemId] = #SearchItemId
END
it might be because indexes are being rebuilt under the hood after the insert completes.
This can give dirty/phantom reads.
If you have an index on [SearchItemId] then the 2nd query might use this but the index may still being refreshed.
This can even affect clustered indexes if you are inserting into the middle of the B-Tree.
It might be worth sticking a sleep(10000) or WAITFOR DELAY '00:00:10'; into your code...
(That's 10 sec but you could experiment with different timings.)
Good luck!
I'm using Microsoft SQL Server 2014 and I have a stored procedure in my database called spLogin that returns a boolean to indicate whether or not login was successful.
This is the stored procedure:
USE [MyDataBase]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[spLogin]
#loginName NVARCHAR(50),
#password NVARCHAR(50)
AS
BEGIN
SET NOCOUNT ON
DECLARE #bit BIT
IF NOT EXISTS (SELECT TOP 1 User.UserID FROM User WHERE User.LoginName=#loginName)
OR RTRIM(LTRIM(#loginName)) IS NULL OR RTRIM(LTRIM(#loginName)) IS NULL
SET #bit=0
ELSE
BEGIN
DECLARE #userID INT
SET #userID= (SELECT User.UserID FROM User WHERE User.LoginName=#loginName
AND User.Password=HASHBYTES('SHA2_512', #password+CAST(User.Salt AS NVARCHAR(36))))
IF(#userID IS NULL)
SET #bit = 0
ELSE
SET #bit = 1
END
RETURN #bit
END
When I execute this stored procedure on Microsoft SQL Server 2014 Management Studio, it returns 1 if I pass the correct arguments. For example:
USE [MyDataBase]
GO
DECLARE #return_value int
EXEC #return_value = [dbo].[spLogin]
#loginName= N'adminCharles',
#password= N'admin123'
SELECT 'Return Value' = #return_value
GO
In this case, it returns the value I expected, which is 1.
But, when I use Entity Framework on a WPF project, it returns -1 even though I'm passing the correct arguments. For instance:
DataBaseEntities context = new DataBaseEntities();
var login = context.spLogin("adminCharles","admin123");
//output: -1
In that case, it outputs -1 and I just simply don't know why.
I would really appreciate some help here. Thanks in advance.
And by the way, this is just a simple project for learnign Entity Framework.
EDIT
I changed #bit BIT for INT and at the end of the stored procedure, I wrote this:
SET #bit=0
RETURN #bit
I updated my project and I'm still getting -1. Could it be a permissions issue?
I want to create a stored procedure to insert data into a table in the database, but it should be unique so I check first for the incoming parameter:
create procedure SP_Insert
#name varchar(50)
AS
if not exists (select Name from Employees where Name = #name)
begin
insert into Employess (Name)
values (#name)
end
My question is, how to tell in my code if the passing parameter hasn't been accepted as a unique value after the execution of the stored procedure?
In my form I have a button (Insert) and a textbox (name), when the user click insert the text value is passed to the stored procedure, and I want to spring a message box warning the user of duplicated entry
Use ##ROWCOUNT to determine that a row was affected and return the value as a parameter. See this answer: How can I get the number of records affected by a stored procedure?
You can do this:
insert into Employess (Name)
select #name
where not exists (select * from Employees where Name = #name)
select ##rowcount
Now the ##rowcount (returned to the caller) is either zero or one depending on whether there was an insert.
var recordsUpdated = command.ExecuteScalar();
Actually you could skip select ##rowocount and not explicitly return anything.
var recordsUpdated = command.ExecuteNonQuery();
That returns the number of affected records. I prefer to be more explicit. Someone could come behind and alter the procedure so that it does something else that changes ##rowcount. (Why? But they could.) And they might not know that something downstream is depending on that affected record count. But if it's explicit, whether a selected value or an output parameter, then someone can tell that something else depends on that value.
create procedure SP_Insert
#name varchar(50), #result bit output
AS
if not exists (select Name from Employees where Name=#name)
begin
insert into Employess (Name) Values (#name)
set #result = 1
End
else set #result = 0
Stored procedure can return a value.
You can change your SP into something like this:
create procedure SP_Insert
#name varchar(50)
AS
BEGIN
if not exists (select Name from Employees where Name=#name)
begin
insert into Employees (Name) Values (#name)
Return 0
end
else begin
Return 1
end
END
Here is the link to MSDN article with more details and examples:
[https://msdn.microsoft.com/en-us/library/ms188655.aspx]
This is my procedure :
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[uspChangeMemberRole]
#TeamID INT,
#MemberID INT,
#MemberRole TINYINT
AS
BEGIN
SET NOCOUNT ON;
UPDATE [dbo].[TeamMember]
SET MemberRole = #MemberRole
WHERE TeamID = #TeamID
AND MemberID = #MemberID;
RETURN #MemberRole;
END
When I execute this procedure I want to return "MemberRole Successfully Changed".
Please give me a solution how to return
Use Row Count to check if there are affected rows (identified if update is successful) then select a string.
RowCount - Returns the number of rows affected by the last statement.
IF ##ROWCOUNT > 0
BEGIN
SELECT 'Member Role Successfully Chnaged';
END
And I think this statement is not necessary since this is an input parameter, you can get outside the proc.
return #MemberRole;
Change your return to select, and replace the datatype of your output parameter with varchar.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[uspChangeMemberRole]
#TeamID INT,
#MemberID INT,
#MemberRole VARCHAR(100) OUTPUT
AS BEGIN
SET NOCOUNT ON;
UPDATE [dbo].[TeamMember] SET MemberRole=#MemberRole WHERE TeamID=#TeamID AND MemberID=#MemberID;
SET #MemberRole = 'MemberRole Successfully Changed.'
SELECT #MemberRole AS 'RETURN';
I am adding some of the concept that will help you to understand how Procedure's will return values.
If you want to return something from SQL Server to Frontend, Just use "select" statement.
You have to use proper command from frontend like you want to return scalar value, or query.
I have various stored procedures. I need a stored procedure to execute a stored procedure and then return only the row count (number of returned rows by the called procedure) and I need to receive it in c# code.
What's the best way to do this?
Assuming you are using SQL Server (which is possible from the code snippets), perhaps something like this would work for you:
exec('exec <your stored procedure goes here>; select ##RowCount')
Since you are running SQL Server, I can think of one solution that is not necessarily pretty.
Create a temporary table (table variable if you have a more recent version of SQL Server). Then execute:
exec(`
declare #t table (
<columns go here>
);
insert into #t
exec(''<your exec here>'');
select #rowcount
');
And now that I've said that, I would recommend sp_executesql. This goes something like this:
declare #sql nvarchar(max) = N'exec '+#YOURQUERY + '; set #RowCount = ##RowCount';
exec sp_executesql #sql, N'#RowCount int output', #RowCount = RowCount output;
I spent most of yesterday debugging an arcane condition that arises when you call a stored procedure inside an insert.
You can try this in your child stored procedure :
CREATE PROC PawanXX
(
#a INT
,#b INT OUTPUT
)
AS
BEGIN
SELECT TOP 2 * FROM X
SET #b = ##ROWCOUNT
RETURN #b
END
GO
The main stored procedure where we call all other sps
DECLARE #RC int
DECLARE #a int
DECLARE #b int
EXECUTE #RC = [dbo].[PawanXX]
#a
,#b OUTPUT
SELECT #RC
The output for the same
ProcessName Parent Child
ShareDrafts Job12 Job03
ShareDrafts Job13 Job58
(2 row(s) affected)
2
(1 row(s) affected)