Bulk Update stored procedure with user input (WITHOUT A DATATABLE) - c#

Can I perform a bulk update using a stored procedure that sends data to a temp table from user input which is not in a datatable.
If I have a foreach loop that takes user input such as values from a checkboxlist and text boxes what I want to know is how to parameterize those separate values in my stored procedure or if I can do it in my code. I cannot use table-valued parameters since I'm using a version of SQL that does not support it.
conn.Open();
foreach(ListItem item in CheckBoxList1.Items)
{
if(item.Selected)
{
//handling parameters in loop.
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "Update_Account_Table";
cmd.Parameters["#SeqNum"].Value = amount.Text;
cmd.Parameters["#SeqDate"].Value = DateTime.ParseExact(datepicker.Text, "mmddyyyy", CultureInfo.InvariantCulture);
cmd.Parameters["#Account_ID"].CheckBoxList1.SelectedValue;
cmd.ExecuteNonQuery();
}
conn.Close();
}
Stored procedure
CREATE TABLE TempTable
(
SeqNum int,
SeqDate datetime,
Account_ID varchar(2)
);
CREATE PROCEDURE [ACCOUNTTABLE_UPDATE]
AS
SET NOCOUNT ON
BEGIN
UPDATE AccountTable
SET SeqNum = t.SeqNum, SeqDate = t.SeqDate
FROM AccountTable AT
INNER JOIN TempTable t ON AT.AccountID = t.AccountID
END

