SQL Server - Hasbytes in function gives different result then in select - sql-server

I created a function like this:
CREATE FUNCTION dbo.HashCheeseName (#CheeseName NVARCHAR(40))
RETURNS VARCHAR(40)
AS BEGIN
DECLARE #Salt VARCHAR(25)
DECLARE #CheeseName NVARCHAR(40)
DECLARE #output VARCHAR(40)
SET #Salt = '123abc11aa'
SET #output = HASHBYTES('SHA2_256', CAST(#CheeseName as VARCHAR(40)) + #Salt)
RETURN #output
END
;
When I just run
SELECT HASHBYTES('SHA2_256', CAST('SwissCheese' as VARCHAR(40)) + #Salt)
I get an expected result like 0xF456D41144584064AC5456B7E3...
However, when I run the function in a query
SELECT dbo.HashCheeseName('SwissCheese')
I get a result like this: h:Mó!yýŠù’p» ªu_aøP¾æhw
Any ideas on why it would result in something like this? At first sight it looks like a conversion issue, but I don't see the problem

What you are doing there isn't the same. HASHBYTES returns a varbinary (Hashbytes (Transact-SQL) - Return Values) where as your function is returning a varchar. Those are different datatypes. As a result, the last line of your function is effectively:
SET #output = CONVERT(varchar(40),HASHBYTES('SHA2_256', CAST(#CheeseName as VARCHAR(40)) + #Salt));
The varchar representation of a varbinary will not be the same. Either return a varbinary in your function, or your test SELECT with a CONVERT to a varchar(40).
Edit: To confirm, the solution is to simply change the return type of your function and variable:
CREATE FUNCTION dbo.HashCheeseName (#CheeseName NVARCHAR(40))
RETURNS varbinary(8000)
AS BEGIN
DECLARE #Salt VARCHAR(25);
DECLARE #CheeseName NVARCHAR(40);
DECLARE #output varbinary(8000) ;
SET #Salt = '123abc11aa';
SET #output = HASHBYTES('SHA2_256', CAST(#CheeseName as VARCHAR(40)) + #Salt);
RETURN #output;
END

Related

How to Convert row string value into column by using SQL query

How to achieve below requirement in SQL Server.
Data what I have:
and Expected output is:
Thanks,
Lawrance A
Assuming of your given data value:
'Message:"A",Level:"0",type:"log"'
'Message:"B",Level:"1",type:"log"'
select substring(ColumnA,10,1) Message,
replace(dbo.udf_GetNumeric(replace(replace(substring(ColumnA,20,5),'"',''),',','')),' ','')[type],
replace(replace(substring(ColumnA,29,250),'"',''),',','')[Log] from YourTable
GetNumeric here
I have created two function to achieve your desired output.
use below query by creating two function split and getVal
select
dbo.getVal(columnA,'Message') Message,
dbo.getVal(columnA,'Level') [Level],
dbo.getVal(columnA,'type') [type]
from TableA
Query for creating split and getVal function
Create function split(#s varchar(500),#splitWith varchar(20))
returns #RetTable Table(id int identity(1,1), Value varchar(200))
as
begin
if(CHARINDEX(#splitWith,#s)>0)
begin
set #s=#s+#splitWith
declare #len int =len(#s)
while charindex(#splitWith,#s)>0
begin
insert #RetTable values(SUBSTRING(#s,1,charindex(#splitWith,#s)-1))
set #s=SUBSTRING(#s,charindex(#splitWith,#s,1)+1,#len)
end
end
return
end
Create function getVal(#str varchar(500),#column varchar(200))
returns varchar(200)
as
begin
declare #ret varchar(200)
select #ret=value From dbo.split((select value From dbo.split('Message:"A",Level:"0",type:"log"',',') where value like +#column+'%'),':') where id=2
return replace(#ret,'"','')
end

"N" before text in sql server

I have a function
create Function [dbo].[persianNum]
(
#persionstr nvarchar(255)
)
Returns nvarchar(255)
AS
Begin
Declare #out nvarchar(255)
-- code
return #out
END
and I call this :
" select dbo.persianNum (N'۰۸/۰۲/۲۰۱۶ ۱۰:۱۳:۵۵') "
this line Worked correctly.
now I wanted to call this in my trigger
'۰۸/۰۲/۲۰۱۶ ۱۰:۱۳:۵۵' is in #myInput
select dbo.persianNum (#myinput)
but I need " N " before my input
How put it before the #myinput
ALTER Function [dbo].[persianNum]
(
#persionstr nvarchar(255)
)
Returns nvarchar(255)
--۰۸/۰۲/۲۰۱۶ ۱۰:۱۴:۴۴ ۰۸/۰۲/۲۰۱۶ ۱۰:۱۳:۵۵
AS
Begin
Declare #out nvarchar(255)
Declare #ss nvarchar(255)
Declare #persianTemp nvarchar(255)
Declare #len int
set #len = LEN(#persionstr)
set #persianTemp= #persionstr
set #out=''
while #len>0
Begin
set #len=#len-1;
set #ss = SUBSTRING(#persianTemp, 1, 1)
set #persianTemp=SUBSTRING(#persianTemp, 2, #len)
set #out=#out+
CASE #ss
WHEN N'۰' THEN N'0'
WHEN N'۱' THEN N'1'
WHEN N'۲' THEN N'2'
WHEN N'۳' THEN N'3'
WHEN N'۴' THEN N'4'
WHEN N'۵' THEN N'5'
WHEN N'۶' THEN N'6'
WHEN N'۷' THEN N'7'
WHEN N'۸' THEN N'8'
WHEN N'۹' THEN N'9'
ELSE #ss
END
END
return #out
END
this is my complete function
The N is used to cast as string as NVARCHAR, once a string is already an NVARCHAR you don't need to cast it again. You need to define #myinput as NVARCHAR otherwise your Persian text will not be encoded correctly.
You don't put the N before #myinput. Instead place it where you set the value of your variable.
Exampe
SET #myinput = N'۰۸/۰۲/۲۰۱۶ ۱۰:۱۳:۵۵';

How to return varchar value from a function

I written the following function.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create FUNCTION NameFunction
(
#eid int
)
RETURNS varchar
AS
BEGIN
Declare #logid varchar(50);
SELECT #logid = E.LoginId from HumanResources.Employee As E
where E.BusinessEntityID = #eid
RETURN #logid
END
GO
When I am executing it is showing result as a.
But expected result is adventure-works\terri0
Where I did the mistake here. Only first character coming. Need to change any thing?
Change your RETURN type to include a length, at this point it is just returning 1 character:
RETURNS varchar(100)
Full code:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create FUNCTION NameFunction
(
#eid int
)
RETURNS varchar(100) -- or whatever length you need
AS
BEGIN
Declare #logid varchar(50);
SELECT #logid = E.LoginId from HumanResources.Employee As E
where E.BusinessEntityID = #eid
RETURN #logid
END
GO
RETURNS varchar should be RETURNS varchar(50).
varchar without a length specified is interpreted as varchar(1) in this context (and as varchar(30) in the context of a CAST).
BTW: Scalar UDFs that do data access can be performance killers. You might want to consider at least rewriting this as an inline TVF so that the optimiser has more options.

SQL Server 2005 Weird varchar Behavior

This SQL Server 2005 T-SQL code:
DECLARE #Test1 varchar;
SET #Test1 = 'dog';
DECLARE #Test2 varchar(10);
SET #Test2 = 'cat';
SELECT #Test1 AS Result1, #Test2 AS Result2;
produces:
Result1 = d
Result2 = cat
I would expect either
The assignment SET #Test1 =
'dog'; to fail because there isn't
enough room in #Test1
Or the SELECT to return 'dog' in the Result1 column.
What is up with #Test1? Could someone please explain this behavior?
Let me answer with some quotes from the SQL Server documentation.
char and varchar
varchar[(n)]
...
When n is not specified in a data definition or variable declaration statement, the default length is 1.
Converting Character Data
When character expressions are converted to a character data type of a different size, values that are too long for the new data type are truncated.
So, your varchar is declared as a varchar(1), and the implicit conversion in your SET statement (from a string literal of length 3 to a varchar(1)) truncates dog to d.
the varchar is defaulting to length one
DECLARE #Test1 varchar;
try this, which will uses a simple function that takes a sql_variant and returns the data type info back:
CREATE FUNCTION [dbo].[yourFunction]
(
#InputStr sql_variant --can not be varchar(max) or nvarchar(max)
)
returns
varchar(8000)
BEGIN
DECLARE #Value varchar(50)
--can use SQL_VARIANT_PROPERTY(#InputStr,'BaseType') to determine given datatype
--do whatever you want with #inputStr here
IF #InputStr IS NULL
BEGIN
SET #value= 'was null'
END
ELSE IF SQL_VARIANT_PROPERTY(#InputStr,'BaseType')='varchar'
BEGIN
--your special code here
SET #value= 'varchar('+CONVERT(varchar(10),SQL_VARIANT_PROPERTY(#InputStr,'MaxLength '))+') - '+CONVERT(varchar(8000),#InputStr)
END
ELSE IF SQL_VARIANT_PROPERTY(#InputStr,'BaseType')='datetime'
BEGIN
--your special code here
SET #value= 'datetime - '+CONVERT(char(23),#InputStr,121)
END
ELSE IF SQL_VARIANT_PROPERTY(#InputStr,'BaseType')='nvarchar'
BEGIN
--your special code here
SET #value= 'nvarchar('+CONVERT(varchar(10),CONVERT(int,SQL_VARIANT_PROPERTY(#InputStr,'MaxLength '))/2)+') - '+CONVERT(varchar(8000),#InputStr)
END
ELSE
BEGIN
--your special code here
set #value= 'unknown!'
END
RETURN #value
END
GO
DECLARE #Test1 varchar;
SET #Test1 = 'dog';
DECLARE #Test2 varchar(10);
SET #Test2 = 'cat';
SELECT #Test1 AS Result1, #Test2 AS Result2;
select [dbo].[yourFunction](#test1)
output:
Result1 Result2
------- ----------
d cat
(1 row(s) affected)
-------------------
varchar(1) - d
(1 row(s) affected)
moral of the story, don't be lazy, specify a length on all of your varchar values!!!

stored procedure returns varchar

I would like to know if in SQL is it possible to return a varchar value from a stored procedure, most of the examples I have seen the return value is an int.
Example within a procedure:
declare #ErrorMessage varchar(255)
if #TestFlag = 0
set #ErrorMessage = 'Test'
return #ErrorMessage
You can use out parameter or the resulset to return any data type.
Return values should always be integer
CREATE PROCEDURE GetImmediateManager
#employeeID INT,
#managerName VARCHAR OUTPUT
AS
BEGIN
SELECT #managerName = ManagerName
FROM HumanResources.Employee
WHERE EmployeeID = #employeeID
END
Taken from here
You will need to create a stored function for that:
create function dbo.GetLookupValue(#value INT)
returns varchar(100)
as begin
declare #result varchar(100)
select
#result = somefield
from
yourtable
where
ID = #value;
return #result
end
You can then use this stored function like this:
select dbo.GetLookupValue(4)
Marc
A stored procedure's return code is always integer, but you can have OUTPUT parameters that are any desired type -- see http://msdn.microsoft.com/en-us/library/aa174792.aspx .

Resources