I have this stored Procedure in MS SQL2008 (C#)
ALTER PROCEDURE UpdateProducts
#ProductID INT, #Name nvarchar(50), #Length Float
AS
UPDATE Product
SET Name = #Name, Length = #Length
WHERE (ProductID = #ProductID)
Length are in some cases "" (nothing). But when "" is inserted the value 0 is inserted instead. I want the value to be null. How can I do that? This did not work:
if (Length == "")
{
Length = null;
}
Set the defaults to NULL in the proc and you dont have to explicity pass NULL to a proc.
CREATE PROC ..dbo.Proc ( #param1 int =NULL, #param2 varchar(40) = NULL ,etc)
Also, if you have to send NULL from your app you would use DBNull.Value
Try DBNull.Value:
if (Size == "")
{
Size = DBNull.Value;
}
and make sure your database column is nullable.
Use NULLIF
UPDATE Product
SET Name = #Name, Length = NULLIF(#Length, '')
WHERE (ProductID = #ProductID)
Empty string is implicitly cast to 0 for float and int. decimal gives an error
Empty string and NULL are different
Edit: this deals with unclean input, so you don't have to worry about it...
Related
I want to know any ideas is available.
This images shows my table and Po_Settl column type is bit and Settled_ type is int.
So when user cancel the record I want to fill this again to the NULL value as shown as other rows.
As far this is done my manually, I press Ctrl+0 to change it to the null. So any other way to do this, Here with I will show my stored procedure that I wrote this to be work, but it's not working currently.
ALTER PROCEDURE [dbo].[Delete_PayBill]
#Req_Id int = NULL,
#Emp_Id varchar(10) = NULL,
#Reason varchar(50) = NULL,
#PO_Id int = NULL
AS
BEGIN
UPDATE [dbo].[App_Paybill]
SET [Cancelled_By] = #Emp_Id,
[Cancelled_Reason] = #Reason,
[Cancelled_Date] = GETDATE(),
[Status] = 0,
Po_SettleID = NULL
WHERE [Id] = #Req_Id
DECLARE #PayType VARCHAR(03)
SET #PayType= (SELECT [ReqType]
FROM [dbo].[Settleing_PaymentRequest]
WHERE [Payment_Id] = #Req_Id)
UPDATE Settleing_PaymentRequest
SET Status = 0
WHERE Payment_Id = #Req_Id
IF #PayType = 'PO'
BEGIN
UPDATE [dbo].[PO_Numbers]
SET [Po_Settled] = NULL, [Settled_By] = NULL
WHERE Req_Id = #PO_Id
END
ELSE IF #PayType = 'GR'
BEGIN
UPDATE App_Common_Request
SET Settled = NULL, SettlePendingStatus = NULL
WHERE Request_Id = #PO_Id
END
END
I have a stored procedure with NVARCHAR parameter like this:
ALTER PROCEDURE [dbo].[hr_Companies_GetByIDAndName]
#CompanyName NVARCHAR(100),
#Lang int = 1
AS
Select * from companies
where
(#Lang = 1 AND NameLang1 LIKE #CompanyName )
OR
(#Lang = 2 AND NameLang2 LIKE #CompanyName )
)
I want to supply it a nvarchar value so I am using this syntax:
DBHelper _helper = new DBHelper();
_helper.StoredProc = "hr_Companies_GetByIDAndName";
_helper.AddParam("#CompanyName", "N'%" + company.Trim() + "%'", SqlDbType.NVarChar);
_helper.AddParam("#Lang", Language, SqlDbType.Int);
return _helper.GetTable();
But it is returning null.
When I run query without stored procedure select * from companies where companyname like N'%mycompanyname%', it returns result.
How to add N using DBHelper addparameter?
I'm not sure what your DBHelper does but to pass nvarchar type values to stored procs, following is the standard way:
var param = new SqlParameter("#CompanyName ", SqlDbType.NVarChar, size)
param.Value = company.Trim();
The 3rd parameter above is size of nvarchar parameter that is declared in sproc using nvarchar(size) syntax. If it is nvarchar(max) then use -1.
Also note that you don't need to use "N %" prefix. ADO.Net layer takes care of it.
The RefNo column in SQL Server table is of datatype bigint, and can accept Nulls.
I am saving multiple records via xml using c#. The code works good, but for a few records, the RefNo has to be null, and it is saving as 0 even when I comment the 'else' part in stringbuilder.
SQL:
ALTER PROCEDURE SaveActivity
#XMLData xml
AS
BEGIN
IF #XMLData IS NOT NULL
BEGIN
CREATE TABLE #Temp(
ActivityId uniqueidentifier,
RefNo int,
Notes nvarchar(500)
);
INSERT INTO tblActivityDetails(ActivityId,RefNo,Notes)
SELECT
detail.query('ActivityId').value('.','uniqueidentifier') as ActivityId,
detail.query('RefNo').value('.','int') as RefNo,
detail.query('Notes').value('.','nvarchar(500)') as Notes
FROM
#XMLData.nodes('/details/detail') AS xmlData(detail)
END
END
C#:
StringBuilder sb = new StringBuilder();
sb.AppendLine("<?xml version=\"1.0\"?>");
sb.AppendLine("<details>")
foreach(GridViewRow gr in gvActivity.Rows)
{
HiddenField hdRefNo = (HiddenField)gr.FindControl("hdRefNo");
HiddenField hdNotes = (HiddenField)gr.FindControl("hdNotes");
string sRefNo = hdRefNo.value.ToString()=="0" ? null :
hdRefNo.value.ToString();
sb.AppendLine("<detail>");
sb.AppendLine("<ActivityId>"+ gActivityId.ToString() + "</ActivityId>");
if(sRefNo!="0")
sb.AppendLine("<RefNo>"+ sRefNo + "</RefNo>");
else
sb.AppendLine("<RefNo></RefNo>");
sb.AppendLine("<Notes>"+ hdNotes.value.ToString() + "</Notes>");
sb.AppendLine("</detail>");
}
sb.AppendLine("</details>")
You don't need to use query() when fetching values. Use values() directly and you will get NULL if the RefNo node is missing.
detail.value('(RefNo/text())[1]','int') as RefNo
Try using "" instead of null in
string sRefNo = hdRefNo.value.ToString()=="0" ? null :
hdRefNo.value.ToString();
like
string sRefNo = hdRefNo.value.ToString()=="0" ? "":
hdRefNo.value.ToString();
and remove if else part and just keep the statement
sb.AppendLine("<RefNo>"+ sRefNo + "</RefNo>");
In this line
string sRefNo = hdRefNo.value.ToString()=="0" ? null :
hdRefNo.value.ToString();
your checking string and if it equals "0" that assign null, so when you after try checking
if(sRefNo!="0") // this condition always true
sb.AppendLine("<RefNo>"+ sRefNo + "</RefNo>");
else
sb.AppendLine("<RefNo></RefNo>");
Possibly if you change condition to !string.IsNullOrEmpty(sRefNo) it will be work as expected
When you try get int field and in xml it don't set, then here
....
detail.query('RefNo').value('.','int') as RefNo,
....
will be return default value, i.e. 0
for solving you can try use number() function like this
....
detail.query('RefNo').value('number(.)','int') as RefNo,
....
I am checking for a dupliacte emaild using stored proc
ALTER procedure [dbo].[Insertreg]
( #id int output,#FirstName varchar (50),#LastName varchar(50) ,#Dob datetime,
#Gender varchar(20) ,#MobileNo nchar(10) ,#Country varchar(50) ,
#State varchar (50),#EmailId varchar (50),#Password nchar (15),#result int output
)
as
begin
if exists(select EmailId from Profile_Master where EmailId=#EmailId)
set #result=0
else
begin
set #result=1
insert into Profile_Master(FirstName,LastName,Dob,Gender,MobileNo,Country,State,EmailId,Password)
values
(#FirstName,#LastName,#Dob,#Gender,#MobileNo,#Country,#State,#EmailId,#Password)
set #id=SCOPE_IDENTITY()
return
end
end
code behind
result = cmd1.Parameters.Add("#result", System.Data.SqlDbType.Int);
result.Direction = System.Data.ParameterDirection.Output;
var id = cmd1.ExecuteNonQuery();
but when i debug if emailid exists i am getting id value as -1 how can i resolve this?
Using ExecuteNonQuery with StoredProc returns -1. That's the expected behaviour.
Change your code to
if exists(select EmailId from Profile_Master where EmailId=#EmailId)
select 0 as result
else
select 1 as result
C#, you don't need to pass parameter here anymore
var id = cmd1.ExecuteScalar();
Since you are using OUTPUT parameter, you can also use #Pilgerstorfer Franz's approach
This is the expected behaviour for ExecuteNonQuery.
Your query is not affecting any rows.
For UPDATE, INSERT, and DELETE statements, the return value is the
number of rows affected by the command. When a trigger exists on a
table being inserted or updated, the return value includes the number
of rows affected by both the insert or update operation and the number
of rows affected by the trigger or triggers. For all other types of
statements, the return value is -1. If a rollback occurs, the return
value is also -1.
You get the result as follows:
result = cmd1.Parameters.Add("#result", System.Data.SqlDbType.Int);
result.Direction = System.Data.ParameterDirection.Output;
cmd1.ExecuteNonQuery();
var id = result.Value;
Please try:
cmd1.ExecuteScalar();
var id=Convert.ToInt32(result.Value);
id is not an Id but just the number of affected rows since you're using ExecuteNonQuery instead of ExecuteScalar You should check result after ExecuteNonQuery to get the output variable.
result = cmd1.Parameters.Add("#result", System.Data.SqlDbType.Int);
result.Direction = System.Data.ParameterDirection.Output;
int numberOfAffectedRecords = (int)cmd1.ExecuteNonQuery();
// now result should have the output variable
If you want to have the newly created ID, you should use ExecuteScalar:
result = cmd1.Parameters.Add("#result", System.Data.SqlDbType.Int);
result.Direction = System.Data.ParameterDirection.Output;
int newID = (int)cmd1.ExecuteScalar();
// now result should have the output variable
Calling ExecuteNonQuery() will return the number of rows affected. As you did add an outputParameter you should access this one.
// access an output parameter
cmd1.ExecuteNonQuery();
var id = cmd1.Parameters["#result"].Value;
// OR: get the returnValue of a SP
var id = cmd1.ExecuteScalar();
EDIT
What about using this version of your sp
ALTER procedure [dbo].[Insertreg]
( #FirstName varchar (50),#LastName varchar(50) ,#Dob datetime,
#Gender varchar(20) ,#MobileNo nchar(10) ,#Country varchar(50),
#State varchar (50),#EmailId varchar (50),#Password nchar (15))
as
begin
if exists(select EmailId from Profile_Master where EmailId=#EmailId)
select -1;
else
begin
insert into Profile_Master(FirstName,LastName,Dob,Gender,MobileNo,Country,State,EmailId,Password)
values (#FirstName,#LastName,#Dob,#Gender,#MobileNo,#Country,#State,#EmailId,#Password)
select SCOPE_IDENTITY();
end
end
And afterwars only use
// no need for any output Parameters here...
int id = int.Parse(cmd1.ExecuteScalar().ToString())
to access your id value. Value will be greater than -1 if given mail is unique and -1 in case email already exists!
I have an insert stored procedure like this
if exists(select EmailId from Profile_Master where EmailId=#EmailId)
set #result=-1
else
begin
set #result=0
insert into Profile_Master(FirstName,LastName,Dob,Gender,MobileNo,Country,State,EmailId,Password)
values
(#FirstName,#LastName,#Dob,#Gender,#MobileNo,#Country,#State,#EmailId,#Password)
set #id=SCOPE_IDENTITY()
return
end
pid = cmd1.Parameters.Add("#id", SqlDbType.Int);
pid.Direction = ParameterDirection.Output;
cmd1.ExecuteNonQuery();
int res = Convert.ToInt32(pid.Value);
I am catching the value of last inserted record but i am getting an error like
Object cannot be cast from DBNull to other types.How to catch the value of last inserted record?
Do a null-check before you try to convert the value.
if( pid.Value is DBNull )
{
// Do alternative route.
}
else
{
int res = Convert.ToInt32(pid.Value);
}
or:
if( ! pid.Value is DBNull )
{
int res = Convert.ToInt32(pid.Value);
}
Well, clearly we can assume that pid.Value is equal to DBNull.Value and cannot be converted to type int
You need to check what the sp does adn what it returns from the Database.