I wonder why recently I create functions but SQL Server returns error in calling them, in a case they get added to the functions list of the database.
For example for the following function I get such a error:
declare #cats nvarchar(1000)
set #cats = 'a|b|c|d|e'
SELECT dbo.fncSplit(#Cats, '|')
Error:
Cannot find either column "dbo" or the user-defined function or aggregate "dbo.fncSplit", or the name is ambiguous.
Sample Function:
CREATE FUNCTION [dbo].fncSplit
(
#RowData NVARCHAR(MAX),
#Delimeter NVARCHAR(MAX)
)
RETURNS #RtnValue TABLE
(
ID INT IDENTITY(1,1),
Data NVARCHAR(MAX)
)
AS
BEGIN
DECLARE #Iterator INT
SET #Iterator = 1
DECLARE #FoundIndex INT
SET #FoundIndex = CHARINDEX(#Delimeter,#RowData)
WHILE (#FoundIndex>0)
BEGIN
INSERT INTO #RtnValue (data)
SELECT
Data = LTRIM(RTRIM(SUBSTRING(#RowData, 1, #FoundIndex - 1)))
SET #RowData = SUBSTRING(#RowData,
#FoundIndex + DATALENGTH(#Delimeter) / 2,
LEN(#RowData))
SET #Iterator = #Iterator + 1
SET #FoundIndex = CHARINDEX(#Delimeter, #RowData)
END
INSERT INTO #RtnValue (Data)
SELECT Data = LTRIM(RTRIM(#RowData))
RETURN
END
Any suggestion or solution would be highly appreciated.
This is table-value function. The syntax is
declare #cats nvarchar(1000)
set #cats = 'a|b|c|d|e'
SELECT * from dbo.fncSplit(#Cats, '|')
Related
Requirement: I have a table for storing queries (SQL programs). I need to search and find out in this table such queries which have hardcoded values for a particular column (name) as shown below:
SELECT
*
FROM TABLE1 AC
WHERE
AC.name = 'hardcoded_value1'
UNION
SELECT
*
FROM TABLE2 BC
WHERE BC.name = 'hardcoded_value2'
I have tried and done this using a function and it works fine. But the requirement has a constraint which doesn't allow to make use of any function or stored procedure.
Below is the function definition for reference:-
CREATE OR ALTER FUNCTION [dbo].[GetConstantValue](#QueryID INT)
RETURNS
#Constantvalue TABLE
(
name_ NVARCHAR(2000)
)
AS
BEGIN
Declare #Query NVARCHAR(max) = SELECT code FROM QUERY_TABLE WHERE ID = #QueryID
Declare #StartIndex int = 0,#EndIndex int = 0,#Count int = 0,#ConstStr nvarchar(max) = ''
WHILE #Count <= LEN(#Query)
BEGIN
IF SUBSTRING(#Query,#Count, 1) = CHAR(39)
BEGIN
IF #StartIndex <> 0
BEGIN
SET #ConstStr = #ConstStr + CASE WHEN LEN(#ConstStr)>0 THEN '|' ELSE '' END+ SUBSTRING(#Query,#StartIndex+1,#Count-(#StartIndex+1))
SET #StartIndex = 0
SET #EndIndex = 0
END
ELSE
IF SUBSTRING(#Query,#Count-20, 20) LIKE '%name%[=]%'
SET #StartIndex = #Count
END
SET #Count = #Count + 1
END
INSERT INTO #Constantvalue
SELECT Value FROM string_split(#ConstStr,'|')
RETURN
END
Please suggest me a way to achieve this in the main query itself without making any function calls
How to get split string with quotation on each split item in SQL Server? I have tried this
declare #departmentNames as varchar(max) = 'Account, hod'
--declare #departmentNames as varchar(max) = 'Account'+', '+'hod'
print #departmentNames
I get result like this => Account,hod
but I want it like this => 'Account', 'hod'
so that I could use it in
select *
from tblDepartment
where name in (select item from splitString(#departmentNames, ','))
I know if I use integers with id column it will work fine i.e => 1, 2, 3, 4 but I want to try it with strings.
So is there anyone who can help me with this?
You can use apply :
select td.*
from tblDepartment td cross apply
<shema>.splitString(#departmentNames, ',') spt(item) -- add schema name
where spt.item = td.name;
If you want string comparison, you can do concatenation.
Note : use Schema name while calling UDF function.
First create this function:
CREATE FUNCTION [dbo].[fn_Split]
(#String varchar(8000),
#Delimiter varchar(50))
RETURNS #temptable TABLE (items varchar(8000))
AS
BEGIN
/*
SELECT * FROM dbo.fn_Split('12345;thome', ';')
*/
DECLARE #idx int
DECLARE #slice varchar(8000)
DECLARE #delimiterLength int
SET #delimiterLength = len(#Delimiter)
SELECT #idx = 1
IF LEN(#String) < 1 OR #String IS NULL
RETURN
WHILE #idx != 0
BEGIN
SET #idx = CHARINDEX(#Delimiter, #String)
IF #idx != 0
SET #slice = LEFT(#String, #idx - 1)
ELSE
SET #slice = #String
IF (LEN(#slice) > 0)
INSERT INTO #temptable(Items)
VALUES (LTRIM(RTRIM(#slice)))
SET #String = RIGHT(#String, LEN(#String) - #idx - #delimiterLength + 1)
IF LEN (#String) = 0
BREAK
END
RETURN
END
After creating this function then you can test with below query.
It splits words with any delimiter you are passing
select items from dbo.fn_Split('ACCOUNT ,HOD',',')
select items from dbo.fn_Split('ACCOUNT ; HOD',';')
Then pass variable and and use join with this function.
Use table alias for easy understanding
declare #departmentNames as varchar(max) = ('Account, hod')
select t.*
from tblDepartment t
inner join
(Select items
from dbo.fn_Split (#departmentNames, ',')) A on t.name = A.items
I create temptable for testing and this query will return output like below
I am trying to apply some logic to my select by creating the following function:
ALTER FUNCTION [dbo].[SelectemnExportObject]
(#TITLE NVARCHAR(MAX))
RETURNS NVARCHAR(20)
AS
BEGIN
DECLARE #Str NVARCHAR(MAX) = ''
DECLARE #Definition1 VARCHAR(MAX) = (SELECT DEFINITION1
FROM [dbo].test
WHERE title = #Title)
DECLARE #Definition2 VARCHAR(MAX) = (SELECT DEFINITION2
FROM [dbo].test
WHERE title = #Title)
DECLARE #Definition3 VARCHAR(MAX) = (SELECT DEFINITION3
FROM [dbo].test
WHERE title = #Title)
IF #Definition1 <> ''
SET #str = #Definition1
ELSE IF #Definition2 <> ''
SET #str = #str + '<br />' + #Definition2
ELSE IF #Definition3 <> ''
SET #str = #str + '<br />' + #Definition3
RETURN #Str
END
Am I correct in saying, to call this function is as such?
select *
from [dbo].[SelectemnExportObject]('absconding')
I am trying to create a row of information, cell 1 will contain #str, then will create another called #str2 and so on ..
Will I need to return something else if I want to accomplish this?
I appreciate the help, and apologies in advance if the tagging isn't correct
Because the function is returning a scalar value, it is a scalar function you would call it like:
select [dbo].[SelectemnExportObject]('absconding') AS [Str1]
,[dbo].[SelectemnExportObject]('abscondin2') AS [Str2]
If the function was returning a table (Inline table valued function or Multi-statement valued function) then you would need to call it/select from it as you were selecting from a table.
select * from [dbo].[SelectemnExportObject]('absconding')
Edit
To make your Function return multiple values you would need to convert this function into a multi-statement table valued function. The function definition would look something like....
CREATE FUNCTION [dbo].[SelectemnExportObject] ( #TITLE NVARCHAR(MAX) )
RETURNS #Result TABLE
(Str1 NVARCHAR(MAX) NOT NULL,
Str2 NVARCHAR(MAX) NOT NULL)
AS
BEGIN
DECLARE #Str1 NVARCHAR(MAX) = '';
DECLARE #Str2 NVARCHAR(MAX) = '';
/* Populate the values of #Str1 and #Str2 how ever you need to */
INSERT INTO #Result (Str1 , Str2)
VALUES (#Str1 , #Str2)
RETURN;
END
I have this query:
DECLARE #holdIds VARCHAR(MAX)
SET #holdIds = '1,2,3'
DECLARE #flagNames NVARCHAR(MAX);
SELECT
#flagNames = COALESCE(#flagNames + ',', '') + FlagName
FROM
BurnHoldStatus
WHERE
BurnHoldStatusID in (#holdIds);
SELECT #flagNames AS FlagName;
In this example the variable '#holdIds' has values '1,2,3' but could have just one value '1'.
When I run the query, an error appears:
Msg 245, Level 16, State 1, Line 6
Conversion failed when converting the varchar value '1,2,3' to data type int.
I try convert the value of '#holdIds' but not work.
Any idea?
Thanks.
[UPDATE]
I found the answer:
DECLARE #holdIds NVARCHAR(MAX);
SET #holdIds = '1,2,3';
DECLARE #holdIdList TABLE(id INT);
INSERT INTO #holdIdList
SELECT * FROM Split(#holdIds, ',');
DECLARE #flagNames NVARCHAR(MAX);
SELECT
#flagNames = COALESCE(#flagNames + ',', '') + FlagName
FROM
BurnHoldStatus, #holdIdList h
WHERE
BurnHoldStatusID = h.id;
SELECT #flagNames AS FlagName;
In this code I use an function 'Split' to split a string passing the divisor (i.e: ',').
Split function code:
ALTER FUNCTION [dbo].[Split]
(
#RowData nvarchar(MAX),
#SplitOn nvarchar(MAX)
)
RETURNS #RtnValue table
(
Data nvarchar(MAX)
)
AS
BEGIN
Declare #Cnt int
Set #Cnt = 1
While (Charindex(#SplitOn,#RowData)>0)
Begin
Insert Into #RtnValue (data)
Select
Data = ltrim(rtrim(Substring(#RowData,1,Charindex(#SplitOn,#RowData)-1)))
Set #RowData = Substring(#RowData,Charindex(#SplitOn,#RowData)+1,len(#RowData))
Set #Cnt = #Cnt + 1
End
Insert Into #RtnValue (data)
Select Data = ltrim(rtrim(#RowData))
Return
END
Thanks for Vercelli by show other post.
Thanks guys :)
The comment made by swe is correct. You could make the query dynamic, then insert #holdIds See below for a workaround:
DECLARE #holdIds VARCHAR(MAX)
SET #holdIds = '1,2,3'
SET #holdIds = (CHAR(39) + (REPLACE(#holdIds, ',', ''',''') + CHAR(39)))
You can do this, then set the entire query above as a varchar variable, then execute. There are certainly other workarounds as well but dynamic SQL will work.
there is a string is "'CNY','THB','USD','VND'" pass from coding.
is there any way that can split it into 'CNY','THB','USD','VND' because I was doing a IN statement. It cannot be done with "'CNY','THB','USD','VND'".
You can use this function, if you are using Microsoft SQL. It will return a table, and in your case you can easily specify if a string in question is in the result set of this table. I am showing you how to use it below
create FUNCTION [dbo].[SPLITSTRING]
(
#CSV varchar(max),
#Delimiter char(1)
)
RETURNS
#Split TABLE (Id int identity(1,1),[OutParam] varchar(max))
AS
BEGIN
Declare #Len as int, #Pos1 int, #Pos2 int
IF LTRIM(RTRIM(#CSV)) = ''
RETURN
SELECT #CSV = #Delimiter + #CSV + #Delimiter
select #Len = len(#csv), #Pos1 = 1
While #Pos1 < #Len
Begin
select #Pos2 = charindex(#Delimiter,#CSV,#Pos1 + 1)
insert #Split select ltrim(rtrim(substring(#csv, #Pos1+1, #Pos2 - #pos1 -1)))
select #Pos1 = #Pos2
End
RETURN
END
Then do
select * from [dbo].[SPLITSTRING]('CNY,THB,USD,VND',',')
What I am doing is creating a table, and splitting out the string between ",", and returning a table.
From above answer , no need of single quote. Pass the string as 'CNY,THB,USD,VND'
in query
Where Varchar_Field IN (select * from [dbo].[SPLITSTRING] ('CNY,THB,USD,VND',','))
Create a Table Vlaued Function
Create FUNCTION [dbo].[Split]
(
#RowData nvarchar(2000),
#SplitOn nvarchar(5)
)
RETURNS #RtnValue table
(
Data nvarchar(100)
)
AS
BEGIN
Declare #Cnt int
Set #Cnt = 1
While (Charindex(#SplitOn,#RowData)>0)
Begin
Insert Into #RtnValue (data)
Select
Data = ltrim(rtrim(Substring(#RowData,1,Charindex(#SplitOn,#RowData)-1)))
Set #RowData = Substring(#RowData,Charindex(#SplitOn,#RowData)+1,len(#RowData))
Set #Cnt = #Cnt + 1
End
Insert Into #RtnValue (data)
Select Data = ltrim(rtrim(#RowData))
Return
END
And Create a table where you want to use split string
Declare #SplitString Table
(
SubjectName nvarchar(50)
)
and Call The Function
INSERT INTO #SplitString SELECT * FROM dbo.Split("Your String",'Character from which you want to split')