SQL server Nvarchar parameters - sql

I Have created an SP to search against many tables in the db based on string sent form ado
the Vb code
Shared ReadOnly Property Connection() As String
Get
Return ConfigurationManager.ConnectionStrings("ConnString").ConnectionString
End Get
End Property
Function GetData(ByVal SearchKey As String) As DataTable
Dim sqlConn As New SqlConnection(Connection)
Dim ds As New DataSet
Dim sqlCmd As New SqlCommand("Search_List")
Dim sqlAdapter As New SqlDataAdapter
sqlCmd.CommandType = CommandType.StoredProcedure
sqlCmd.Connection = sqlConn
sqlAdapter.SelectCommand = sqlCmd
sqlCmd.Parameters.Add(New SqlParameter("#SearchKey", SqlDbType.NVarChar, 255, ParameterDirection.Input, True, CByte(0), CByte(0), "SearchKey", DataRowVersion.Default, SearchKey))
sqlCmd.Parameters.Add("RerurnValue", SqlDbType.Int)
sqlCmd.Parameters("RerurnValue").Direction = ParameterDirection.ReturnValue
Try
sqlConn.Open()
sqlAdapter.Fill(ds, "Result")
sqlConn.Close()
Catch ex As Exception
Exit Function
End Try
Return ds.Tables("Result")
End Function
and the SQL SP is :
ALTER PROCEDURE [dbo].[Search_List](
#SearchKey NVARCHAR(200)
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Rc bigint
DECLARE #Err bigint
set #SearchKey = '%'+#SearchKey+'%'
CREATE
TABLE
#Temp
(
ID BIGINT,
elementType NVARCHAR(10),
NameAr NVARCHAR(255),
NAmeEn NVARCHAR(255),
DescAr NVARCHAR(MAX),
DescEn NVARCHAR(MAX),
URL NVARCHAR(MAX)
)
INSERT INTO #Temp
SELECT
Id
,'C'
,NameAr
,NameEn
,DescAr
,DescEn
,'Counsel.aspx'
FROM
CMS_Councils
Where
(NameAr like #SearchKey
OR
NameEn Like #SearchKey
OR
DescAr Like #SearchKey
OR
DescEn Like #SearchKey)
AND
isnull(Status,0) = 1
select * from #Temp
end
As you can see I have declared argument in VB as Nvarchr and SQL parameter #SearchKey as Nvarchar also if I send english data in #SearchKey search returns correct data, but if I tried to send arabic string in #SearchKey no results appeared knowing that there is arabic data inside the table
Am I missing something?
What Should I do further than that to allow arabic search?

You can try specifying a collation using the COLLATE keyword:
You'd need to specify arabic afterwards, for instance: COLLATE arabic_ci_as
SELECT
Id
,'C'
,NameAr
,NameEn
,DescAr
,DescEn
,'Counsel.aspx'
FROM
CMS_Councils
Where
(NameAr like #SearchKey
OR
NameEn Like #SearchKey
OR
DescAr Like #SearchKey
OR
DescEn Like #SearchKey)
AND
isnull(Status,0) = 1
COLLATE arabic_ci_as

Related

sql procedure returns 1 but vb.net gets 0

I have stored procedure which seems to be working fine when executing directly from management studio, but when it comes o vb.net code i always get 0. Can anyone look at that and tell me what is missing here. I read documentation and seems that should work as expected however it is not somehow.
stored procedure:
ALTER PROCEDURE [dbo].[IsPhraseConnectedAlready]
#PhraseId INT,
#KatSubkatId INT,
#WordId INT,
#SubsubkatId INT = NULL
AS
BEGIN
SET NOCOUNT ON;
DECLARE #temp_T_Html_Word_Categories TABLE(Id INT)
DECLARE #temp_T_Html_WordCat_Phrase TABLE(FK_Phrase_ID INT)
DECLARE #temp_T_Html_Phrase TABLE(Id INT, [Name] varchar(max))
IF #SubsubkatId IS NULL
BEGIN
INSERT INTO #temp_T_Html_Word_Categories(Id) SELECT Id FROM T_Html_Word_Categories WHERE FK_KatSubkat_ID = #KatSubkatId And FK_Word_ID = #WordId And FK_Subsubkat_ID IS NULL;
END
ELSE
BEGIN
INSERT INTO #temp_T_Html_Word_Categories(Id) SELECT Id FROM T_Html_Word_Categories WHERE FK_KatSubkat_ID = #KatSubkatId And FK_Word_ID = #WordId And FK_Subsubkat_ID = #SubsubkatId;
END
Declare #Id int;
Select #Id = Id From #temp_T_Html_Word_Categories;
INSERT INTO #temp_T_Html_WordCat_Phrase(FK_Phrase_ID) SELECT FK_Phrase_ID FROM T_Html_WordCat_Phrase WHERE FK_Word_Categorie_ID = #Id;
IF (##ROWCOUNT > 0)
BEGIN
Declare #FK_Phrase_ID int;
--it makes no difference what you SELECT in an EXISTS sub-query as it is just syntactical sugar. (ie Nothing is actually selected.) SELECT * or SELECT 1 ...
WHILE EXISTS(SELECT * FROM #temp_T_Html_WordCat_Phrase)
BEGIN
Select Top 1 #FK_Phrase_ID = FK_Phrase_ID From #temp_T_Html_WordCat_Phrase;
INSERT INTO #temp_T_Html_Phrase(Id, [Name]) SELECT Id, [Name] FROM T_Html_Phrase WHERE Id = #FK_Phrase_ID;
IF (#PhraseId = #FK_Phrase_ID)
RETURN 1
Delete #temp_T_Html_WordCat_Phrase Where FK_Phrase_ID = #FK_Phrase_ID;
END;
END
ELSE
BEGIN
Delete #temp_T_Html_Word_Categories;
RETURN 0
END
RETURN 0
END
This is my visual basic.net code below:
Public Function IsPhraseConnectedAlready(phraseId As Integer, katsubkatid As Integer, wordid As Integer, subsubkatid As Integer?) As Integer
Using con As New SqlConnection(_strcon)
Using cmd As New SqlCommand("IsPhraseConnectedAlready", con)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.AddWithValue("#PhraseId", phraseId)
cmd.Parameters.AddWithValue("#KatSubkatId", katsubkatid)
cmd.Parameters.AddWithValue("#WordId", wordid)
If subsubkatid.HasValue Then 'check whether nullable field contain value
cmd.Parameters.AddWithValue("#SubsubkatId", subsubkatid.Value)
Else
cmd.Parameters.AddWithValue("#SubsubkatId", DBNull.Value)
End If
con.Open()
Dim i = CType(cmd.ExecuteScalar(), Integer)
If i = 1 Then
Return True
ElseIf i = 0 Then
Return False
End If
End Using
End Using
End Function
Executed from ssms directly shows it reaches RETURN 1, however with same values passed from vb.net i am getting 0:
in vb.net working with same values:
seems the resolution was to do like this:
instead of this:
RETURN 1 or RETURN 0
make it as:
SELECT 1 or SELECT 0
however to break execution when it reaches first select to add additional return after each SELECT.
Does anyone sees any issues with that? To me it works and wonder why just RETURN was not from vb.net
cmd.ExecuteScalar() will execute the query, and return the first column of the first row in the result set returned by the query. However, you're not returning a column/row, you're just returning a value.
So, either convert RETURN 1 to SELECT 1 or else declare a return parameter in your VB.Net code like so:
...
Dim returnParameter As SqlParameter = cmd.Parameters.Add("#ReturnVal", SqlDbType.Int)
returnParameter.Direction = ParameterDirection.ReturnValue
con.Open()
cmd.ExecuteNonQuery()
Dim i = CType(returnParameter.Value, Integer)
...

Error When Running Stored Procedure From VBA

I am using VBA to pull information from SQL Server. To not make things complicated read this:
"I have a Stored Procedure in SQL that receiving a Date (#NeededDate as Date) & a comma delimited text (#DelimitedAssets as NVARCHAR(MAX) returns the required results.
When I run my code in VBA, IT WORKS when the text I'm passing (#DelimitedAssets) is not longer than 7000 characters (that's not the exact number but is close). So, rephrasing this: the code works as expected if the string is not big.
But the text I'm passing to the Stored Procedure from VBA adds up to 12000 characters. NVARCHAR should be able to handle that but is not doing it when I pass it from VBA.
IMPORTANT: if I run the same chunk of data (12000 characters) from SQL Server Management Studio, it works perfectly. No errors and the data is ok.
ERROR OCCURS IN LINE:
Set oRecordSet = .Execute
VBA CODE*
Private Function RunMonthlyPricesSP(ByVal strDate As String, ByRef strAssetsDelimted As String, ByRef cnAccounting As Object, ByRef rDestination As Range) As Variant
Dim oCmd As ADODB.Command
Dim oRecordSet As ADODB.Recordset
Dim ActivityParam As ADODB.Parameter
Dim varPrices As Variant
Dim strAction As String
Set oCmd = New ADODB.Command
Set oRecordSet = New ADODB.Recordset
With oCmd
.ActiveConnection = cnAccounting
.CommandType = adCmdStoredProc
.CommandText = "Usp_bondselectionprices"
.Parameters("#NeededDate").Value = strDate
.Parameters("#DelimitedAssets").Value = strAssetsDelimted
Set oRecordSet = .Execute
End With
' Return Array.
' Pending.
End Function
SQL STORED PROCEDURE*
GO
/****** Object: StoredProcedure [dbo].[Usp_bondselectionprices] Script Date: 4/13/2018 5:41:57 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[Usp_bondselectionprices] #NeededDate DATE,
#DelimitedAssets VARCHAR(max)
AS
BEGIN
DECLARE #TblBuysSelectionBond BUYSSELECTIONBONDS
INSERT INTO #TblBuysSelectionBond
SELECT *
FROM dbo.Splittext(#DelimitedAssets)
SELECT CASE
WHEN Prices.Price * CurrencyPrices.Price IS NULL THEN Prices.Price
ELSE Prices.Price * CurrencyPrices.Price
END AS Price,
Assets.AssetName
FROM Prices
INNER JOIN Assets
ON Prices.AssetID = Assets.AssetID
INNER JOIN Assets AS Currencies
ON Assets.CurrencyID = Currencies.AssetID
LEFT OUTER JOIN Prices AS CurrencyPrices
ON Currencies.AssetID = CurrencyPrices.AssetID
AND Prices.PriceDate = CurrencyPrices.PriceDate
WHERE prices.PriceDate = #NeededDate
AND assets.InstrumentTypeID = 4
AND Assets.AssetName IN (SELECT *
FROM #TblBuysSelectionBond)
END
FUNCTION CALLED FROM STORED PROCEDURE TO CONVERT TEXT DELIMITED INTO A TABLE*
GO
/****** Object: UserDefinedFunction [dbo].[Splittext] Script Date: 4/13/2018 6:10:02 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[Splittext] (#input AS VARCHAR(max))
RETURNS #Result TABLE(
Value VARCHAR(max))
AS
BEGIN
DECLARE #str VARCHAR(max)
DECLARE #ind bigint
IF( #input IS NOT NULL )
BEGIN
SET #ind = Charindex(',', #input)
WHILE #ind > 0
BEGIN
SET #str = Substring(#input, 1, #ind - 1)
SET #input = Substring(#input, #ind + 1, Len(#input) - #ind)
INSERT INTO #Result
VALUES (#str)
SET #ind = Charindex(',', #input)
END
SET #str = #input
INSERT INTO #Result
VALUES (#str)
END
RETURN
END
Remember, this works for for small string delimited text. So we know that my connection and other arguments are OK.
Thanks,
Ok. I found the solution and it's very, very easy. This is why is so important to check the Watch windows to understand what your Objects (oCMD in this case) has inside.
By default it was taking the parameter #DelimitedAssets as adVarChar. You need to specify that it's not a adVarChar but an adLongVarChar.
.Parameters("#DelimitedAssets").Value = strAssetsDelimted
.Parameters("#DelimitedAssets").Type = adLongVarChar
Once I changed this, everything worked as expected.
Hope this helps.
have you tried to specify type&size?
param.SqlDbType = SqlDbType.VarChar;
param.Size = -1;

Procedure or function 'userpro' expects parameter '#Username', which was not supplied

i am getting error of ExcecuteNonQuery ,i am not getting where i am wrong please help!
SqlConnection con = new SqlConnection(
"Data Source="";Initial Catalog=bunny;Integrated Security=SSPI");
SqlCommand cmd = new SqlCommand("userpro", con);
CommandType cd = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#Username", TextBox1.Text);
cmd.Parameters.AddWithValue("#Addresss", TextBox2.Text);
cmd.Parameters.AddWithValue("#Contact ", TextBox3.Text);
cmd.Parameters.AddWithValue("#EmailId", TextBox4.Text);
cmd.Parameters.AddWithValue("#Passwords", TextBox5.Text);
cmd.Parameters.AddWithValue("#ConfirmPassword", TextBox6.Text);
con.Open();
cmd.ExecuteNonQuery();
con.Close();
this is my store procedure
create procedure userpro
#Username varchar (20),
#Addresss varchar (20),
#Contact varchar (20),
#EmailId varchar (20),
#Passwords varchar (20),
#ConfirmPassword varchar (20)
as
begin
if exists (select * from userlogs where Username=#Username)
begin
update userlogs set Addresss=#Addresss,Contact=#Contact,EmailId=#EmailId,Passwords=#Passwords,ConfirmPassword=#ConfirmPassword where Username=#Username
end
else
begin
insert into userlogs(Username,Addresss,Contact,EmailId,Passwords,ConfirmPassword) values (#Username,#Addresss,#Contact,#EmailId,#Passwords,#ConfirmPassword)
end
end
You need to check if TextBox1.Text is not null. If it is procedure will fail because #Username is mandatory. You can resolve this like that:
if(TextBox1.Text == null)
cmd.Parameters.AddWithValue("#Username", DBNull.Value);
else
cmd.Parameters.AddWithValue("#Username", TextBox1.Text);
Or you can make this parameter optional in your userpro procedure:
create procedure userpro
#Username varchar (20) = '',

Very Strange SqlClient error with SmallDatetime parameter in SQL Server 2014 stored proc

I've been stumped with the following error for the past hour:
"Procedure or function 'write_call' expects parameter '#Date', which was not supplied."
The #date parameter is a smalldatetime. I am trying to pass the value #1/27/2009 04:32:00 PM#
I am using SQLExpress 2014.
The same stored proc has been in production on SQLExpress 2008
T-SQL Stored Proc:
ALTER proc [dbo].[write_call]
(
#Date smalldatetime, #Duration smallint, #Ring tinyint, #Extension smallint = null, #Number varchar(20) = null, #LineID smallint,
#AccountID smallint = null, #AccountName varchar(30) = null, #UnitID smallint = null, #UnitName varchar(30) = null, #AreaName varchar(100) = null, #CallType char(1) = null,
#CallCode varchar(6) = null, #Rate numeric(5,2) = 0.0, #Cost numeric(12,2) = 0.0, #TAC varchar(10) = null
)
as
declare #id int=0, #old_acctid int=0 --, #old_rate numeric(5,2)=0.0, #old_cost numeric(12,2)=0.0
select #id=o.ID,#old_acctid=o.AccountID from OutboundCalls o where o.Date=#Date and o.Duration=#Duration and o.Number=#Number
if #id=0
begin
insert into _OutboundCalls (Date, Duration, Ring, Extension, Number, LineID, AccountID, AccountName, UnitID, UnitName, AreaName, CallType,CallCode, Rate, Cost, TAC,redirected,contactid,CompanyID,CompanyName)
values (#Date, #Duration, #Ring, #Extension, #Number, #LineID, #AccountID, #AccountName, #UnitID, #UnitName, #AreaName, #CallType, #CallCode, #Rate, #Cost, #TAC,1,0,1,'PricewaterhouseCoopers')
end
else if #id>0 and #old_acctid<>#AccountID
update OutboundCalls set AccountID=#AccountID, UnitID=#UnitID,AccountName=#AccountName,UnitName=#UnitName
where OutboundCalls.ID=#id
VB.NET 2015:
Private Sub write_call(c As CallInfo)
Using cnn = New SqlClient.SqlConnection(connString)
Using cmd = New SqlClient.SqlCommand("write_call", cnn)
cmd.Parameters.AddWithValue("#Date", c.dt)
cmd.Parameters.AddWithValue("#Duration", c.secDurn)
cmd.Parameters.AddWithValue("#Ring", 0)
cmd.Parameters.AddWithValue("#Extension", c.src)
cmd.Parameters.AddWithValue("#Number", c.dst)
cmd.Parameters.AddWithValue("#LineID", c.lineId)
cmd.Parameters.AddWithValue("#AccountID", c.account_id)
cmd.Parameters.AddWithValue("#AccountName", c.account_name)
cmd.Parameters.AddWithValue("#UnitID", c.unit_id)
cmd.Parameters.AddWithValue("#UnitName", c.unit_name)
cmd.Parameters.AddWithValue("#AreaName", c.area?.Name)
cmd.Parameters.AddWithValue("#CallType", c.dst_type)
cmd.Parameters.AddWithValue("#CallCode", c.callcode)
cmd.Parameters.AddWithValue("#Rate", c.rate?.rate)
cmd.Parameters.AddWithValue("#Cost", c.Cost)
cmd.Parameters.AddWithValue("#TAC", c._oC)
cnn.Open()
Try
cmd.ExecuteNonQuery()
Catch ex As Exception
Stop
End Try
End Using
End Using
End Sub
It seems that your code misses to set the CommandType property. This property defaults to CommandType.Text and it is appropriate when you pass a sql string as the CommandText.
If you pass the name of a stored procedure you need to set
cmd.CommandType = CommandType.StoredProcedure
without this setting the behavior of the SqlCommand is unpredictable.

get return value from stored procedure without output parameter

I have a vb.net application that inserts records into a db table using a stored procedure that is supposed to return a value. This stored procedure was setup by someone else and initially was linked to a webservice through which my application made the insert and got the return value in the returned xml. I now have access to the db table and not sure how to receive the return value in my vb.net method.
SQl stored procedure snippet;
#urlname varchar(500),
#siteid varchar(16),
#origin varchar(50),
#queryid varchar(25)
AS
SET NOCOUNT ON;
declare #cnt int
declare #serverip varchar(16)
declare #mincnt int
declare #siteservercnt int
select #cnt=COUNT(*) from sites
where urlname=#urlname
if #cnt = 0
begin
insert into sites (urlname,siteid,exported,origin,queryid)
values(#urlname,#siteid,1,#origin,#queryid)
select #siteservercnt = COUNT(*) from siteserverip where siteid=#siteid
if #siteservercnt=0
begin
select top 1 #mincnt=COUNT(*),#serverip=serverip from siteserverip
group by serverip
order by COUNT(*)
select top 1 #mincnt=sitecount,
#serverip=serverip from serveripcounts
order by sitecount
insert into siteserverip values(#siteid,#serverip)
update serveripcounts set sitecount=sitecount+1
where serverip=#serverip
end
end
SELECT siteid from sites
where urlname=#urlname
return
and my vb.net code to do the insert
CommandObj.CommandText = "Getsite"
CommandObj.CommandTimeout = 90
Dim newUrl As String = String.Empty
CommandObj.Parameters.Clear()
Dim m_param As SqlParameter
m_param = CommandObj.Parameters.Add("#urlname", SqlDbType.VarChar, 500)
m_param.Direction = ParameterDirection.Input
m_param.Value = name
m_param = CommandObj.Parameters.Add("#siteid", SqlDbType.VarChar, 16)
m_param.Direction = ParameterDirection.Input
m_param.Value = siteid
m_param = CommandObj.Parameters.Add("#origin", SqlDbType.VarChar, 50)
m_param.Direction = ParameterDirection.Input
m_param.Value = method
m_param = CommandObj.Parameters.Add("#queryId", SqlDbType.VarChar, 25)
m_param.Direction = ParameterDirection.Input
m_param.Value = forumID
Dim recordsAffected As Integer = CommandObj.ExecuteNonQuery
You can use ExecuteScalar to get that value. ExecuteNonQuery returns number of rows affected while you want to get the value generated by last select. You could use ExecuteReader as well but that is useful when your SP might be returning more columns and/or more rows.
'Populate first column and first row value in siteID
Dim siteID As Integer = CommandObj.ExecuteScalar