Why newly created functions can not be found by SQL Server? - sql-server

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

How to find hardcoded values defined in text using MS SQL query without using functions

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?

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

SQL Server: creating functions

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

Select query using varchar with 'in'

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.

split string by " " in a sql query

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')

Resources