Assume I have the following SQL snippet in SQL Server 2012:
DECLARE #fname varchar(20), #strVarName varchar(50)
SET #fname = 'cronus'
SET #strVarName = COVERT_VARIABLE_TO_STRING_NAME ( #fname)
--this should return '#fname'. this is not a value conversion this is converting a variable name to a string name
SELECT #strVarName
How do I do this?
SQL Server does not support reflection. You may be able to retrieve column or table names from its catalog views but with variables you're out of luck. Maybe you'll find another way to solve this issue with dynamic SQL.
Use dynamic sql query
DECLARE #fname varchar(20), #sql varchar(MAX)
SET #fname = 'cronus'
SET #sql = 'SELECT ' + #fname
EXEC (#sql)
There are following Character data types used to store character strings:
char,
varchar,
nvarchar,
text,
If u already used variable as String then why need to convert as a string
DECLARE #fname varchar(20), #strVarName varchar(50)
SET #fname = 'cronus'
SET #strVarName = #fname
SELECT #strVarName
if needed use CAST and CONVERT function
This is such a bizarre question, sounds like something I'd try to do.
Hmm, SQL is not supposed to do this but I guess, it doesn't mean you can't make it.
I think you would effectively have to write your own process to pull this off, something along the lines of:
Create dbo.sProcInserts stored procedure to insert values into a table:
Takes VariableName, Value and possibly table name to insert into as parameters
Create dbo.sProcExec stored procedure to execute stored procedure:
Before execute, read stored procedure into a variable
Find all variables that are SET (i.e. they have a SET #Var = OR SELECT #Var =)
After each variable set, add to your string a line that calls dbo.sProcInserts with the name of the variable and a select #Variable
Execute your newly written stored procedure
That way you don't have to actually make any modifications to your sProcs and it should catch the flow of variables and their changes through your procedure
However the requirement itself is a bit strange for me, but here is a way that could be a good start point for you:
declare #var1 int
Set #var1= 1
--some code here
declare #var2 nvarchar(max)
set #var2 = 10
--some other code here
declare #var3 bit
print ##VERSION
print 'this is fake #value inside a string'
--$ This is a Hint to help me find the Query that should parsed
declare #sql varbinary(max)
select #sql=sql_handle
from sys.sysprocesses
where spid=56
declare #q nvarchar(max)
select #q= substring(text,1,charindex('$',text)-3) from sys.dm_exec_sql_text(#sql)
Select distinct rtrim(ltrim(substring(Name,1,charindex(' ',Name)))) as Name from(
Select substring(replace(Name,'=',' '),8, Len(Name)) as Name from dbo.SplitString(#q,'declare ')
) as K
where Name like '#[^#]%'
By running the above query you will get the variables name.
Output:
#var1
#var2
#var3
You can find the source code for SplitString function Here
Note: If you are using SQL Server 2016 and your database's compatibility level is equal or greater than 130, you can also use SPLIT_STRING introduced by Microsoft it self. Learn more Here
I have the following function to remove set of character from a given string:
ALTER function removalspchar(#Name varchar(30))
returns varchar(500)
As
Begin
declare #sub char(1)
while patindex('%[-:;&, ]%',#Name)>0
begin
set #sub=substring(#Name,patindex('%[-:;&, ]%',#Name),1)
set #Name = replace(#Name,#sub,'')
end
return #Name
End
select dbo.removalspchar('CORP - Sovereign & Public Finance')
But the ouput of the following function coming as : CORPSovereignPublicFina rather than CORPSovereignPublicFinance.
Can somebody let me know what I am doing incorrect or a better way to resolve this issue.
Perhaps, you should increase length of param (#Name varchar(30)) say (#Name varchar(100)).
I'm asking this question for SQL Server 2008 R2
I'd like to know if there is a way to create multiple functions in a single batch statement.
I've made the following code as an example; suppose I want to take a character string and rearrange its letters in alphabetical order. So, 'Hello' would become 'eHllo'
CREATE FUNCTION char_split (#string varchar(max))
RETURNS #characters TABLE
(
chars varchar(2)
)
AS
BEGIN
DECLARE #length int,
#K int
SET #length = len(#string)
SET #K = 1
WHILE #K < #length+1
BEGIN
INSERT INTO #characters
SELECT SUBSTRING(#string,#K,1)
SET #K = #K+1
END
RETURN
END
CREATE FUNCTION rearrange (#string varchar(max))
RETURNS varchar(max)
AS
BEGIN
DECLARE #SplitData TABLE (
chars varchar(2)
)
INSERT INTO #SplitData SELECT * FROM char_split(#string)
DECLARE #Output varchar(max)
SELECT #Output = coalesce(#Output,' ') + cast(chars as varchar(10))
from #SplitData
order by chars asc
RETURN #Output
END
declare #string varchar(max)
set #string = 'Hello'
select dbo.rearrange(#string)
When I try running this code, I get this error:
'CREATE FUNCTION' must be the first statement in a query batch.
I tried enclosing each function in a BEGIN END block, but no luck. Any advice?
Just use a GO statement between the definition of the UDFs
Not doable. SImple like that.
YOu can make it is one statement using a GO between them.
But as the GO is a batch delimiter.... this means you send multiple batches, which is explicitly NOT Wanted in your question.
So, no - it is not possible to do that in one batch as the error clearly indicates.
SQL Server comes with a number of string functions, such as RIGHT(), which accepts an Expression as a parameter so that it can accept either a varchar or nvarchar value.
How do I create my own custom function to do the same?
I am not a SQL Server expert, so a simple example with syntax would help.
Thank You
Here is a simple example:
CREATE FUNCTION myUDF (#input nvarchar(255))
RETURNS nvarchar(255)
AS
BEGIN
-- function logic here
declare #output nvarchar(255)
select #output = 'The value passed in was: ' + #input
return #output
End
GO
select dbo.myUDF('I wrote a function!')
Here you can try this way.
How to: Create and Run a CLR SQL Server User-Defined Function
[Update: Using SQL Server 2005]
Hi, what I want to do is query my stored procedure with a comma-delimited list of values (ids) to retrieve rows of data.
The problem I am receiving is a conversion error:
Conversion failed when converting the varchar value ' +
#PassedInIDs + ' to data type int.
The statement in my where-clause and error is:
...
AND (database.ID IN (' + #PassedInIDs + '))
Note: database.ID is of int type.
I was following the article at:
http://www.sql-server-helper.com/functions/comma-delimited-to-table.aspx
but did not complete because of the error.
In my execution script I have:
...
#PassedInIDs= '1,5'
Am I doing something wrong here?
Thank you for your help.
I would strongly suggest that you use the second method from that link. Create a user-defined function that turns your comma-delimited string into a table, which you can then select from easily.
If you do a Google on Erland and "Dynamic SQL" he has a good writeup of the pitfalls that it entails.
For one, you are passing a string to the IN function in SQL. If you look back at the original article, you'll see that instead of issuing a direct SQL statement, it instead is building a string which is the SQL statement to execute.
There is no string evaluation in SQL. This:
database.ID IN (' + #PassedInIDs + ')
will not be turned to:
database.ID IN (1,2,3)
just because the #PassedInIDs parameter happens to contain '1,2,3'. The parameter is not even looked at, because all you have is a string containing " + #PassedInIDs + ". Syntactically, this is equivalent to:
database.ID IN ('Bob')
To make it short, you can't do what you attempt here in SQL. But there are four other possibilities:
you construct the SQL string in the calling language and abandon the stored procedure altogether
you use a dynamic prepared statement with as many parameters in the IN clause as you pan to use
you use a fixed prepared statement with, say, 10 parameters: IN (?,?,?,?,?,?,?,?,?,?), filling only as many as you need, setting the others to NULL
you create a stored procedure with, say, 10 parameters and pass in as many as you need, setting the others to NULL: IN (#p1, #p2, ..., #p10).
I would create a CLR table-valued function:
http://msdn.microsoft.com/en-us/library/ms131103.aspx
In it, you would parse the string apart and perform a conversion to a set of rows. You can then join on the results of that table, or use IN to see if an id is in the list.
You need to treat ufn_CSVToTable like it's a table. So you can join the function:
JOIN ufn_CSVToTable(#PassedInIDs) uf ON database.ID = uf.[String]
I suggest using XML for this in SQL 2005. Somewhat bulkier, but it can be easier. It allows you to select the XML into a table which can then be joined or inserted etc.
Look at Sql Server's OPENXML() if you haven't already.
For example, you could pass in something like:
'12...'
and then use:
exec sp_xml_preparedocument #doc OUTPUT, #xmlParam
SELECT element
FROM OPENXML (#doc, 'Array/Value', 2) WITH (element varchar(max) 'text()')
That should be a start
this may be solved by 6 ways as mentioned in Narayana's article Passing a list/array to an SQL Server stored procedure
And my most strait forward implementation is
declare #statement nvarchar(256)
set #statement = 'select * from Persons where Persons.id in ('+ #PassedInIDs +')'
exec sp_executesql #statement
-
Here is what I have found and tested:
SET QUOTED_IDENTIFIER ON
SET ANSI_NULLS ON
GO
CREATE FUNCTION [dbo].[SplitStrings] ( #IDsList VARCHAR(MAX) )
RETURNS #IDsTable TABLE ( [ID] VARCHAR(MAX) )
AS
BEGIN
DECLARE #ID VARCHAR(MAX)
DECLARE #Pos VARCHAR(MAX)
SET #IDsList = LTRIM(RTRIM(#IDsList)) + ','
SET #Pos = CHARINDEX(',', #IDsList, 1)
IF REPLACE(#IDsList, ',', '') <> ''
BEGIN
WHILE #Pos > 0
BEGIN
SET #ID = LTRIM(RTRIM(LEFT(#IDsList, #Pos - 1)))
IF #ID <> ''
BEGIN
INSERT INTO #IDsTable
( [ID] )
VALUES ( CAST(#ID AS VARCHAR) )
END
SET #IDsList = RIGHT(#IDsList, LEN(#IDsList) - #Pos)
SET #Pos = CHARINDEX(',', #IDsList, 1)
END
END
RETURN
END
GO
Here is how function Call:
SELECT * FROM dbo.SplitStrings('123,548,198,547,965')
Try this:
DECLARE #Ids varchar(50);
SET #Ids = '1,2,3,5,4,6,7,98,234';
SELECT *
FROM sometable
WHERE ','+#Ids+',' LIKE '%,'+CONVERT(VARCHAR(50),tableid)+',%';