Output parameter used to insert a row in same table - asp.net

Thanks for your help Guys
I am working on a Asp.net based project and my requiremnent is to generate a PARTNO with the combination of MaterialType+ProductID and - 4digit random number
NOTE: ProductID is Primary key and also set it to output parameter
for example If material type is 500 and product ID generated 55 and random no generated 5434, then part no become 555-5434
Now my question is how could I store partno in same table, I am somewhat trying like that
Connection.Open()
Dim trn As SqlClient.SqlTransaction
trn = Connection.BeginTransaction
Using trn
Dim sqlcode As New SqlParameter("#ProductID", Products.ProductID)
sqlcode.Direction = ParameterDirection.InputOutput
Using Command As New SqlCommand("Product_Write", Connection, trn)
Command.CommandType = CommandType.StoredProcedure
Command.Parameters.Add(sqlcode) Command.Parameters.AddWithValue("#MaterialType", Materialtype.MaterialTypeCode)
Command.Parameters.AddWithValue("#CategoryID", category.CategoryId)
Command.Parameters.AddWithValue("#ProductName", Products.ProductName)
Command.Parameters.AddWithValue("#ProductDescription", Products.ProductDescription)
Command.Parameters.AddWithValue("#ProductActive", Products.ProductActive)
Command.Parameters.AddWithValue("#ProductImage", Products.ProductImage)
Command.Parameters.AddWithValue("#PartNo", 0)
Command.ExecuteNonQuery()
Products.ProductID = CInt(sqlcode.Value)
'Insert the part no
Dim random As New Random()
Dim value As Integer = random.Next(9999)
Dim PartNo As String = CType((Materialtype.MaterialTypeCode + Products.ProductID).ToString + "-" + value.ToString, String)
'Dont know what to do
trn.Commit()
Connection.Close()
End Using
End Using
End Using
Return Products
End Function
ALTER PROCEDURE [dbo].[Product_Write]
#ProductID bigint OUTPUT,
#MaterialType int,
#CategoryID bigint,
#ProductName VARCHAR(MAX),
#ProductDescription VARCHAR(MAX),
#ProductActive Bit,
#ProductImage VARCHAR(MAX),
#PartNo VARCHAR(30)
AS
IF (#ProductID=0)
BEGIN
INSERT INTO T_Product(
MaterialType,
CategoryID,
ProductName,
ProductDescription,
ProductActive,
ProductImage,
PartNo)
VALUES(
#MaterialType,
#CategoryID,
#ProductName,
#ProductDescription,
#ProductActive,
#ProductImage,
#PartNo)
SET #ProductID=SCOPE_IDENTITY()
END
ELSE
UPDATE T_Product SET
MaterialType=#MaterialType,
CategoryID=#CategoryID,
ProductName=#ProductName,
ProductDescription=#ProductDescription,
ProductActive=#ProductActive,
ProductImage=#ProductImage,
PartNo=#PartNo
WHERE ProductID=#ProductID
Please help me out
Thanks

If you can update the Stored Procedure you would need something along these lines
declare #id int
set #id = SCOPE_IDENTITY()
UPDATE <Table> Set PartNo = MaterialType + convert(varchar(max),#id) + convert(varchar(4),CEILING(9999*RAND())) Where ID = #id

Related

SQL Server procedure has too many arguments specified

I get the error
Procedure or function has to many arguments specified
but only sometimes. It's a REST API and cellphones call this function to validate the user. Today it's onli 1-2 cellphones and they make the call every second minute.
It works well most times but sometimes I get this error code.
To see what's wrong, I've made a small loop that gathers the parameters into a string. And sometimes they are two #GUID and #Datum and sometimes repeat themselves.
Here is the VB code:
Public Shared Sub validatePhone(secretKey As String, ByRef _RS As phoneData, Fnr As Integer)
Dim connStr As String = System.Configuration.ConfigurationManager.AppSettings("ConnStringSQL")
Dim Conn As SqlConnection = New System.Data.SqlClient.SqlConnection(connStr)
Dim _theString As New System.Text.StringBuilder
Try
_RS.message = ""
_RS.status = True
Dim Status As Integer = 0
Dim _GUID As Guid = New Guid(secretKey)
Try
Conn.Open()
Catch ex As Exception
End Try
cmd.Connection = Conn
Apt.SelectCommand = cmd
cmd.CommandType = CommandType.StoredProcedure
cmd.CommandText = "API2017_checkPhone"
cmd.Parameters.Clear()
cmd.Parameters.Add("#GUID", SqlDbType.UniqueIdentifier).Value = _GUID
cmd.Parameters.Add("#Datum", SqlDbType.SmallDateTime).Value = Now
For Each item As SqlParameter In cmd.Parameters
_theString.Append(item.ParameterName & ";")
Next
Apt.Fill(ds, "DataCheckPhone")
If ds.Tables("DataCheckPhone").Rows.Count > 0 Then
With ds.Tables("DataCheckPhone").Rows(0)
Status = .Item("spStatus")
If Status = 0 Then
_RS.Namn = .Item("Namn")
_RS.SalesID = .Item("SalesID")
_RS.Anlaggning = .Item("Anlaggning")
_RS.Anlnr = .Item("Anlnr")
Funktions.URLEncodeStr(_RS.Namn)
Funktions.URLEncodeStr(_RS.Anlaggning)
End If
End With
Else
Dim _Lnum As Integer
Funktions.Logg(Fnr & ": " & "Fatal error", 999, _Lnum, 0)
_RS.message = "Error 999:" & _Lnum.ToString
Return
End If
Catch ex As Exception
_RS.status = False
_RS.Anlaggning = Nothing
_RS.Anlnr = 0
_RS.Namn = Nothing
_RS.SalesID = Nothing
Dim _Lnum As Integer
Funktions.Logg(Fnr & ": " & ex.Message & "{" & _theString.ToString & "}", 999, _Lnum, 0)
_RS.message = "Error 999:" & _Lnum.ToString
Finally
ds.Tables.Clear()
Try
ds.Tables("DataCheckPhone").Dispose()
Catch ex As Exception
End Try
End Try
Try
Conn.Close()
Conn.Dispose()
Catch ex As Exception
End Try
End Sub
And here is the stored procedure:
ALTER PROCEDURE [dbo].[API2017_checkPhone]
#GUID as uniqueidentifier,
#Datum as smalldatetime
AS
DECLARE #Status AS INT
DECLARE #Anlaggning AS NVARCHAR(50)
DECLARE #Namn AS NVARCHAR(50)
DECLARE #Anlnr AS INT
DECLARE #SalesID AS uniqueidentifier
DECLARE #LockedSalesman AS BIT
DECLARE #LockedAnlaggning AS BIT
SET #Status = 0
IF EXISTS (SELECT * FROM KK2017_connectedPhones WHERE [guid] = #guid)
BEGIN
SET #status = 0
SET #salesID = (SELECT salesID FROM KK2017_connectedPhones
WHERE [guid] = #guid)
SET #Anlnr = (SELECT anlnr FROM KK2017_Säljare WHERE salesID = #salesID)
SET #Namn = (SELECT Namn FROM KK2017_Säljare WHERE salesID = #salesID)
SET #Anlaggning = (SELECT namn FROM KK2017_Anlaggning WHERE anlnr = #Anlnr)
SET #LockedSalesman = (SELECT locked FROM KK2017_Säljare WHERE salesID = #salesID)
UPDATE KK2017_Säljare
SET inloggad = #Datum
WHERE salesID = #SalesID
IF #LockedSalesman = 1
BEGIN
SET #Status = 2
END
SET #LockedAnlaggning = (SELECT locked FROM KK2017_Anlaggning
WHERE AnlNr = #Anlnr)
IF #LockedAnlaggning = 1
BEGIN
SET #status = 3
END
END
ELSE
SET #status = 1
SELECT
#Status AS spStatus,
#Anlaggning AS Anlaggning,
#anlnr AS anlnr,
#Namn AS namn,
#SalesID AS salesID
I must have done something wrong but can not see it.
If anyone has a proposal, I would be grateful.
/Claes
You have a threading issue because you have defined cmd as shared, which means there is only one instance servicing all of the incoming requests. Sometimes two threads are in the process of adding parameters at the same time, and both threads end up with four, hence the error.
The standard pattern here would be declare cmd as a local variable, and instantiate a new instance each time the function is called. The overhead to this is negligible.
Also, avoid shared variables in multithreaded applications (such as web services). There is only one copy of the variable for all users and all threads, and 99% of the time that is not what you actually want. For the other 1% usually you'd use application variables or HttpCache. In this case you should use a local variable.

Stored procedure doesn't return output

I have a simple stored procedure which inserts a users record in a table and should give out its userid.
Here is the stored procedure:
Alter proc spRegistration
#UserId nvarchar(10) output,
#Name nvarchar(20),
#EmailAdd nvarchar(20)
as
begin
Declare #Count int;
Declare #ReturnCode int
Select #Count = Count(EmailAdd)
from tblAllUsers
where EmailAdd = #EmailAdd
if #Count > 0
begin
Set #ReturnCode = -1
end
else
begin
Set #ReturnCode = 1
Insert into tblAllUsers(Name, EmailAdd)
values(#Name, #EmailAdd)
end
Select #UserId = UserId
from tblAllUsers
where EmailAdd = #EmailAdd
Select #ReturnCode as ReturnCode
end
I try to get the userid into a textbox like below :
string CS = ConfigurationManager.ConnectionStrings["hh"].ConnectionString;
using (SqlConnection con = new SqlConnection(CS))
{
con.Open();
SqlCommand cmd = new SqlCommand("spRegistration", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#Name", txtName.Text);
cmd.Parameters.AddWithValue("#EmailAdd", txtEmailAddress.Text);
var UserID = cmd.Parameters.AddWithValue("#UserId", SqlDbType.NVarChar);
UserID.Direction = ParameterDirection.Output;
int ReturnCode = (int)cmd.ExecuteScalar();
if (ReturnCode == -1)
{
lblRegMessage.Text = "This email has already been registered with us.";
}
else
{
lblRegMessage.Text = "You were registered successfully.";
txtUserId.Text=(String)UserID.Value;
}
The table as well as the stored procedure is far too complex,I have simplified it for better understanding of problem.UserId is Alphanumeric.Dont worry about that.
Putting a break point shows a null against var UserID
Where am i going wrong?
You need to Use .ToString() on UserID
txtUserId.Text= UserID.Value.ToString();
EDIT:
var UserID = cmd.Parameters.AddWithValue("#UserId", SqlDbType.NVarChar,50);

Stored Procedure Variable (Code error I believe is there)

I am trying to create a script to tidy all the columns and rows in SQL Server (I will be doing more than trimming but once it works I can plug into app-code I have already)
I think I am there but it does not seem to update - maybe the stored procedure is wrong? I believe the error is here.. -- I have looked around about variables in stored procedures and think it looks correct to me.
Insert statements for procedure here
UPDATE systemUsers
SET #ColumnName = #Update
WHERE ID = #ID
Full script...
Protected Sub btnTest_Click(sender As Object, e As System.EventArgs) Handles btnTest.Click
'Select the column names
Dim cn As SqlConnection = New SqlConnection()
Dim cmd As SqlCommand = New SqlCommand()
Dim dr As SqlDataReader
Dim i As Integer = 0
cn.ConnectionString = ConfigurationManager.ConnectionStrings("mySQLConnectionString").ConnectionString
cmd.Connection = cn
' this gets the colum name
cmd.CommandText = "select COLUMN_NAME FROM INFORMATION_SCHEMA.Columns where TABLE_NAME = 'systemUsers'"
'Open the connection to the database
cn.Open()
' Execute the sql.
dr = cmd.ExecuteReader()
' Read all of the rows generated by the command (in this case only one row).
CheckBoxList1.Items.Clear() 'remove all items for the new list
Do While dr.Read()
i = i + 1
Session.Item("ColumnName" & i) = dr.Item("COLUMN_NAME").ToString()
Loop
' Close your connection to the DB.
dr.Close()
cn.Close()
Dim j As Integer = 1
For j = 1 to i
cn.ConnectionString = ConfigurationManager.ConnectionStrings("mySQLConnectionString").ConnectionString
cmd.Connection = cn
cmd.CommandText = "Select * From [systemUsers]"
'Open the connection to the database
cn.Open()
' Execute the sql.
dr = cmd.ExecuteReader()
' Read all of the rows generated by the cmd (in this case only one row).
Dim vName As String = ""
If vName = "ID" Then
'skip as ID should never be edited!!
Else
Do While dr.Read()
vName = Session.Item("ColumnName" & j).ToString ' put into vName for Stored Procedure
Dim sConnString As String = System.Web.Configuration.WebConfigurationManager.ConnectionStrings("mySQLConnectionString").ConnectionString
Dim dsNames As SqlDataSource
dsNames = New SqlDataSource
dsNames.ConnectionString = sConnString
Dim sSQL As String
sSQL = "SPTidy"
dsNames.UpdateCommand = sSQL
dsNames.UpdateCommandType = SqlDataSourceCommandType.StoredProcedure
dsNames.UpdateParameters.Clear()
dsNames.UpdateParameters.Add("ID", dr.Item("ID").ToString())
dsNames.UpdateParameters.Add("Update", Trim(dr.Item(vName).ToString()))
dsNames.UpdateParameters.Add("ColumnName", vName)
dsNames.Update()
dsNames = Nothing
Loop
End If
j = j + 1
' Close your connection to the DB.
dr.Close()
cn.Close()
Next
End Sub
Stored procedure:
create PROCEDURE [dbo].[SPTidy]
#ID bigint,
#Update nvarchar(max),
#ColumnName nvarchar(max)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
UPDATE systemUsers
SET #ColumnName = #Update
WHERE ID = #ID
END
That code won't throw an error message because it's simply updating the variable. To have a dynamic column name you need to use dynamic SQL (or complicated case statements) but dynamic SQL is better in this instance.
DECLARE #sql nvarchar(max) = '';
SET #sql = N'UPDATE systemUsers SET ' + #ColumnName + N' = ' + #Update + N' WHERE ID=' + #ID
EXEC sp_executesql #sql
Hope this helps :)

How to pass concatenated value of drop down to stored proc as parameter

I have a drop down where in the values are concatenated from two columns of a table, now I will use the value of that drop down as a parameter to another stored procedure, is this possible? How will I do that?
This is my code
CREATE PROCEDURE [dbo].[Reassign]
#recordumber int
#employeeName
AS
BEGIN
UPDATE QR
SET QR.QAMemberID = #QAMemberID
FROM Roster AS QR
INNER JOIN TeamMaster S TM
ON QR.QAMemberID = TM.QAMemberID
WHERE QR.recordNumber = #recordumber
and qr.firstname, qr.lastname = #employeeName
END
and qr.firstname, qr.lastname = #employeeName I know this last piece of code is wrong... how can I do this the right way? Thank you...
Do not concatenate the values together in your code, but rather use a parameter for firstName and a parameter for lastName, like this:
CREATE PROCEDURE [dbo].[Reassign]
#recordumber int,
#firstName,
#lastName
AS
BEGIN
UPDATE QR
SET QR.QAMemberID = #QAMemberID
FROM Roster AS QR
INNER JOIN TeamMaster S TM
ON QR.QAMemberID = TM.QAMemberID
WHERE QR.recordNumber = #recordumber
and qr.firstname = #firstName, qr.lastname = #lastName
END
To use the value from your drop down you can use this in the code behind
if (myDropDown.SelectedIndex != 0)
{
var myData = myDropDown.SelectedValue;
// access Sproc and you can then pass myData
}
You can use qr.firstname + ' ' + qr.lastname = #employeeName if you concatenated that fields with space.
...
and qr.firstname + ' ' + qr.lastname = #employeeName
...
But it's better to pass two parameters into the procedure:
CREATE PROCEDURE [dbo].[Reassign]
#recordumber int
#firstname,
#lastname
AS
...
and qr.firstname = #firstname and qr.lastname = #lastname
...

Stored Procedure fails to see parameters or returns a convert data type error

I've run into a rather annoying problem which I cannot seem to get to the root of.
I've searched the internet for similar problems - and I've found a few unanswered in other forums - so I thought I'd give it a go here.
The following WebMethod of a webservice contacts a database, which works fine, and runs a stored procedure.
The problem is, that when I pass the parameters as single characters it tells me it cannot find either of the parameters and when I pass a full length "ean" parameter it tells me the following error message:
System.Data.OleDb.OleDbException: Error converting data type varchar to int.
at System.Data.OleDb.OleDbDataReader.ProcessResults(OleDbHResult hr)
at System.Data.OleDb.OleDbDataReader.NextResult()
at System.Data.OleDb.OleDbCommand.ExecuteReaderInternal(CommandBehavior behavior, String method)
at System.Data.OleDb.OleDbCommand.ExecuteReader(CommandBehavior behavior)
at System.Data.OleDb.OleDbCommand.ExecuteReader()
at Service.GetOthersRatings(Int32 personID, String ean)
And now here's the Webmethod:
[WebMethod(Description = "GetRatings")]
public string GetRatings(int personID, string ean)
{
string ratings = "";
OleDbConnection connection = new OleDbConnection(connectionString);
OleDbCommand command = new OleDbCommand("GetRatings", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#personID",OleDbType.Integer,10).Value = personID;
command.Parameters.Add("#ean",OleDbType.VarChar,30).Value = ean;
try
{
connection.Open();
myReader = command.ExecuteReader();
if (myReader.HasRows)
{
while (myReader.Read())
{
ratings = myReader.GetString(0);
}
}
else
{
ratings = "Null";
}
}
catch (Exception e)
{
ratings = "Error - " + e.ToString();
}
finally
{
}
return ratings;
}
One thing that's worth mentioning is that if I remove the OUTPUT part of the SP, it runs fine down to and returns
ratings = "Null";
But seeing that I try to read a String from the reader, I don't see why it wouldn't work with a varchar output from the SP.
In the Database we have the corresponding Stored Procedure, which works fine if just executed in SQL Server Management Studio:
IF ( OBJECT_ID('GetRatings') IS NOT NULL )
DROP PROCEDURE GetRatings
GO
CREATE PROCEDURE GetRatings
#ratingschars varchar(36) = NULL OUTPUT,
#personID int,
#ean varchar(30)
AS
BEGIN TRAN
SET NOCOUNT ON;
BEGIN
DECLARE #pris varchar(2)
DECLARE #forventet varchar(2)
DECLARE #smag varchar(2)
DECLARE #count varchar(30)
IF EXISTS(SELECT * FROM feedback where personID = #personID AND ean = #ean)
BEGIN
SELECT #pris = (SELECT CAST(pris AS varchar(2)) FROM feedback where personID = #personID AND ean = #ean)
SELECT #forventet = (SELECT CAST(forventet AS varchar(2)) FROM feedback where personID = #personID AND ean = #ean)
SELECT #smag = (SELECT CAST(smag AS varchar(2)) FROM feedback where personID = #personID AND ean = #ean)
SELECT #ratingschars = #pris + #forventet + #smag
END
ELSE
BEGIN
SELECT #pris = (SELECT CAST(avg(pris) AS varchar(2)) FROM feedback WHERE ean = #ean)
SELECT #forventet += (SELECT CAST(avg(forventet) AS varchar(2)) FROM feedback WHERE ean = #ean)
SELECT #smag += (SELECT CAST(avg(smag) AS varchar(2)) FROM feedback WHERE ean = #ean)
SELECT #count += (SELECT CAST(count(*) AS varchar(30)) FROM feedback WHERE ean = #ean)
SELECT #ratingschars = #pris + #forventet + #smag + #count
END
END
COMMIT TRAN
Which I've tried to change to output of to int, with the same error results.
I'm stumped - I need help.
Stored-procedure has three parameters where as in your code, you've added only two parameters. So add a third parameter as OutPut type.
EDIT:
Stored Procedure:
ALTER PROCEDURE SampleProc
#no1 int,
#no2 int,
#result int OUTPUT
AS
set #result=#no1+#no2
RETURN
Code to execute the Stored-procedure:
cmd.CommandText = "SampleProc"
cmd.CommandType = CommandType.StoredProcedure
cmd.Connection = cn
Dim no1 as New OleDbParameter("#no1", OleDbType.Integer)
Dim no2 as New OleDbParameter("#no2", OleDbType.Integer)
Dim resultas New OleDbParameter("#result", OleDbType.Integer)
result.Direction = ParameterDirection.Output
no1.Value = 10
no2.Value = 20
cmd.Parameters.Add(no1)
cmd.Parameters.Add(no2)
cmd.Parameters.Add(result)
cn.Open()
cmd.ExecuteNonQuery()
cn.Close()
Dim returnResult as Integer
returnResult=CType(result.Value,Integer)
can you try the following?
command.Parameters.AddWithValue("#personID", personID);
command.Parameters.AddWithValue("#ean", ean);
Also, IF EXISTS(...) ... ELSE ... can be replaced with:
IF EXISTS(SELECT * FROM feedback where personID = #personID AND ean = #ean)
BEGIN
SELECT #ratingschars
= CAST(pris AS varchar(2))
+ CAST(forventet AS varchar(2))
+ CAST(smag AS varchar(2))
FROM feedback
WHERE personID = #personID
AND ean = #ean
END
ELSE
BEGIN
SELECT #ratingschars
= CAST(avg(pris) AS varchar(2)) --or STR
+ CAST(avg(forventet) AS varchar(2)) --or STR
+ CAST(avg(smag) AS varchar(2)) --or STR
+ CAST(count(*) AS varchar(11))
FROM feedback
WHERE ean = #ean
END
END
or
SELECT #ratingschars --Question: all these columns (pris, forventet, smag) are NOT NULL ?
= CAST(pris AS varchar(2))
+ CAST(forventet AS varchar(2))
+ CAST(smag AS varchar(2))
FROM feedback
WHERE personID = #personID
AND ean = #ean
IF #ratingschars IS NULL
BEGIN
SELECT #ratingschars
= CAST(avg(pris) AS varchar(2))
+ CAST(avg(forventet) AS varchar(2))
+ CAST(avg(smag) AS varchar(2))
+ CAST(count(*) AS varchar(30))
FROM feedback
WHERE ean = #ean
END

Resources