Stored procedure cast error - sql-server-2008

I have a strange problem with the following SP:
CREATE PROCEDURE [dbo].[Manufacturer_GetProductsCountByManufacturedId]
(
#ManufacturerIds NVARCHAR(MAX) = '',
#ExcludeType INT
)
AS
BEGIN
DECLARE #ManufacturerId NVARCHAR(MAX)
DECLARE #GoodManufacturerIds NVARCHAR(MAX) = ''
DECLARE #result BIGINT
DECLARE #pos INT
DECLARE #len INT
SET #GoodManufacturerIds = ''
SET #pos = 0
SET #len = 0
WHILE CHARINDEX(',', #ManufacturerIds, #pos + 1)>0
BEGIN
-- Split
SET #len = CHARINDEX(',', #ManufacturerIds, #pos+1) - #pos
SET #ManufacturerId = SUBSTRING(#ManufacturerIds, #pos, #len)
-- Check
SELECT TOP 1 #result = p.ProductId
FROM [MYDB].[dbo].[Product] p
INNER JOIN [MYDB].[ProductTyping].[TypedProductFieldValue] tpfv ON tpfv.ProductId = p.ProductId
WHERE ManufacturerId = #ManufacturerId
AND tpfv.ProductTypeId <> #ExcludeType
IF #result > 0
SET #GoodManufacturerIds = #GoodManufacturerIds + #ManufacturerId + ','
SET #pos = CHARINDEX(',', #ManufacturerIds, #pos+#len)+1
END
-- Last comma kaputt
SET #GoodManufacturerIds = LEFT(#GoodManufacturerIds, LEN(#GoodManufacturerIds) - 1)
RETURN #GoodManufacturerIds
END
Basically I have to split a string with comma-separated values and for each on those values, I execute a query and put the result in another comma-separated string.
If I send these values as stored procedure parameters, ("5220,3008,1561,2678," and 5) I got an error, "Unable to cast nvarchar values '5220,3008,1561,2678' to type int".
BUT If I built in those values in the stored procedure as:
DECLARE #ManufacturerId NVARCHAR(MAX)
DECLARE #GoodManufacturerIds NVARCHAR(MAX) = ''
DECLARE #result BIGINT
DECLARE #pos INT
DECLARE #len INT
-- test
DECLARE #ManufacturerIds NVARCHAR(MAX) = ''
DECLARE #ExcludeType INT
SET #ManufacturerIds = '5220,3008,1561,2678,13715,5047,'
SET #ExcludeType = 5
SET #GoodManufacturerIds = ''
SET #pos = 0
SET #len = 0
WHILE CHARINDEX(',', #ManufacturerIds, #pos + 1)>0
BEGIN
-- Split
SET #len = CHARINDEX(',', #ManufacturerIds, #pos+1) - #pos
SET #ManufacturerId = SUBSTRING(#ManufacturerIds, #pos, #len)
-- Check
SELECT TOP 1 #result = p.ProductId
FROM [MYDB].[dbo].[Product] p
INNER JOIN [MYDB].[ProductTyping].[TypedProductFieldValue] tpfv ON tpfv.ProductId = p.ProductId
WHERE ManufacturerId = #ManufacturerId
AND tpfv.ProductTypeId <> #ExcludeType
IF #result > 0
SET #GoodManufacturerIds = #GoodManufacturerIds + #ManufacturerId + ','
SET #pos = CHARINDEX(',', #ManufacturerIds, #pos+#len)+1
END
-- Last comma kaputt
SET #GoodManufacturerIds = LEFT(#GoodManufacturerIds, LEN(#GoodManufacturerIds) - 1)
RETURN #GoodManufacturerIds
Everything works fine and I got my new string.
I dunno where the error could be in the first procedure, any hints?

I found the error, I was using RETURN but RETURN is for integer values and in this case mine is a string, so putting SELECT make everything works fine.

Related

converting the sql function to mysql

I want to convert the following funciton creation to work in MySql
CREATE FUNCTION dbo.DistinctList
(
#List VARCHAR(MAX),
#Delim CHAR
)
RETURNS
VARCHAR(MAX)
AS
BEGIN
DECLARE #ParsedList TABLE
(
Item VARCHAR(MAX)
)
DECLARE #list1 VARCHAR(MAX), #Pos INT, #rList VARCHAR(MAX)
SET #list = LTRIM(RTRIM(#list)) + #Delim
SET #pos = CHARINDEX(#delim, #list, 1)
WHILE #pos > 0
BEGIN
SET #list1 = LTRIM(RTRIM(LEFT(#list, #pos - 1)))
IF #list1 <> ''
INSERT INTO #ParsedList VALUES (CAST(#list1 AS VARCHAR(MAX)))
SET #list = SUBSTRING(#list, #pos+1, LEN(#list))
SET #pos = CHARINDEX(#delim, #list, 1)
END
SELECT #rlist = COALESCE(#rlist+',','') + item
FROM (SELECT DISTINCT Item FROM #ParsedList) t
RETURN #rlist
END
I found this function at http://blog.sqlauthority.com/2009/01/15/sql-server-remove-duplicate-entry-from-comma-delimited-string-udf/
I don't know why people have down graded my question.
Anyway I was able to come up with the answer.
Delimiter //
CREATE FUNCTION DistinctList
(
List TEXT,
Delim CHAR
)
RETURNS
TEXT
BEGIN
DECLARE list1 TEXT;
DECLARE Pos INT;
DECLARE rList TEXT;
DROP TEMPORARY TABLE IF EXISTS ParsedList;
Create temporary table if not exists ParsedList
(
Item VARCHAR(60)
) ENGINE=MEMORY;
SET list = CONCAT(list, Delim);
SET pos = length(SUBSTRING_INDEX(list, delim, 1));
WHILE (pos > 0) DO
SET list1 = SUBSTRING(list, 1, pos);
IF list1 <> '' THEN
INSERT INTO ParsedList VALUES (list1);
END IF;
SET list = SUBSTRING(list, pos+2);
SET pos = length(SUBSTRING_INDEX(list, delim, 1));
END WHILE;
SELECT GROUP_CONCAT(DISTINCT Item) FROM ParsedList INTO rlist;
RETURN rlist;
END//
Delimiter ;

Ms Sql Function for list

I have varchar values like below
72,73,74
I try to split as a comma after that i want to convert to int above values.Than i want to match Id with my User Table.
CREATE FUNCTION Fn_MyFunction(#MyUserIdValues VARCHAR(100))
RETURNS VARCHAR(300) AS
BEGIN
DECLARE #Result VARCHAR(300) = ''
Select UserName From UserTable
Where MyUserIdValues=UserIdValues
RETURN #Result
#Result must be like below in one column
Joe,Michael,Ricky
Any help will be appreciated.
Thanks.
The classic way of doing this...
/*
create table Users
(
id int,
name nvarchar(max)
)
insert into Users
values
(72, 'Joe'),
(73, 'Michael'),
(74, 'Ricky'),
(75, 'Manny'),
(76, 'Bob')
*/
CREATE FUNCTION dbo.Fn_MyFunction(#IdValues VARCHAR(100))
RETURNS NVARCHAR(max) AS
BEGIN
DECLARE #Result NVARCHAR(max);
DECLARE #delimiter as nchar = ',';
WHILE LEN(#IdValues) <> 0
BEGIN
Declare #CurrentId int;
If CHARINDEX(#delimiter, #IdValues) = 0
begin
Set #CurrentId = cast(#IdValues as int);
Set #IdValues = ''
End
Else
begin
Set #CurrentId = cast(left(#IdValues, charindex(#delimiter, #IdValues) -1) as int)
Set #IdValues = Substring(#IdValues, charindex(#delimiter, #IdValues) +1, len(#IdValues))
End
select #Result = Isnull(#Result + ',', '') + Isnull((Select Name From Users Where Id=#CurrentId),'(unknown)')
END
RETURN #Result
END
GO
Select dbo.Fn_MyFunction('72,73,74')
--Joe,Michael,Ricky
Select dbo.Fn_MyFunction('72,0,74')
--Joe,(unknown),Ricky
Select dbo.Fn_MyFunction('72,73,72,74,74')
--Joe,Michael,Joe,Ricky,Ricky
GROUP_CONCAT and FIND_IN_SET might be a handy for you.
Try this:
SELECT GROUP_CONCAT(UserName)
FROM UserTable
WHERE FIND_IN_SET(MyUserIdValues,'72,73,74');
I had found solution for splitting string and inserting it in a table
GO
/****** Object: UserDefinedFunction [dbo].[Split] Script Date: 10/03/2013 11:45:16 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[Split] (
#InputString VARCHAR(8000),
#Delimiter VARCHAR(50)
)
RETURNS #Items TABLE (
Item int
)
AS
BEGIN
IF #Delimiter = ' '
BEGIN
SET #Delimiter = ','
SET #InputString = REPLACE(#InputString, ' ', #Delimiter)
END
IF (#Delimiter IS NULL OR #Delimiter = '')
SET #Delimiter = ','
DECLARE #Item VARCHAR(8000)
DECLARE #ItemList VARCHAR(8000)
DECLARE #DelimIndex INT
SET #ItemList = #InputString
SET #DelimIndex = CHARINDEX(#Delimiter, #ItemList, 0)
WHILE (#DelimIndex != 0)
BEGIN
SET #Item = SUBSTRING(#ItemList, 0, #DelimIndex)
INSERT INTO #Items VALUES (#Item)
-- Set #ItemList = #ItemList minus one less item
SET #ItemList = SUBSTRING(#ItemList, #DelimIndex+1, LEN(#ItemList)-#DelimIndex)
SET #DelimIndex = CHARINDEX(#Delimiter, #ItemList, 0)
END -- End WHILE
IF #Item IS NOT NULL -- At least one delimiter was encountered in #InputString
BEGIN
SET #Item = #ItemList
INSERT INTO #Items VALUES (#Item)
END
-- No delimiters were encountered in #InputString, so just return #InputString
ELSE INSERT INTO #Items VALUES (cast(#InputString as int))
RETURN
END -- End Function
Select UserName From UserTable where MyUserIdValues in(Select Item from Split('72,73,74',','))
//Call function Split using last query
Check this out, it will solve your problem and it simple and perfect method
Select Username from UserTable where MyUserIdValues IN ' + '('+ #Id +')'
My attempt (i think it's a little neater):
create function dbo.fn_UserNames(#ids varchar(max))
returns varchar(max) as
begin
set #ids = #ids + ','
declare #id table (Id int)
while(#ids != '') begin
insert into #id
select i
from (select substring(#ids, 1, charindex(',', #ids, 0) - 1) i) a
where i != ''
if #ids like '%,%'
set #ids = substring(#ids, charindex(',', #ids, 0) + 1,
len(#ids) - charindex(',', #ids, 0))
else
set #ids = ''
end
declare #ret varchar(max)
select #ret = isnull(#ret, '') + a.UserName + ','
from adhoc.UserTable a
join #id b on a.UserId = b.Id
return #ret
end
Hi you can try this one also.
CREATE FUNCTION [DBO].[FN_SPLIT] ( #STRSTRING VARCHAR(MAX))
RETURNS #NAME TABLE (NAME VARCHAR(MAX))
AS
BEGIN
DECLARE #USERID TABLE(ID INT)
DECLARE #USERS TABLE (ID INT , NAME VARCHAR(50))
INSERT INTO #USERS VALUES (72,'A'),(73,'B'),(74,'C')
;WITH STR_CTE(_START, _STOP) AS
(
SELECT 1, CHARINDEX(',' , #STRSTRING )
UNION ALL
SELECT CAST(_STOP + 1 AS INT), CHARINDEX(',' ,#STRSTRING , CAST((_STOP + 1) AS INT))
FROM
STR_CTE
WHERE _STOP > 0
)
INSERT INTO #USERID (ID)
SELECT
SUBSTRING(#STRSTRING , _START, CASE WHEN _STOP > 0 THEN _STOP -_START ELSE 4000 END) AS ID
FROM STR_CTE
DECLARE #STRNAME VARCHAR(MAX)
SELECT
#STRNAME = COALESCE(#STRNAME+',','') + U.NAME
FROM
#USERID UD
INNER JOIN
#USERS U ON UD.ID = U.ID
INSERT INTO #NAME
SELECT #STRNAME
RETURN;
END

Splitting a long word with space

I have a long string.I want to check throughout this string for consecutive 15 letters if there is no space i have to manually put a space in sql server. Can any one pls help??
For eg. my string is 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ'
then it should appear like 'ABCDEFGHIJKLMNOP QRSTUVWXYZABCDE FGHIJKLMNOPQRST UVWXYZ'
#dcp1986: I tried with your function as below.
SELECT dbo.UF_StringSplitter('HeloEveryonehru Howslyfgoingonn HaveaGoodDayGoodMorning')
But an unexpected split occured. I think your function must be modified as below for the correct result:
IF EXISTS(SELECT * FROM sysobjects WHERE ID = OBJECT_ID('UF_StringSplitter'))
DROP FUNCTION UF_StringSplitter
GO
CREATE FUNCTION UF_StringSplitter (
#psCSString VARCHAR(MAX)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #sTemp VARCHAR(MAX)
DECLARE #tTemp VARCHAR(MAX)
SET #tTemp=''
WHILE LEN(#psCSString)>15
BEGIN
SET #sTemp = LEFT(LTRIM(#psCSString), 15)
SET #psCSString = LTRIM(SUBSTRING(#psCSString,16, LEN(#psCSString)))
IF #psCSString LIKE ' %'
SET #tTemp=#tTemp+#sTemp
ELSE
SET #tTemp=#tTemp+#sTemp+' '
END
SET #tTemp=#tTemp+#psCSString
RETURN #tTemp
END
You could use a function like this
IF EXISTS(SELECT * FROM sysobjects WHERE ID = OBJECT_ID('UF_StringSplitter'))
DROP FUNCTION UF_StringSplitter
GO
CREATE FUNCTION UF_StringSplitter
(
#psCSString VARCHAR(MAX)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #sTemp VARCHAR(MAX)
DECLARE #tTemp VARCHAR(MAX)
SET #tTemp=''
WHILE LEN(#psCSString)>15
BEGIN
SET #sTemp = LEFT(#psCSString, 15)
SET #psCSString = SUBSTRING(#psCSString,16, LEN(#psCSString))
IF #psCSString LIKE ' %'
SET #tTemp=#tTemp+#sTemp
ELSE
SET #tTemp=#tTemp+#sTemp+' '
END
SET #tTemp=#tTemp+#psCSString
RETURN #tTemp
END
Go
Here i have hard coded the splitting value, and you can use the function
UPDATE mytable SET mycol=dbo.UF_StringSplitter(mycol)
I don't know how to do it on a single statement, but you can create a sql function something like this
create function AddStuffCharacterInLength (#original nvarchar(100), #take int, #stuff varchar(100))
returns nvarchar(200)
AS
BEGIN
declare #result nvarchar(200)
declare #len int
declare #skip int
set #len = len(#original)
set #result = ''
set #skip = (#take * -1) + 1
while #len > 0
begin
set #result = #result + substring(#original, #skip + #take, #take)
set #len = #len - #take
set #skip = #skip + #take
if #len > 0
set #result = #result + ' '
end
RETURN #result
END
And use it like this
select dbo.AddStuffCharacterInLength ('ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ',15, ' ')
And the output should be
----------------------------------------------------------------------------------------------------
ABCDEFGHIJKLMNO PQRSTUVWXYZABCD EFGHIJKLMNOPQRS TUVWXYZ
(1 row(s) affected)

MS-SQL stored procedure to MySQL

can anybody help me to write the following MS-SQL sp to MySQL sp,
use of this:
CREATE PROCEDURE sp_InputWork
#_DelimitedString nvarchar(MAX)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #_DataRow nvarchar(MAX)
DECLARE #_DescriptionOfWorkDone nvarchar(MAX)
DECLARE #_TemporaryStorage nvarchar(MAX)
DECLARE #_QTY int
DECLARE #_Total int
DECLARE #_CurrentField int
WHILE CHARINDEX(';', #_DelimitedString) > 0
BEGIN
SET #_DataRow = CAST(SUBSTRING(#_DelimitedString, 0, CHARINDEX(';', #_DelimitedString)) AS nvarchar(MAX))
SET #_CurrentField = 1
WHILE CHARINDEX(',', #_DataRow) > 0
BEGIN
SET #_TemporaryStorage = CAST(SUBSTRING(#_DataRow, 0, CHARINDEX(',', #_DataRow)) AS nvarchar(MAX))
IF #_CurrentField = 1
SET #_QTY = CAST(#_TemporaryStorage AS int)
IF #_CurrentField = 2
SET #_DescriptionOfWorkDone = #_TemporaryStorage
IF #_CurrentField = 3
SET #_Total = CAST(#_TemporaryStorage AS int)
SET #_DataRow = SUBSTRING(#_DataRow, CHARINDEX(',', #_DataRow) + 1, LEN(#_DataRow))
SET #_CurrentField = #_CurrentField + 1
END
INSERT INTO tblWorkDone (QTY, DescriptionOfWorkDone, Total) VALUES (#_QTY, #_DescriptionOfWorkDone, #_Total)
SET #_DelimitedString = SUBSTRING(#_DelimitedString, CHARINDEX(';', #_DelimitedString) + 1, LEN(#_DelimitedString))
END
END
I have changed the SP to Mysql
BEGIN
DECLARE _DataRow VARCHAR(21000);
DECLARE _DescriptionOfWorkDone VARCHAR(21000);
DECLARE _TemporaryStorage VARCHAR(21000) ;
DECLARE _QTY int;
DECLARE _Total int;
DECLARE _CurrentField int;
WHILE INSTR(_DelimitedString, ';') >0 DO
SET _DataRow = CAST(SUBSTRING(_DelimitedString, 1, INSTR(_DelimitedString,';' )) AS CHAR);
SET _CurrentField = 1;
WHILE INSTR(_DataRow,',' ) > 0 DO
SET _TemporaryStorage = CAST(SUBSTRING(_DataRow, 1, INSTR(_DataRow,',' )-1) AS CHAR);
IF _CurrentField = 1 then
SET _QTY = CAST(_TemporaryStorage AS UNSIGNED);
end if;
IF _CurrentField = 2 then
SET _DescriptionOfWorkDone = _TemporaryStorage;
end if;
IF _CurrentField = 3 then
SET _Total = CAST(_TemporaryStorage AS UNSIGNED) ;
end if;
SET _DataRow = SUBSTRING(_DataRow, INSTR( _DataRow,',') + 1, LENGTH(_DataRow));
SET _CurrentField = _CurrentField + 1;
END while;
INSERT INTO tblWorkDone (QTY, DescriptionOfWorkDone, Total) VALUES (_QTY, _DescriptionOfWorkDone, _Total);
SET _DelimitedString = SUBSTRING(_DelimitedString, INSTR(_DelimitedString,';' ) + 1, LENGTH(_DelimitedString));
END WHILE;END
Data inserted
CALL `sp_InputWork`('1,TEST,100,;2,TEST1,200,;3,TEST3,300,;')
Successfully looped and inserted to Mysql Table

T-SQL append number to variable

I couldn't find an answer to this....
I have three variables and need to switch between them in While Loop
Example:
DECLARE
#tableHTML NVARCHAR(MAX),
#email nvarchar(100),
#text1 nvarchar(100),
#text2 nvarchar(100),
#text3 nvarchar(100),
#number_suffix nvarchar(1)
SET #text1 = 'State of orders for Morfeus'
SET #text2 = 'State of orders for Fenix'
SET #text3 = 'State of orders for Perseus'
SET #number_suffix = 1
WHILE (#number_suffix < 4)
BEGIN
print #text(#number_suffix) /*and here is the problem */
SET #number_suffix = (#number_suffix + 1)
END
How do I append the number to variable #text please?
I am using MS SQL 2008
Do you want to append number to variable name? This is not possible. Why you need that, perhaps solution is more straightforward....
Try out following, perhaps id does what are you looking for:
DECLARE #cities TABLE(id int IDENTITY(1,1), cityName varchar(100))
INSERT INTO #cities(cityName) VALUES ('Morfeus'), ('Fenix'), ('Morfeus')
SELECT 'State of orders for ' + cityName
FROM #cities
Output:
State of orders for Morfeus
State of orders for Fenix
State of orders for Morfeus
To print number as well:
SELECT '#' + CAST(id AS varchar(2)) + ' State of orders for ' + cityName
FROM #cities
Output:
1 State of orders for Morfeus
2 State of orders for Fenix
3 State of orders for Morfeus
The question is not quite clear what your end game is but if I understand you correctly then something like this should work (note, you need to create the parse function first):
CREATE FUNCTION [dbo].[fnParseString]
(
#Section SMALLINT,
#Delimiter CHAR,
#Text VARCHAR(MAX)
)
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE #startindex NUMERIC(18,0),
#length NUMERIC(18,0),
#FieldPosition INT
SET #FieldPosition = ABS(#Section) - 1
SET #startindex = 0
WHILE #FieldPosition != 0
BEGIN
SET #FieldPosition = #FieldPosition - 1
SET #startindex = CHARINDEX(#Delimiter, #Text, #startindex + 1)
END
SET #Text = SUBSTRING(#Text, #startindex + 1, LEN(#Text) - #startindex)
SET #Text = SUBSTRING(#Text, 0, CHARINDEX(#Delimiter, #Text))
RETURN #Text
END
GO
DECLARE
#tableHTML NVARCHAR(MAX),
#email nvarchar(100),
#text nvarchar(100),
#number_suffix nvarchar(1)
SET #text = 'State of orders for Morfeus|State of orders for Fenix|State of orders for Perseus|'
SET #number_suffix = 1
WHILE (#number_suffix < 4)
BEGIN
PRINT dbo.fnParseString(#number_suffix, '|', #text)
SET #number_suffix = (#number_suffix + 1)
END
You can do it with Dynamic SQL but you'd need to reinitialize all you variables. The following will do it, but its a colossally bad idea, and you should use sll's answer instead
DECLARE
#tableHTML NVARCHAR(MAX),
#email nvarchar(100),
#number_suffix nvarchar(1),
#SQL nvarchar(max)
SET #number_suffix = 1
WHILE (#number_suffix < 4)
BEGIN
SET #SQL = N'
DECLARE #text1 nvarchar(100),
#text2 nvarchar(100),
#text3 nvarchar(100)
SET #text1 = ' + '''' + 'State of orders for Morfeus' + '''' +
'SET #text2 = ' + '''' + 'State of orders for Fenix' + '''' +
'SET #text3 = ' + '''' + 'State of orders for Perseus' + ''''
+
'PRINT #text' + #number_suffix
EXEC sp_executeSQL #SQL
SET #number_suffix = (#number_suffix + 1)
END