SQL Concat field from multiple rows - sql

I would like to create a function that returns a concatinated string of a given field of given query. Here is what I did.
And this one gives me an error.
Must declare the table variable "#qry".
CREATE FUNCTION dbo.testing
(
#qry varchar(1000),
#fld varchar(100),
#separator varchar(15) = '; '
)
RETURNS varchar
AS
BEGIN
DECLARE #rslt varchar(1000)
SET #rslt =''
SELECT #rslt = #rslt + #separator + CAST(#fld as varchar(160)) FROM #qry
RETURN #rslt
END
What I am trying to do is pass a query to this function and receive a concatinated string for certain field of the query.
Is this possible?
What am I doing wrong?
EDIT: BTW I have MSSQL Server 2005;

If you want to pass through any form of dynamic SQL, you need to execute it via EXEC or (preferred) sp_ExecuteSQL. Make sure your code's not subject to any injection attacks if you're using dynamic SQL as well lest you suffer the wrath of little Bobby Tables :-)

You can't do a FROM #variable. You'd have to use dynamic SQL and make your #qry a derived table or something of that nature. However, I think that's really not the best approach. I believe this is what you're trying to do:
http://geekswithblogs.net/mnf/archive/2007/10/02/t-sql-user-defined-function-to-concatenate-column-to-csv-string.aspx
Make sure to read the comments on the XML alternative solution as well.

Related

Is it possible to declare a Database as a variable?