This uses a dynamic table name in stored procedure, and sets value based on incoming parameter. You could use code below instead of temp table, or use parameters #seqnum, #SeqDate, #AcctID in place of #Stats_Value below:
USE [EODData]
GO
/****** Object: StoredProcedure [dbo].[erase_Stats] Script Date: 8/23/2016 4:32:55 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[erase_Stats]
#table varchar(25), #stats_value int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
Declare #ProductsSQL nvarchar(max);
SET #ProductsSQL = 'update ' + #table + ' set stats_completed = #Stats_Value'
exec sp_executesql #ProductsSQL
END
GO

you can add # before the table to make it temporary table
your should be like
CREATE TABLE #TempTable
will create temporary table and destroyed after process completes

Related

stored procedure returns varchar c# sql server

I need input one variable and output another
CREATE PROC CheckLogPas2
#log varchar(Max)
as
BEGIN
SET NOCOUNT ON;
DECLARE #k varchar(50);
set #k = (SELECT position From sotrud_users where login = #log);
RETURN #k;
END
in this procedure i want take in variable "k" "position". "position" is varchar. When i try use it procedure give error. I can't output variable "k" because RETURN can't output not int variable
SqlCommand sqlcmd = new SqlCommand("[CheckLogPas]", conn);
sqlcmd.CommandType = CommandType.StoredProcedure;
sqlcmd.Parameters.AddWithValue("#log", SqlDbType.Int);
sqlcmd.Parameters["#UserID"].Value = DB_values.check_log;
SqlParameter param = new SqlParameter();
param.ParameterName = "#k";
param.SqlDbType = SqlDbType.NVarChar;
param.Direction = ParameterDirection.ReturnValue;
sqlcmd.ExecuteNonQuery();
comm.Parameters.Add(param);
conn.Open();
comm.ExecuteNonQuery();
pos = param.Value;
and this my code in c#. i need to get a variable in another variable string on c#
I believe a Scalar-valued Function would solve your problem, instead of a Stored Procedure. Using this you would be able to create a function in SQL Server that accepts parameters, and can return a value. If you wish to return more than one value from your function, you would need to use a Table-valued Function instead.
Here is the structure for a Scalar-valued function:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date, ,>
-- Description: <Description, ,>
-- =============================================
CREATE FUNCTION <Scalar_Function_Name, sysname, FunctionName>
(
-- Add the parameters for the function here
<#Param1, sysname, #p1> <Data_Type_For_Param1, , int>
)
RETURNS <Function_Data_Type, ,int>
AS
BEGIN
-- Declare the return variable here
DECLARE <#ResultVar, sysname, #Result> <Function_Data_Type, ,int>
-- Add the T-SQL statements to compute the return value here
SELECT <#ResultVar, sysname, #Result> = <#Param1, sysname, #p1>
-- Return the result of the function
RETURN <#ResultVar, sysname, #Result>
END
GO
And here is how a Table-valued Function would be structured:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
CREATE FUNCTION <Inline_Function_Name, sysname, FunctionName>
(
-- Add the parameters for the function here
<#param1, sysname, #p1> <Data_Type_For_Param1, , int>,
<#param2, sysname, #p2> <Data_Type_For_Param2, , char>
)
RETURNS TABLE
AS
RETURN
(
-- Add the SELECT statement with parameter references here
SELECT 0
)
GO
Your current stored procedure:
CREATE PROC CheckLogPas2
#log varchar(Max)
as
BEGIN
SET NOCOUNT ON;
DECLARE #k varchar(50);
set #k = (SELECT position From sotrud_users where login = #log);
RETURN #k;
END
Could be re-written as a Scalar-valued function like so:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Author,,Name>
-- Create date: <Create Date, ,>
-- Description: <Description, ,>
-- =============================================
CREATE FUNCTION CheckLogPas2
(
-- Add the parameters for the function here
#log nvarchar(max)
)
RETURNS nvarchar(max)
AS
BEGIN
RETURN (SELECT position From sotrud_users where login = #log)
END
GO
Using that, you could instead have your c# code execute the following query:
SELECT [dbo].[CheckLogPas2](#log);
Like so:
// using a command to retrieve
using (SqlCommand cmd = new SqlCommand("SELECT [dbo].[CheckLogPas2](#log);", conn))
{
// format command
cmd.Parameters.Add("#log", SqlDbType.NVarChar).Value = yourLogVariable;
// get a sqlreader with the results from our query
using (SqlDataReader reader = cmd.ExecuteReader())
{
if(reader.Read())
{
string desiredStringResult = reader.GetString(0);
}
}
}

Use only one petition to server instead multiple

I have a list of CheckBoxes:
List<CheckBox> checkBoxes = new List<CheckBox>();
I want to update it via a stored procedure, so I have:
private void btnSave_Click(object sender, EventArgs e)
{
SQLConnMgr db = new SQLConnMgr();
foreach (var c in checkBoxes)
{
db.ExeSQL($"exec test #CheckBoxName = {c.Name}, #CheckBoxValue = {c.Checked} ");
}
}
Stored procedure:
CREATE OR ALTER PROCEDURE test
-- Add the parameters for the stored procedure here
#CheckBoxName VARCHAR(255),
#CheckBoxValue BIT
AS
BEGIN
SET NOCOUNT ON;
-- Insert statements for procedure here
UPDATE MyTable SET #CheckBoxName = #CheckBoxValue
END
My question is: is there another way to do this? Like sending multiple petitions in the foreach statement instead of only one at a time?
UPDATE
So to be more clear every bool is a column so I need something like:
DECLARE #CurrentCheckboxName VARCHAR(255) = (SELECT
[CheckBoxName]
FROM #CheckBoxList)
UPDATE [m]
SET
#CurrentCheckboxName = [c].[CheckBoxValue]
FROM [RedMarkItems] [m]
JOIN #CheckBoxList [c] ON [c].[CheckBoxName] = #CurrentCheckboxName
but how can iterate on each checkboxName in my DECLARE?
Depending on the version of SQL Server you are using, you could use a TABLE parameter type for your stored proc and call it only once.
CREATE TYPE dbo.MyCheckBoxValues AS TABLE(
CheckBoxName VARCHAR(255) NOT NULL,
CheckBoxValue BIT NOT NULL )
Then you modify your stored proc to use the type.
CREATE OR ALTER PROCEDURE test
-- Add the parameters for the stored procedure here
#CheckBoxList MyCheckBoxValues READONLY
AS
BEGIN
SET NOCOUNT ON;
-- Insert statements for procedure here
UPDATE m SET CheckBoxValue=c.CheckBoxValue
FROM MyTable m
JOIN #CheckBoxList c ON c.CheckBoxName=m.CheckBoxName
END
You can also use Dynamic SQL in your stored proc. For Each checkboxValues :
DECLARE #Query nvarchar(max);
SET #Query = 'UPDATE Table SET ' + #CheckboxName + '='+ #CheckBoxValue;
exec sp_executeSql #Query
Then you only have to get the values in your code.
Something like this should do it.
StringBuilder builder = new StringBuilder();
builder.Append("DECLARE #MyCheckboxes MyCheckBoxValues; ");
foreach (Guid id in _equipmentToMerge)
{
builder.Append(String.Format("INSERT INTO #MyCheckboxes (CheckBoxName, CheckBoxValue) VALUES ('{0}',{1}); ", name, ischecked));
}
builder.Append("exec dbo.test #MyCheckboxes ");
I think there is a problem with your Update statement in your stored procedure. Could you change it thusly?
Update MyCheckBoxValues SET CheckBoxValue = #CheckBoxValue Where CheckBoxName = #CheckBoxName
I don't know why you want to complicate things. Use a single connection for the loop and I can't imagine that you could have a prohibitive number of check boxes on your form. If it is still too slow, get rid of entity framework or whatever orm you are using and try dealing with the server directly.

2nd Query in SQL Stored Procedure giving me Null error

I need to run three Insert queries in SQL Server 2008 via stored procedure and expected three OUTPUT values to read in C#. In following Stored Procedure, my first query only runs and remain I am getting Null error
Cannot insert the value NULL into column
'AssessmentElectronicSignatureID'
USE [myDB]
GO
/****** Object: StoredProcedure [dbo]. [p_assessment_dfn_statementAnswer_insert] Script Date: 10/05/2015 13:24:22 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[p_assessment_dfn_statementAnswer_insert]
#StatementID AS bigint,
#StaffID AS int,
#AssessmentID As bigint,
#StatementText AS nvarchar(MAX),
#StatementDate AS Date,
#StatementAnswerID AS bigint OUTPUT,
--
#SignatureCheck AS bit,
#SignatureDate AS Date,
#ElectronicSignatureID AS bigint OUTPUT,
--
#AssessmentElectronicSignatureID AS bigint OUTPUT
AS
SET NOCOUNT ON
SET XACT_ABORT ON
-- local variables
DECLARE #l_object AS SYSNAME = OBJECT_NAME(##PROCID)
,#l_error_msg AS NVARCHAR(2000)
BEGIN TRY
BEGIN TRAN
INSERT INTO [adb_TestDb].[dbo].[Assessment_Statement_Answer]
([StatementID],[StaffID],[AssessmentID],[StatementText],[Date])
VALUES (#StatementID, #StaffID, #AssessmentID, #StatementText, #StatementDate)
SELECT #StatementAnswerID = SCOPE_IDENTITY();
IF(#StatementAnswerID>0)
BEGIN
INSERT INTO [adb_TestDb].[dbo].[Assessment_ElectronicSignature]([AssessmentID],[ElectronicSignatureCheck],[SignatureDateAndTime])
VALUES (#AssessmentID, #SignatureCheck,#SignatureDate)
SELECT #ElectronicSignatureID = SCOPE_IDENTITY();
END
IF(#ElectronicSignatureID>0)
BEGIN
INSERT INTO [adb_TestDb].[dbo].[AssessorSignature]([AssessmentElectronicSignatureID],[StatementAnswerID],[AssessorID])
VALUES(#ElectronicSignatureID, #StatementAnswerID, #AssessmentID)
SELECT #AssessmentElectronicSignatureID = SCOPE_IDENTITY();
END
COMMIT TRAN
--RETURN SCOPE_IDENTITY();
END TRY
BEGIN CATCH
-- rollback any open/uncomitted transactions
IF XACT_STATE() IN ( -1, 1) ROLLBACK TRANSACTION
-- return an error containing the object, error number and error description
SELECT #l_error_msg = 'Error number : ' + CAST(ERROR_NUMBER()AS VARCHAR) + '. ' + ERROR_MESSAGE()
RAISERROR (#l_error_msg,16,1)
END CATCH
There is a known bug with SCOPE_IDENTITY(); Occurs occasionally when triggers are used. Google for the occurances if you want to dig deep. Or...
Try changing things like
SELECT #StatementAnswerID = SCOPE_IDENTITY();
to
SELECT #StatementAnswerID = ##IDENTITY;
Or
SET #StatementAnswerID = ##IDENTITY;
and other similar assignments. I think the problem here is causing because of being the #StatementAnswerID as Null.

Calling stored procedure from another stored procedure with parameters

I have a stored procedure with takes 2 parameters (StudentID and CurrentSmester) as input and return me table with fields :
Course Code
Update Type
Update Id
This stored procedure is created by another team in my office. I can not modify it but at the same point I want to use it in my Webservice (which I am building for android) to make sure data remains consistent.
My requirement is to get :
Course Code
Update Type
Update Id
Course Title
Can I create another store procedure which will call that store procedure with parameters as I mentioned, make a join with course table to get course title too.
Is this possible ? If yes can you please guide me through its implementation.
Thanking You and Happy New Year !!
Create a new stored procedure , insert the results coming back from your existing stored procedure into a temp table, join your Course table with that temp table and you are good to go ,
something like this.....
CREATE PROCEDURE usp_NewProc
#StudentID INT ,
#CurrentSmester INT
AS
BEGIN
SET NOCOUNT ON;
IF OBJECT_ID('tempdb..#temp', 'U') IS NOT NULL
DROP TABLE #temp
CREATE TABLE #temp
(
CourseCode [DataType],
UpdateType [DataType],
Update Id [DataType]
)
INSERT INTO #temp
EXEC existsting_proc #StudentID , #CurrentSmester
SELECT t.* , C.CourseTitle
FROM #temp t INNER JOIN CourseTable C on <join Condition>
IF OBJECT_ID('tempdb..#temp', 'U') IS NOT NULL
DROP TABLE #temp
END
You can insert the results from the STORED PROCEDURE into a temp table (table variable or temp table) and them select from that table and join onto the Courses table to retrieve the title.
SQL Fiddle DEMO
Example code
CREATE TABLE Courses(
CourseCode VARCHAR(50),
CourseName VARCHAR(250)
);
INSERT INTO Courses VALUES ('A','AA'), ('B','BB');
CREATE PROCEDURE OtherTeamsSP(
#StudentID INT,
#CurrentSmester INT
)
AS
SELECT 'A' CourseCode,
'FOO' UpdateType,
1 UpdateId;
CREATE PROCEDURE MyProcedure(
#StudentID INT,
#CurrentSmester INT
)
AS
CREATE TABLE #SPOutput(
CourseCode VARCHAR(50),
UpdateType VARCHAR(50),
UpdateId INT
)
INSERT INTO #SPOutput
EXEC OtherTeamsSP #StudentID, #CurrentSmester
SELECT *
FROM #SPOutput s INNER JOIN
Courses c ON s.CourseCode = c.CourseCode
DROP TABLE #SPOutput
Calling the new SP
EXEC MyProcedure 1,2
-- First Stored Procedure
CREATE PROCEDURE FirstSP
#MyFirstParam INT
AS
DECLARE #MyFirstParamValue INT
SELECT #MyFirstParamValue = #MyFirstParam * #MyFirstParam
RETURN (#MyFirstParamValue)
GO
-- Second Stored Procedure
CREATE PROCEDURE SecondSP
#SecondParam INT
AS
DECLARE #SecondParamValue INT
SELECT #SecondParamValue = #SecondParam * #SecondParam
RETURN (#SecondParamValue)
GO
-- Pass One Stored Procedure's Result as Another Stored Procedure's Parameter
DECLARE #FirstValue INT, #SeondValue INT
-- First SP
EXEC #FirstValue = FirstSP 5
-- Second SP
EXEC #SeondValue = SecondSP #FirstValue
SELECT #SeondValue SecondSP
GO
-- Clean up
DROP PROCEDURE FirstSP
DROP PROCEDURE SecondSP
GO

Stored procedure not inserting using cursor data in SQL Server

I am creating a web page to store data which is read from a Microsoft Excel worksheet.
I am passing the data to a stored procedure in SQL Server 2008.
Here is my C# code:
SqlConnection conn = new SqlConnection(AppDB);
conn.Open();
SqlCommand command = new SqlCommand();
command.Connection = conn;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "sp_ins_TaskDetails_from_Excel";
command.Parameters.AddWithValue("#TaskDetails", dtTaskDetailsFromExcel);
string sReturnValue = command.ExecuteNonQuery().ToString();
The stored procedure has one user defined table data type as parameter.
Here is my stored procedure:
ALTER PROCEDURE dbo.sp_ins_TaskDetails_from_Excel
(
#TaskDetails TypeInsertTaskFromExcel11 readonly
)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE
#ProjectID int,
#ProjectTeamID int,
#TeamLeaderUserID int,
#TaskCategoryName varchar(max),
#TaskDescription varchar(max),
#TeamMemberUserID int,
#TaskPriorityName varchar(10),
#PlanDuration float,
#PlanStartDate datetime,
#PlanEndDate datetime,
#TaskTypeName varchar(30),
#TaskStatusName varchar(30),
#TaskAllotName varchar(10),
#CreatedBy varchar(30),
#CreatedDate datetime,
#ISMailSend bit,
#Isvisible bit,
#UniqueID int
DECLARE TMSTaskDetailFromExcelCursor CURSOR FOR SELECT
ProjectID,
ProjectTeamID,
TeamLeaderUserID,
TaskCategoryName,
TaskDescription,
TeamMemberUserID,
TaskPriorityName,
PlanDuration,
PlanStartDate,
PlanEndDate,
TaskTypeName,
TaskStatusName,
TaskAllotName,
CreatedBy,
CreatedDate,
ISMailSend,
Isvisible,
UniqueID
FROM #TaskDetails
OPEN TMSTaskDetailFromExcelCursor
FETCH NEXT FROM TMSTaskDetailFromExcelCursor INTO
#ProjectID,
#ProjectTeamID,
#TeamLeaderUserID,
#TaskCategoryName,
#TaskDescription,
#TeamMemberUserID,
#TaskPriorityName,
#PlanDuration,
#PlanStartDate,
#PlanEndDate,
#TaskTypeName,
#TaskStatusName,
#TaskAllotName,
#CreatedBy,
#CreatedDate,
#ISMailSend,
#Isvisible,
#UniqueID;
WHILE ##FETCH_STATUS=0 BEGIN
-- Insert statements for procedure here
INSERT INTO ManageTasks (ProjectID, ProjectTeamID, TeamLeaderUserID,
TaskCategoryName,TaskDescription, TeamMemberUserID, TaskPriorityName,
PlanDuration, PlanStartDate, PlanEndDate, TaskTypeName,
TaskStatusName, TaskAllotName, CreatedBy, CreatedDate, ISMailSend, Isvisible,UniqueID)
VALUES (#ProjectID, #ProjectTeamID, #TeamLeaderUserID, #TaskCategoryName,
#TaskDescription, #TeamMemberUserID, #TaskPriorityName, #PlanDuration,
#PlanStartDate, #PlanEndDate, #TaskTypeName, #TaskStatusName,
#TaskAllotName, #CreatedBy, #CreatedDate, #ISMailSend,#Isvisible,#UniqueID);
FETCH NEXT FROM TMSTaskDetailFromExcelCursor INTO
#ProjectID,
#ProjectTeamID,
#TeamLeaderUserID,
#TaskCategoryName,
#TaskDescription,
#TeamMemberUserID,
#TaskPriorityName,
#PlanDuration,
#PlanStartDate,
#PlanEndDate,
#TaskTypeName,
#TaskStatusName,
#TaskAllotName,
#CreatedBy,
#CreatedDate,
#ISMailSend,
#Isvisible,
#UniqueID;
END;
CLOSE TMSTaskDetailFromExcelCursor;
DEALLOCATE TMSTaskDetailFromExcelCursor;
END
It receives the data and using a cursor in the same stored procedure each row will be inserted using an Insert statement in the same procedure.
While executing, all the data from Excel is passed to the stored procedure as exactly mentioned in the user defined table type.
But, the values are not stored in database and the stored procedure returns -1.
All the values are in correct format and order. I don't know what is going wrong.
Is there something I should change in the stored procedures?

Categories

Resources