I want to display a string in a table format as shown below:
For a string like 'hi,is,1,question,thanks,.,.,n'
I need this result:
column1 column2 column3 column4 ..... column
hi is 1 question ..... n
DECLARE #string VARCHAR(MAX);
SET #string = 'hi,is,1,question,thanks,.,.,n';
DECLARE #SQL VARCHAR(MAX);
SET #SQL = 'SELECT ''' + REPLACE(#string, ',', ''',''') + '''';
EXEC (#SQL);
Result:
Add SELECT ' at beginning and ' at the end of string
Replace all , with ',' inside string
So string 'hi,is,1,question,thanks,.,.,n' is replace by 'SELECT 'hi','is','1','question','thanks','.','.','n''
Executed as SQL query
PS: If you want to use it on column you will have to combine it with CURSOR
Update
DECLARE #table TABLE
(
ID INT IDENTITY,
string VARCHAR(MAX)
);
INSERT INTO #table
VALUES
('This,is,a,string,,n,elements,..');
INSERT INTO #table
VALUES
('And,one,more');
INSERT INTO #table
VALUES
('Ugly,but,works,,,Yay!,..,,,10,11,12,13,14,15,16,17,18,19,..');
SELECT * FROM #table
DECLARE #string_to_split VARCHAR(MAX);
DECLARE #sql_query_to_execute VARCHAR(MAX);
DECLARE #max_elements INT, #id INT, #i INT;
SET #i = 1;
DECLARE string_cursor CURSOR FOR SELECT ID, string FROM #table;
SELECT #max_elements = MAX(LEN(string) - LEN(REPLACE(string, ',', ''))) + 1 -- Find max number of elements */
FROM #table;
IF OBJECT_ID('tempdb..##my_temp_table_for_splitted_columns') <> 0 -- Create new temp table with valid amount of columns
DROP TABLE ##my_temp_table_for_splited_columns;
SET #sql_query_to_execute = 'create table ##my_temp_table_for_splitted_columns ( ID int,';
WHILE #i <= #max_elements
BEGIN
SET #sql_query_to_execute = #sql_query_to_execute + ' Col' + CAST(#i AS VARCHAR(max)) + ' varchar(25), ';
SET #i = #i + 1;
END;
SELECT #sql_query_to_execute = SUBSTRING(#sql_query_to_execute, 1, LEN(#sql_query_to_execute) - 1) + ')';
EXEC (#sql_query_to_execute);
/* Split string for each row */
OPEN string_cursor;
FETCH NEXT FROM string_cursor
INTO #id,
#string_to_split
WHILE ##FETCH_STATUS = 0
BEGIN
SET #i = MAX(LEN(#string_to_split) - LEN(REPLACE(#string_to_split, ',', ''))) + 1; -- check amount of columns for current string
WHILE #i < #max_elements
BEGIN
SET #string_to_split = #string_to_split + ','; -- add missing columns
SET #i = #i + 1;
END;
SET #sql_query_to_execute = 'SELECT ' + CAST(#id AS VARCHAR(MAX)) + ',''' + REPLACE(#string_to_split, ',', ''',''') + '''';
INSERT INTO ##my_temp_table_for_splitted_columns --insert result to temp table
EXEC (#sql_query_to_execute);
FETCH NEXT FROM string_cursor
INTO #id,
#string_to_split;
END;
CLOSE string_cursor;
DEALLOCATE string_cursor;
SELECT *
FROM ##my_temp_table_for_splitted_columns;
This is not trivial. You will find a lot of examples how to split your string in a set of fragments. And you will find a lot of examples how to pivot a row set to a single row. But - adding quite some difficulty - you have an unknown count of columns. There are three approaches:
Split this and return your set with a known maximum of columns
Use a dynamically created statement and use EXEC. But this will not work in VIEWs or iTVFs, nor will it work against a table.
Instead of a column list you return a generic container like XML
with a known maximum of columns
One example for the first was this
DECLARE #str VARCHAR(1000)='This,is,a,string,with,n,elements,...';
SELECT p.*
FROM
(
SELECT A.[value]
,CONCAT('Column',A.[key]+1) AS ColumnName
FROM OPENJSON('["' + REPLACE(#str,',','","') + '"]') A
) t
PIVOT
(
MAX(t.[value]) FOR ColumnName IN(Column1,Column2,Column3,Column4,Column5,Column6,Column7,Column8,Column9 /*add as many as you need*/)
) p
Hint: My approach to split the string uses OPENJSON, not available before version 2016. But there are many other approaches you'll find easily. It's just an example to show you the combination of a splitter with PIVOT using a running index to build up a column name.
Unknown count of columns
And the same example with a dynamically created column list was this:
DECLARE #str VARCHAR(1000)='This,is,a,string,with,n,elements,...';
DECLARE #CountElements INT=LEN(#str)-LEN(REPLACE(#str,',',''))+1;
DECLARE #columnList NVARCHAR(MAX)=
STUFF((
SELECT TOP(#CountElements)
CONCAT(',Column',ROW_NUMBER() OVER(ORDER BY (SELECT 1)))
FROM master..spt_values /*has a lot of rows*/
FOR XML PATH('')
),1,1,'');
DECLARE #Command NVARCHAR(MAX)=
N'SELECT p.*
FROM
(
SELECT A.[value]
,CONCAT(''Column'',A.[key]+1) AS ColumnName
FROM OPENJSON(''["'' + REPLACE(''' + #str + ''','','',''","'') + ''"]'') A
) t
PIVOT
(
MAX(t.[value]) FOR ColumnName IN(' + #columnList + ')
) p;';
EXEC(#Command);
Hint: The statement created is exactly the same as above. But the column list in the pivot's IN is created dynamically. This will work with (almost) any count of words generically.
If you need more help, please use the edit option of your question and provide some more details.
An inlineable approach for a table returning a generic container
If you need this against a table, you might try something along this:
DECLARE #tbl TABLE(ID INT IDENTITY,YourList NVARCHAR(MAX));
INSERT INTO #tbl VALUES('This,is,a,string,with,n,elements,...')
,('And,one,more');
SELECT *
,CAST('<x>' + REPLACE((SELECT t.YourList AS [*] FOR XML PATH('')),',','</x><x>') + '</x>' AS XML) AS Splitted
FROM #tbl t
This will return your list as an XML like
<x>This</x>
<x>is</x>
<x>a</x>
<x>string</x>
<x>with</x>
<x>n</x>
<x>elements</x>
<x>...</x>
You can grab - if needed - each element by its index like here
TheXml.value('/x[1]','nvarchar(max)') AS Element1
I have a stored procedure which takes 'table name' as parameter. I want to store my 'exec' results to a variable and display using that variable.
Here is my T-SQL stored procedure..
create procedure DisplayTable( #tab varchar(30))
as
begin
Declare #Query VARCHAR(30)
set #Query='select * from ' +#tab
EXEC (#Query)
END
I want to do something like this..
SET #QueryResult = EXEC (#Query)
select #QueryResult
How do i achieve this.. Please help.. I am a beginner..
You can use XML for that. Just add e.g. "FOR XML AUTO" at the end of your SELECT. It's not tabular format, but at least it fulfills your requirement, and allows you to query and even update the result. XML support in SQL Server is very strong, just make yourself acquainted with the topic. You can start here: http://technet.microsoft.com/en-us/library/ms178107.aspx
alter procedure DisplayTable(
#tab varchar(30)
,#query varchar(max) output
)
as
BEGIN
Declare #execution varchar(max) = 'select * from ' +#tab
declare #tempStructure as table (
pk_id int identity
,ColumnName varchar(max)
,ColumnDataType varchar(max)
)
insert into
#tempStructure
select
COLUMN_NAME
,DATA_TYPE
from
INFORMATION_SCHEMA.columns
where TABLE_NAME= #tab
EXEC(#execution)
declare #ColumnCount int = (SELECT count(*) from #tempStructure)
declare #counter int = 1
while #counter <= #ColumnCount
BEGIN
IF #counter = 1
BEGIN
set #query = (SELECT ColumnName + ' ' + ColumnDataType FROM #tempStructure where pk_id= #counter)
END
IF #counter <> 1
BEGIN
set #query = #query + (SELECT ',' + ColumnName + ' ' + ColumnDataType FROM #tempStructure where #counter = pk_id)
END
set #counter = #counter + 1
END
END
When you execute the SP, you'll now get a return of the structure of the table you want.
This should hopefully get you moving.
If you want the table CONTENTS included, create yourself a loop for the entries, and append them to the #query parameter.
Remember to delimit the #query, else when you read it later on, you will not be able to restructure your table.
First of all you have to understand that you can't just store the value of a SELECTon a table in simple variable. It has to be TABLE variable which can store the value of a SELECTquery.
Try the below:
select 'name1' name, 12 age
into MyTable
union select 'name2', 15 union
select 'name3', 19
--declaring the table variable and selecting out of it..
declare #QueryResult table(name varchar(30), age int)
insert #QueryResult exec DisplayTable 'MyTable'
select * from #QueryResult
Hope this helps!
I am using a dynamic sql i.e.
DECLARE #searchstring VARCHAR(500)
DECLARE #str VARCHAR(MAX)
SELECT #str = 'SELECT * FROM Table1 WHERE ' + #searchstring
EXECUTE #str
What I need is I want to select one column value from above dynamic sql to pass in a different SP
Let's say I need ID column value and pass it to another sp named GetAnotherData #Ids. How can I do that?
well you can go with Alexander Fedorenko example, but if you don't want to create any temp tables, you can use output xml parameter to pass your ids:
declare #stmt nvarchar(max), #Data xml, #searchstring nvarchar(max)
select #stmt = '
select #Data = (
select id
from Table1
where ' + #searchstring + '
for xml raw(''Data'')
)
'
exec sp_executesql
#stmt = #stmt,
#params = N'#Data xml output',
#Data = #Data output
select
T.C.value('#id', 'int') as id
from #Data.nodes('Data') as T(C)
sql fiddle demo
The following example creates a user-defined table type that has one Id column. Further the INSERT #RetIds EXEC(#STR) statement fills the parameter list, and then passes the values to a stored procedure
CREATE TYPE RetIds AS TABLE
(
Id int
)
DECLARE #searchstring varchar(500) = 'AND SearchCol = 1'
DECLARE #str varchar(max)
SELECT #str ='SELECT Id FROM dbo.test6 WHERE 1 = 1 ' + #searchstring
DECLARE #RetIds AS RetIds
INSERT #RetIds
EXEC(#str)
EXEC dbo.ExecIds #RetIds
See demo on SQLFiddle
I am using this logic to split the string query
declare #query nvarchar(max)
set #query = '1&2&3&4&5&6&7&8&9&10&11&12&13&14'
SELECT SUBSTRING('&' + #query + '&', Number + 1, -- is used to split the '#query' on the basis of '&' sign
CHARINDEX('&', '&' + #query + '&', Number + 1) - Number -1)AS VALUE
FROM master..spt_values
WHERE Type = 'P'
AND Number <= LEN('&' + #query + '&') - 1
AND SUBSTRING('&' + #query + '&', Number, 1) = '&'
It works fine when query is small, but its giving me less result then actual when the value of #query is very large
For eg.
#query = 'very large string containing 60 & sign '
returns only 10 records
How can I split large string, and what is the reason? Why can SUBSTRING not handle large strings?
You can use this function. It returns a table of splitted values, based on input string and a delimeter.
Usage:
select *
from dbo.fn_ParseText2Table('1&2&3&4&5&6&7&8&9&10&11&12&13&14','&')
The function has a parameter #p_SourceText which type is varchar(8000), so input string can be up to 8000 characters.
You can change type to varchar(max) if version of your SQL Server allows you to do this.
I used this Function and its working for me Perfectly :)
CREATE function f_split(#SourceSql nvarchar(Max),#StrSeprate varchar(10))
returns #temp
table([column] nvarchar(Max))
begin
declare #i int
set #SourceSql=rtrim(ltrim(#SourceSql))
set #i=charindex(#StrSeprate,#SourceSql)
while #i>=1
begin
insert #temp values(left(#SourceSql,#i-1))
set #SourceSql=substring(#SourceSql,#i+1,len(#SourceSql)-#i)
set #i=charindex(#StrSeprate,#SourceSql)
end
if #SourceSql<>'\'
insert #temp values(#SourceSql)
return
end
go
select * from dbo.f_split('1,2,3,4,5',',')
go
I am not sure why your code is not getting the result. I executed the query with large amount of data. But I got the result. May be your string is very much bigger than I did the testing. I have also the same requirement to split the string. I am using this function to get the solution. You can try this.
CREATE FUNCTION [dbo].[fnSplitString] ( #MyArray VARCHAR(8000), #separator CHAR(1) )
RETURNS #RetTable TABLE
(StrValue VARCHAR(256))
AS
BEGIN
DECLARE #SeperatorString VARCHAR(10);
SET #SeperatorString = '%' + #separator + '%'
DECLARE #separator_position INT
DECLARE #array_value VARCHAR(1000)
SET #MyArray = #MyArray + #separator
WHILE PATINDEX( #SeperatorString , #MyArray) <> 0
BEGIN
SELECT #separator_position = PATINDEX(#SeperatorString , #MyArray)
SELECT #array_value = LEFT(#MyArray, #separator_position - 1)
INSERT #RetTable VALUES ( CAST(#array_value AS VARCHAR(256)) )
SELECT #MyArray = STUFF(#MyArray, 1, #separator_position, '')
END
RETURN
END
If you want more explanation on this function, how the function is using and what the parameters are , you can take a look here.. This is very simple function and easy to use.
I'm running a query using "EXEC sp_helptext Object", but it returns multiple lines with a column name Text. I'm trying to concatenate that value into a single string but I'm having trouble trying to figure out the best way to do it using T-SQL.
You can try something like this
DECLARE #Table TABLE(
Val VARCHAR(MAX)
)
INSERT INTO #Table EXEC sp_helptext 'sp_configure'
DECLARE #Val VARCHAR(MAX)
SELECT #Val = COALESCE(#Val + ' ' + Val, Val)
FROM #Table
SELECT #Val
This will bring back everything in one line, so you might want to use line breaks instead.
Assuming SQL Server 2005 and above (which is implied by varchar(max) in astander's answer), why not simply use one of these
SELECT OBJECT_DEFINITION('MyObject')
SELECT definition FROM sys.sql_modules WHERE object_id = OBJECT_ID('MyObject')
This is not very glamorous, but it works ...
DECLARE #Table TABLE(
Val VARCHAR(MAX)
)
INSERT INTO #Table EXEC sp_helptext 'sp_configure'
DECLARE #Val VARCHAR(MAX)
SET #Val = ''
SELECT #Val = #Val + REPLACE(REPLACE(REPLACE(Val, CHAR(10), ''), CHAR(13), ''), CHAR(9), '')
FROM #Table
-- Replaces line breaks and tab keystrokes.
SELECT #Val