I am working on data migration and want to be able to change my SourceDatabase without eding the code in multiple places is this possible? This is what I have tried from looking at some other posts but I must be doing something wrong
Declare #SourceDatabase VARCHAR(255)
Set #SourceDatabase = '[PrimaryTesting]';
Select LAid+Dfeid as DFE,SchoolName from #SourceDatabase.dbo.School;
I assume you're using MSSQL, in which case you'd have to build up the desired SQL string, then use the exec statement to run it:
declare #SourceDatabase VARCHAR(255) = '[PrimaryTesting]';
exec('select LAid+Dfeid as DFE,SchoolName from ' + #SourceDatabase + '.dbo.School;');
However, please be aware of the possible dangers of SQL injection when using this approach.

How do i convert variable name to string name?

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

Creating a dynamic table from dynamic SQL

First of all I'm using ms SQL server 2012. I' trying to use a table based on a string value passed in as a string into a procedure. I found out that you can't use strings are table names when writing a query so I'm trying to find a way around that. The only lead I'm kind of onto is using dynamic SQL which I also am not sure how to make work. Here is what I have:
DECLARE #q AS NVARCHAR(MAX)
SET #q = 'SELECT * FROM ' + #tableName
DECLARE #tableCopy AS EXECUTE(#q)
How can I get the executed #q into #tableCopy? Or is there a better way to access my table when all I know is the tables name as a string?
You can create the temporary table and then insert into that table inside the dynamic sql. There's an example here:
http://smehrozalam.wordpress.com/2009/10/14/t-sql-using-result-of-a-dynamic-sql-query-in-a-variable-or-table/
Unfortunately, you would need to know the schema. The following does not work:
declare #query varchar(max) =
'select * into #t from table'
EXEC(#query)
select * FROM #t

how to concatenate varying stored procedure parameters

please help me with writing this search sql stored procedure
procedure may have different number of parameters at different time
so could any body help me with writing this query. I don't know how to concatenate parameters.
i am new to stored procedure
CREATE PROCEDURE searchStudent
-- Add the parameters for the stored procedure here
#course int=null,
#branch int=null,
#admissionYear varchar(max)=null,
#passingYear varchar(max)=null,
#userName varchar(max)=null,
#sex varchar(max)=null,
#studyGap varchar(max)=null,
#firstName varchar(max)=null,
#lastName varchar(max)=null
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE query STR DEFAULT null
IF #course IS NOT NULL
THEN query=
SELECT * FROM [tbl_students] WHERE
END
GO
please complete the query so that it can have parameters which are having values and can search from database on the basis of parameters value. But parameter may vary every time depends on search criteria.
You would probably need to use Dynamic SQL to achieve this. First of all I would highly recommend reading this excellent article. http://www.sommarskog.se/dynamic_sql.html
You're dynamic sql would be something like this;
Declare #query varchar(max)
Set #query = 'Select * From dbo.MyTable Where '
If #Course Is Not Null
Begin
Set #query = #query + 'Course = ' + Convert(varchar(10), #Course)
end
If #Branch Is Not Null
Begin
Set #query = #query + ' and Branch = ' + Convert(varchar(10), #Branch )
end
This is only an example! You will need to build in some checks to ensure that you have one (and only one) Where clause, you must ensure that the integer values are converted to string values correctly. You must also check that the parameters don't have any special characters that could break the dynamic sql - like an apostrophe (')
Using dynamic SQL can be painful and very difficult to get right.
Good luck!
The key with a dynamic search conditions is to make sure an index is used, instead of how can I easily reuse code, eliminate duplications in a query, or try to do everything with the same query. Here is a very comprehensive article on how to handle this topic:
Dynamic Search Conditions in T-SQL by Erland Sommarskog
It covers all the issues and methods of trying to write queries with multiple optional search conditions. This main thing you need to be concerned with is not the duplication of code, but the use of an index. If your query fails to use an index, it will preform poorly. There are several techniques that can be used, which may or may not allow an index to be used.
here is the table of contents:
Introduction
The Case Study: Searching Orders
The Northgale Database
Dynamic SQL
Introduction
Using sp_executesql
Using the CLR
Using EXEC()
When Caching Is Not Really What You Want
Static SQL
Introduction
x = #x OR #x IS NULL
Using IF statements
Umachandar's Bag of Tricks
Using Temp Tables
x = #x AND #x IS NOT NULL
Handling Complex Conditions
Hybrid Solutions – Using both Static and Dynamic SQL
Using Views
Using Inline Table Functions
Conclusion
Feedback and Acknowledgements
Revision History
Sorry, I am having trouble understanding what you are asking. Do you mean the consumer of the sproc may specify some arbitrary subset of the parameters and you want to filter on those?
Assuming the above you have 2 options.
1.
use a where clause something like this:
WHERE ([tbl_students].firstName = ISNULL(#firstname,firstName)
AND ([tbl_students].lastName = ISNULL(#lastName ,lastName )
etc.
What this does is check if your parameter has a value, and, if so, it will compare it to the column. If the param is null, then it will compare the column to itself, which will never filter anything out.
use dynamic sql in your sproc and just include the line of the where clause you want if the param is not null.

Using Parameter Values In SQL Statement

I am trying to write a database script (SQL Server 2008) which will copy information from database tables on one server to corresponding tables in another database on a different server.
I have read that the correct way to do this is to use a sql statement in a format similar to the following:
INSERT INTO <linked_server>.<database>.<owner>.<table_name> SELECT * FROM <linked_server>.<database>.<owner>.<table_name>
As there will be several tables being copied, I would like to declare variables at the top of the script to allow the user to specify the names of each server and database that are to be used. These could then be used throughout the script. However, I am not sure how to use the variable values in the actual SQL statements. What I want to achieve is something like the following:
DECLARE #SERVER_FROM AS NVARCHAR(50) = 'ServerFrom'
DECLARE #DATABASE_FROM AS NVARCHAR(50) = 'DatabaseTo'
DECLARE #SERVER_TO AS NVARCHAR(50) = 'ServerTo'
DECLARE #DATABASE_TO AS NVARCHAR(50) = 'DatabaseTo'
INSERT INTO #SERVER_TO.#DATABASE_TO.dbo.TableName SELECT * FROM #SERVER_FROM.#DATABASE_FROM.dbo.TableName
...
How should I use the # variables in this code in order for it to work correctly?
Additionally, do you think my method above is correct for what I am trying to achieve and should I be using NVARCHAR(50) as my variable type or something else?
Thanks
There is probably a better way to do this, but what you are probably trying to do in your example is what's called dynamic SQL where you treat the statement as a string and the execute it. This would be section #2 here:
http://www.mssqltips.com/tip.asp?tip=1160
There are some major downsides to dynamic SQL. You see a couple other approaches that might be better in that article.
If you want to execute a dynamically generated query then you have to use sp_ExecuteSQL
HTH
For the nvarchar(50) - you'd be better using sysname. This is a synonym in SQL Server (for nvarchar(128)) and represents the maximum length of an object identifier.
have a look at http://msdn.microsoft.com/en-us/library/ms188001.aspx - sp_executesql takes a parameter that is a string and executes the sql in that string. so you'd need to concatenate #SERVER_FROM and other params with the INSERT INTO part to make the entire sql statement, and then pass to sp_executesql.
nvarchar(50) is fine, unless your server/database names are longer than that :)
You can create the select statement by concatenating all the information together and then use sp_executesql
so:
sp_executesql 'INSERT INTO ' + #SERVER_TO + '.' + #DATABASE_TO +
'.dbo.TableName SELECT * FROM ' + #SERVER_FROM + '.' +
#DATABASE_FROM+'.dbo.TableName'
I like to make templates for dynamic SQL things like this - it's a lot easier to maintain complex statements and also sometimes easier to handle nested quotes - and definitely easier when terms need to be repeated in multiple places (like column lists):
DECLARE #sql AS nvarchar(max);
SET #sql = 'INSERT INTO {#SERVER_TO}.{#DATABASE_TO}.dbo.TableName
SELECT *
FROM {#SERVER_FROM}.{#DATABASE_FROM}.dbo.TableName'
SET #sql = REPLACE(#sql, '{#SERVER_TO}', QUOTENAME(#SERVER_TO))
SET #sql = REPLACE(#sql, '{#DATABASE_TO}', QUOTENAME(#DATABASE_TO))
SET #sql = REPLACE(#sql, '{#SERVER_FROM}', QUOTENAME(#SERVER_FROM))
SET #sql = REPLACE(#sql, '{#DATABASE_FROM}', QUOTENAME(#DATABASE_FROM))
EXEC(#sql)