converting rows into columns in t-sql - sql server 2005 - sql-server-2005

I have situation that I have a table in the structure
ID, name
1, 'value1'
1, 'value2'
2, 'value3'
2, 'value4'
1, 'value5'
I wanted to show the above data in following format
id , combineName
1 ,'value1','value2', 'value5'
2 ,'value3','value4'
Is there an easy way to do this in SQL Server 2005, or will I have to run cursors to do it?

Assuming your data is in aTable:
create FUNCTION toCSV (#id int)
RETURNS varchar(100)
AS
BEGIN
DECLARE #List varchar(100)
SELECT #List = COALESCE(#List + ', ', '') +
CAST(name AS varchar(10))
FROM aTable
WHERE ID = #id
RETURN(#list)
END;
go
Then:
select distinct id, dbo.toCSV(id) from aTable

SQL 2005 has a PIVOT function that should do what you want.
http://msdn.microsoft.com/en-us/library/ms177410.aspx

You can do this using nested selects, or more easily using the pivot operator, although you have to know all of the possible values before hand.
If you want it to be dynamic, then you will need a cursor and some dynamic SQL.

Simple Example of COALESCE Function:
Created one Temp table in which i have put one 9 rows with the help of WHILE loop.
The at the Main part i have just take Column to COALESCE function.
DROP TABLE #Material
SET NOCOUNT ON
CREATE TABLE #Material
(
MaterialID INT
)
DECLARE #LoopCounter INT
DECLARE #MaxLoopCounter INT
SET #LoopCounter = 1
SET #MaxLoopCounter = 10
WHILE (#LoopCounter < #MaxLoopCounter)
BEGIN
INSERT INTO #Material (MaterialID) VALUES (#LoopCounter)
SET #LoopCounter = #LoopCounter + 1
END
/* MAIN PART */
DECLARE #MaterialID VARCHAR(100)
SELECT #MaterialID = COALESCE(#MaterialID + ',','') + CAST(MaterialID AS VARCHAR(100)) FROM #Material
PRINT 'FINAL OUTPUT: '+ #MaterialID
-- SELECT * FROM #Material
SET NOCOUNT OFF

Related

Declared varchar in where condition

I want to pass declared variables to where.
For example I have a table #test:
ID Amount
1 100
2 50
3 20
4 40
5 150
I want to do something like that:
declare #id varchar(11) = '(1, 4, 5)'
select * from #test where IDNumber in #id
How can I do that?
Create a table valued user defined function as given below. There are many examples available online.
Convert comma separated list to Table valued function
this will be giving you good results and better approach, than dynamic sql code.
Once you have the function dbo.split(#string NVARCHAR(4000),',') then use them in the JOIN as given below.
declare #id varchar(11) = '1, 4, 5'
select t.* from #test as t
JOIN dbo.Split(#id,',') AS csv
ON t.id = csv.data;
Try the following-:
declare #id varchar(11) = '(1, 4)'
declare #sql nvarchar(max)
set #sql='select * from TABLE_NAME where id in '+ #id
EXEC sp_sqlexec #sql
SQL Server 2014
As stated in the comments you'd be better off using another datatype.
But if you really did want to do it like your example, you could use dynamic sql:
DECLARE #ids VARCHAR(32) = '1,4,5';
DECLARE #result TABLE (ID INT, Amount INT);
DECLARE #sql NVARCHAR(MAX) =
N' SELECT ID, Amount
FROM #test
WHERE ID IN (' + #ids + ');';
PRINT #sql;
INSERT #result
EXEC(#sql);
SELECT*
FROM #result;
The results are placed into a table variable if you need to use them again in your script, if not you can just EXEC the sql

How do I get a collection of every value in every column of a table?

I have two tables, Values and SpecialValues.
Values has two columns, RecordID and ValueName.
SpecialValues is a table which contains a single row, and thirty columns named SpecialValueName1, SpecialValueName2, SpecialValueName3, etc.
There are obvious database design problems with this system.
That aside, can someone explain to me how to query SpecialValues so that I can get a collection of all the values of every row from the table, and exclude them from a Select from Values?
There's probably some easy way to do this or create a View for it or something, but I think looking at this code might have broken me for the moment...
EDIT: I'd like a query to get all the individual values from every row and column of a given table (in this case the SpecialValues table) so that the query does not need to be updated the next time someone adds another column to the SpecialValues table.
This creates a #SpecialValuesColumns temporary table to store all the column names from SpecialValues.
It then uses a cursor to insert all the values from each of those columns into another temporary table #ProtectedValues.
It then uses a NOT IN query to exclude all of those values from a query to Values.
This code is bad and I feel bad for writing it, but it seems like the least-worst option open to me right now.
DECLARE #SpecialColumnsCount INT;
DECLARE #Counter INT;
DECLARE #CurrentColumnName VARCHAR(255);
DECLARE #ExecSQL VARCHAR(1024);
SET #Counter = 1;
CREATE TABLE #ProtectedValues(RecordID INT IDENTITY(1,1) PRIMARY KEY NOT NULL, Value VARCHAR(255));
DECLARE #SpecialValuesColumns TABLE (RecordID INT IDENTITY(1,1) PRIMARY KEY NOT NULL, ColumnName VARCHAR(255));
INSERT INTO #SpecialValuesColumns (ColumnName)
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = 'SpecialValues' AND
DATA_TYPE = 'varchar' AND
CHARACTER_MAXIMUM_LENGTH = 255
SELECT #SpecialColumnsCount = COUNT(*) FROM #SpecialValuesColumns
WHILE #Counter <= #SpecialColumnsCount
BEGIN
SELECT #CurrentColumnName = ColumnName FROM #SpecialValuesColumns WHERE RecordID = #Counter;
SET #ExecSQL = 'INSERT INTO #ProtectedValues (Value) SELECT ' + #CurrentColumnName + ' FROM SpecialValues'
EXEC (#ExecSQL)
SET #Counter = #Counter + 1;
END
SELECT * FROM Values WHERE ValueName NOT IN (SELECT ValueName COLLATE DATABASE_DEFAULT FROM #ProtectedValues)
DROP TABLE #ProtectedValues;
I might have misunderstood but doesn't this do it?
SELECT * FROM Values
WHERE ValueName NOT IN (
SELECT SpecialValueName1 FROM SpecialValues
UNION SELECT SpecialValueName2 FROM SpecialValues
UNION SELECT SpecialValueName3 FROM SpecialValues
etc..
)
You could of course make the subquery into a view instead.
*Edit:
This is quite ugly but should solve your problem:
First Create procedure #1
CREATE PROCEDURE [dbo].[SP1]
As
DECLARE
#Query nvarchar(MAX),
#Table nvarchar(255),
#Columns nvarchar(255)
CREATE TABLE #TempTable (Value nvarchar(255))
SET #Table = 'SpecialValues'
SELECT [COLUMN_NAME]
FROM [INFORMATION_SCHEMA].[COLUMNS]
WHERE [TABLE_NAME] = #Table
DECLARE Table_Cursor CURSOR FOR
SELECT COLUMN_NAME
FROM [INFORMATION_SCHEMA].[COLUMNS]
WHERE [TABLE_NAME] = #Table
OPEN Table_Cursor
FETCH NEXT FROM Table_Cursor INTO #Columns
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO #TempTable EXEC SP2 #Columns = #Columns, #Table = #Table
FETCH NEXT FROM Table_Cursor INTO #Columns
END
CLOSE Table_Cursor
DEALLOCATE Table_Cursor
SELECT ValueName FROM Value WHERE Value NOT IN (SELECT * FROM #TempTable)
TRUNCATE TABLE #TempTable
DROP TABLE #TempTable
Then Create procedure #2
CREATE PROCEDURE [dbo].[SP2]
#Columns nvarchar(255) = '',
#Table nvarchar(255)
AS
DECLARE
#Query nvarchar(MAX)
SET #Query = 'SELECT TOP 1 CONVERT(nvarchar, ' + #Columns + ') FROM ' + #Table
EXEC (#Query)
Then lastly execute the procedure
EXEC SP1
You need to unpivot the values in specialvalues. A pretty easy way to do that is with cross apply syntax:
select sv.value
from specialvalues sv cross apply
(values(sv.SpecialValueName1), (sv.SpecialValueName2), . . .
) sv(value)
where sv.value is not null;
You can exclude these from the list using not in, not exists or a left join.
What ever way you cut it, you have to specify the columns in SpecialValues, you can do this with a long set of UNION queries, or use UNPIVOT:
select SpecialValue
from (select SpecialValueName1,SpecialValueName2,SpecialValueName3 from #SpecialValues) p
unpivot (SpecialValue FOR ROW IN (SpecialValueName1,SpecialValueName2,SpecialValueName3))
AS unpvt
You can then incorporate this into a query on Values using NOT IN
select * from [Values] where ValueName not in (
select SpecialValue
from (select SpecialValueName1,SpecialValueName2,SpecialValueName3 from #SpecialValues) p
unpivot (SpecialValue FOR ROW IN (SpecialValueName1,SpecialValueName2,SpecialValueName3))
AS unpvt
)

How to iterate through each row in sql server?

My query returns 26 table names.
select name from sys.tables where name like '%JPro_VP_Service%'
Now I'm trying to write a query to check in every table return from the above query.
--consider this is my first table
select * from JPro_VP_Service
where row_id like '%1-101%' or row_id like '%1-102%'
-- likewise I want to search in 26 tables return from above query
I think I need to write for or cursor to accomplish this.
Can anyone help me how to achieve this?
The easiest way to do this is
Try this:
SELECT 'select * from ' + name
+ ' where row_id like ''%1-101%'' or row_id like ''%1-102%'''
FROM sys.tables
WHERE name LIKE '%JPro_VP_Service%'
you will get all tables together with the same conditions. You could execute them together.
Yes, you would have to use a cursor for this, and probably also dynamic sql
Also see
Generate dynamic SQL statements in SQL Server
Dynamic SQL PROs & CONs
DECLARE #mn INT
DECLARE #mx INT
DECLARE #tblname VARCHAR(100);
WITH cte
AS (SELECT Row_number()
OVER (
ORDER BY (SELECT 0)) AS rn,
name
FROM sys.tables
WHERE name LIKE '%JPro_VP_Service%')
SELECT #mn = Min(rn),
#mx = Max(rn)
FROM cte
WHILE( #mn >= #mx )
BEGIN
SELECT #tblname = name
FROM cte
WHERE rn = #mn
SELECT *
FROM #tblname
WHERE row_id LIKE '%1-101%'
OR row_id LIKE '%1-102%'
--Do something else
SET #mn=#mn + 1
END
This route may work, though you might want the results saved to a table:
DECLARE #tables TABLE(
ID INT IDENTITY(1,1),
Name VARCHAR(100)
)
INSERT INTO #tables (Name)
SELECT name
FROM sys.tables
WHERE name like '%JPro_VP_Service%'
DECLARE #b INT = 1, #m INT, #table VARCHAR(100), #cmd NVARCHAR(MAX)
SELECT #m = MAX(ID) FROM #tables
WHILE #b <= #m
BEGIN
SELECT #table = Name FROM #tables WHERE ID = #b
SET #cmd = 'select * from ' + #table + '
where row_id like ''%1-101%'' or row_id like ''%1-102%''
'
EXECUTE sp_executesql #cmd
SET #b = #b + 1
SET #cmd = ''
END

String concatenation in SQL server

Consider a situation we have two variables in SQL Server 2005's SP as below,
#string1 = 'a,b,c,d'
#string2 = 'c,d,e,f,g'
Is there a solution to get a new string out of that like (#string1 U #string2) without using any loops. i.e the final string should be like,
#string3 = 'a,b,c,d,e,f,g'
In case you need to do this as a set and not one row at a time. Given the following split function:
USE tempdb;
GO
CREATE FUNCTION dbo.SplitStrings(#List nvarchar(max))
RETURNS TABLE
AS
RETURN ( SELECT Item FROM
( SELECT Item = x.i.value(N'./text()[1]', N'nvarchar(max)')
FROM ( SELECT [XML] = CONVERT(xml, '<i>'
+ REPLACE(#List,',', '</i><i>') + '</i>').query('.')
) AS a CROSS APPLY [XML].nodes('i') AS x(i) ) AS y
WHERE Item IS NOT NULL
);
GO
Then with the following table and sample data, and string variable, you can get all of the results this way:
DECLARE #foo TABLE(ID INT IDENTITY(1,1), col NVARCHAR(MAX));
INSERT #foo(col) SELECT N'c,d,e,f,g';
INSERT #foo(col) SELECT N'c,e,b';
INSERT #foo(col) SELECT N'd,e,f,x,a,e';
DECLARE #string NVARCHAR(MAX) = N'a,b,c,d';
;WITH x AS
(
SELECT f.ID, c.Item FROM #foo AS f
CROSS APPLY dbo.SplitStrings(f.col) AS c
), y AS
(
SELECT ID, Item FROM x
UNION
SELECT x.ID, s.Item
FROM dbo.SplitStrings(#string) AS s
CROSS JOIN x
)
SELECT ID, Items = STUFF((SELECT ',' + Item
FROM y AS y2 WHERE y2.ID = y.ID
FOR XML PATH(''), TYPE).value(N'./text()[1]', N'nvarchar(max)'), 1, 1, N'')
FROM y
GROUP BY ID;
Results:
ID Items
-- ----------
1 a,b,c,d,e,f,g
2 a,b,c,d,e
3 a,b,c,d,e,f,x
On newer versions (SQL Server 2017+), the query is much simpler, and you don't need to create your own custom string-splitting function:
;WITH x AS
(
SELECT f.ID, c.value FROM #foo AS f
CROSS APPLY STRING_SPLIT
(
CONCAT(f.col, N',', #string), N','
) AS c GROUP BY f.ID, c.value
)
SELECT ID, STRING_AGG(value, N',')
WITHIN GROUP (ORDER BY value)
FROM x GROUP BY ID;
Example db<>fiddle
Now that all said, what you really should do is follow the previous advice and store these things in a related table in the first place. You can use the same type of splitting methodology to store the strings separately whenever an insert or update happens, instead of just dumping the CSV into a single column, and your applications shouldn't really have to change the way they're passing data into your procedures. But it sure will be easier to get the data out!
EDIT
Adding a potential solution for SQL Server 2008 that is a bit more convoluted but gets things done with one less loop (using a massive table scan and replace instead). I don't think this is any better than the solution above, and it is certainly less maintainable, but it is an option to test out should you find you are able to upgrade to 2008 or better (and also for any 2008+ users who come across this question).
SET NOCOUNT ON;
-- let's pretend this is our static table:
CREATE TABLE #x
(
ID int IDENTITY(1,1),
col nvarchar(max)
);
INSERT #x(col) VALUES(N'c,d,e,f,g'), (N'c,e,b'), (N'd,e,f,x,a,e');
-- and here is our parameter:
DECLARE #string nvarchar(max) = N'a,b,c,d';
The code:
DECLARE #sql nvarchar(max) = N'DECLARE #src TABLE(ID INT, col NVARCHAR(32));
DECLARE #dest TABLE(ID int, col nvarchar(32));';
SELECT #sql += '
INSERT #src VALUES(' + RTRIM(ID) + ','''
+ REPLACE(col, ',', '''),(' + RTRIM(ID) + ',''') + ''');'
FROM #x;
SELECT #sql += '
INSERT #dest VALUES(' + RTRIM(ID) + ','''
+ REPLACE(#string, ',', '''),(' + RTRIM(ID) + ',''') + ''');'
FROM #x;
SELECT #sql += '
WITH x AS (SELECT ID, col FROM #src UNION SELECT ID, col FROM #dest)
SELECT DISTINCT ID, Items = STUFF((SELECT '','' + col
FROM x AS x2 WHERE x2.ID = x.ID FOR XML PATH('''')), 1, 1, N'''')
FROM x;'
EXEC sys.sp_executesql #sql;
GO
DROP TABLE #x;
This is much trickier to do in 2005 (though not impossible) because you need to change the VALUES() clauses to UNION ALL...
Two ways you can do that:
Build a CLR function to do the job for you. Move the logic back to .NET code which is much easier platform for string manipulation.
If you have to use SQL Server, then you will need to:
"explode" the two strings into two tables, this function might help: http://blog.logiclabz.com/sql-server/split-function-in-sql-server-to-break-comma-separated-strings-into-table.aspx
Get a unique list of strings from the two tables. (simple query)
"implode" the two string tables into a variable (http://stackoverflow.com/questions/194852/concatenate-many-rows-into-a-single-text-string)
Found this function dbo.Split in a related answer, which you can use like this:
declare #string1 nvarchar(50) = 'a,b,c,d'
declare #string2 nvarchar(50) = 'c,d,e,f,g'
select * from dbo.split(#string1, ',')
select * from dbo.split(#string2, ',')
declare #data nvarchar(100) = ''
select #data = #data + ',' + Data from (
select Data from dbo.split(#string1, ',')
union
select Data from dbo.split(#string2, ',')
) as d
select substring(#data, 2, LEN(#data))
The last SELECT returns
a,b,c,d,e,f,g
How about
set #string3 = #string1+','+#string2
Sorry, wasn't clear you wanted only unique occurrences. What version of SQL server are you using? String manipulation functions vary per version.
If you don't mind a UDF to split the string, try this:
CREATE FUNCTION dbo.Split
(
#RowData nvarchar(2000),
#SplitOn nvarchar(5)
)
RETURNS #RtnValue table
(
Id int identity(1,1),
Data nvarchar(100)
)
AS
BEGIN
Declare #Cnt int
declare #data varchar(100)
Set #Cnt = 1
While (Charindex(#SplitOn,#RowData)>0)
Begin
Insert Into #RtnValue (data)
Select 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 the code to use the UDF
go
#string1 = 'a,b,c,d'
#string2 = 'c,d,e,f,g'
declare #string3 varchar(200)
set #string3 = ''
select #string3 = #string3+data+','
from ( select data,min(id) as Id from dbo.split(#string1+','+#string2,',')
group by data ) xx
order by xx.id
print left(#string3,len(#string3)-1)
The following SQL function will convert a comma separated list to a table variable...
CREATE FUNCTION [dbo].[udfCsvToTable]( #CsvString VARCHAR( 8000))
-- Converts a comman separated value into a table variable
RETURNS #tbl TABLE( [Value] VARCHAR( 100) COLLATE DATABASE_DEFAULT NOT NULL)
AS BEGIN
DECLARE #Text VARCHAR( 100)
SET #CsvString = RTRIM( LTRIM( #CsvString))
SET #CsvString = REPLACE( #CsvString, CHAR( 9), '')
SET #CsvString = REPLACE( #CsvString, CHAR( 10), '')
SET #CsvString = REPLACE( #CsvString, CHAR( 13), '')
IF LEN( #CsvString) < 1 RETURN
WHILE LEN( #CsvString) > 0 BEGIN
IF CHARINDEX( ',', #CsvString) > 0 BEGIN
SET #Text = LEFT( #CsvString, CHARINDEX( ',', #CsvString) - 1)
SET #CsvString = LTRIM( RTRIM( RIGHT( #CsvString, LEN( #CsvString) - CHARINDEX( ',', #CsvString))))
END
ELSE BEGIN
SET #Text = #CsvString
SET #CsvString = ''
END
INSERT #tbl VALUES( LTRIM( RTRIM( #Text)))
END
RETURN
END
You can then union the two tables together, like so...
SELECT * FROM udfCsvToTable('a,b,c,d')
UNION
SELECT * FROM udfCsvToTable('c,d,e,f,g')
Which will give you a result set of:
a
b
c
d
e
f
g

How to use table variable in a dynamic sql statement?

In my stored procedure I declared two table variables on top of my procedure. Now I am trying to use that table variable within a dynamic sql statement but I get this error at the time of execution of that procedure. I am using Sql Server 2008.
This is how my query looks like,
set #col_name = 'Assoc_Item_'
+ Convert(nvarchar(2), #curr_row1);
set #sqlstat = 'update #RelPro set '
+ #col_name
+ ' = (Select relsku From #TSku Where tid = '
+ Convert(nvarchar(2), #curr_row1) + ') Where RowID = '
+ Convert(nvarchar(2), #curr_row);
Exec(#sqlstat);
And I get the following errors,
Must declare the table variable "#RelPro".
Must declare the table variable "#TSku".
I have tried to take the table outside of the string block of dynamic query but to no avail.
On SQL Server 2008+ it is possible to use Table Valued Parameters to pass in a table variable to a dynamic SQL statement as long as you don't need to update the values in the table itself.
So from the code you posted you could use this approach for #TSku but not for #RelPro
Example syntax below.
CREATE TYPE MyTable AS TABLE
(
Foo int,
Bar int
);
GO
DECLARE #T AS MyTable;
INSERT INTO #T VALUES (1,2), (2,3)
SELECT *,
sys.fn_PhysLocFormatter(%%physloc%%) AS [physloc]
FROM #T
EXEC sp_executesql
N'SELECT *,
sys.fn_PhysLocFormatter(%%physloc%%) AS [physloc]
FROM #T',
N'#T MyTable READONLY',
#T=#T
The physloc column is included just to demonstrate that the table variable referenced in the child scope is definitely the same one as the outer scope rather than a copy.
Your EXEC executes in a different context, therefore it is not aware of any variables that have been declared in your original context. You should be able to use a temp table instead of a table variable as shown in the simple demo below.
create table #t (id int)
declare #value nchar(1)
set #value = N'1'
declare #sql nvarchar(max)
set #sql = N'insert into #t (id) values (' + #value + N')'
exec (#sql)
select * from #t
drop table #t
You don't have to use dynamic SQL
update
R
set
Assoc_Item_1 = CASE WHEN #curr_row = 1 THEN foo.relsku ELSE Assoc_Item_1 END,
Assoc_Item_2 = CASE WHEN #curr_row = 2 THEN foo.relsku ELSE Assoc_Item_2 END,
Assoc_Item_3 = CASE WHEN #curr_row = 3 THEN foo.relsku ELSE Assoc_Item_3 END,
Assoc_Item_4 = CASE WHEN #curr_row = 4 THEN foo.relsku ELSE Assoc_Item_4 END,
Assoc_Item_5 = CASE WHEN #curr_row = 5 THEN foo.relsku ELSE Assoc_Item_5 END,
...
from
(Select relsku From #TSku Where tid = #curr_row1) foo
CROSS JOIN
#RelPro R
Where
R.RowID = #curr_row;
You can't do this because the table variables are out of scope.
You would have to declare the table variable inside the dynamic SQL statement or create temporary tables.
I would suggest you read this excellent article on dynamic SQL.
http://www.sommarskog.se/dynamic_sql.html
Well, I figured out the way and thought to share with the people out there who might run into the same problem.
Let me start with the problem I had been facing,
I had been trying to execute a Dynamic Sql Statement that used two temporary tables I declared at the top of my stored procedure, but because that dynamic sql statment created a new scope, I couldn't use the temporary tables.
Solution:
I simply changed them to Global Temporary Variables and they worked.
Find my stored procedure underneath.
CREATE PROCEDURE RAFCustom_Room_GetRelatedProducts
-- Add the parameters for the stored procedure here
#PRODUCT_SKU nvarchar(15) = Null
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
IF OBJECT_ID('tempdb..##RelPro', 'U') IS NOT NULL
BEGIN
DROP TABLE ##RelPro
END
Create Table ##RelPro
(
RowID int identity(1,1),
ID int,
Item_Name nvarchar(max),
SKU nvarchar(max),
Vendor nvarchar(max),
Product_Img_180 nvarchar(max),
rpGroup int,
Assoc_Item_1 nvarchar(max),
Assoc_Item_2 nvarchar(max),
Assoc_Item_3 nvarchar(max),
Assoc_Item_4 nvarchar(max),
Assoc_Item_5 nvarchar(max),
Assoc_Item_6 nvarchar(max),
Assoc_Item_7 nvarchar(max),
Assoc_Item_8 nvarchar(max),
Assoc_Item_9 nvarchar(max),
Assoc_Item_10 nvarchar(max)
);
Begin
Insert ##RelPro(ID, Item_Name, SKU, Vendor, Product_Img_180, rpGroup)
Select distinct zp.ProductID, zp.Name, zp.SKU,
(Select m.Name From ZNodeManufacturer m(nolock) Where m.ManufacturerID = zp.ManufacturerID),
'http://s0001.server.com/is/sw11/DG/' +
(Select m.Custom1 From ZNodeManufacturer m(nolock) Where m.ManufacturerID = zp.ManufacturerID) +
'_' + zp.SKU + '_3?$SC_3243$', ep.RoomID
From Product zp(nolock) Inner Join RF_ExtendedProduct ep(nolock) On ep.ProductID = zp.ProductID
Where zp.ActiveInd = 1 And SUBSTRING(zp.SKU, 1, 2) <> 'GC' AND zp.Name <> 'PLATINUM' AND zp.SKU = (Case When #PRODUCT_SKU Is Not Null Then #PRODUCT_SKU Else zp.SKU End)
End
declare #curr_row int = 0,
#tot_rows int= 0,
#sku nvarchar(15) = null;
IF OBJECT_ID('tempdb..##TSku', 'U') IS NOT NULL
BEGIN
DROP TABLE ##TSku
END
Create Table ##TSku (tid int identity(1,1), relsku nvarchar(15));
Select #curr_row = (Select MIN(RowId) From ##RelPro);
Select #tot_rows = (Select MAX(RowId) From ##RelPro);
while #curr_row <= #tot_rows
Begin
select #sku = SKU from ##RelPro where RowID = #curr_row;
truncate table ##TSku;
Insert ##TSku(relsku)
Select distinct top(10) tzp.SKU From Product tzp(nolock) INNER JOIN
[INTRANET].raf_FocusAssociatedItem assoc(nolock) ON assoc.associatedItemID = tzp.SKU
Where (assoc.isActive=1) And (tzp.ActiveInd = 1) AND (assoc.productID = #sku)
declare #curr_row1 int = (Select Min(tid) From ##TSku),
#tot_rows1 int = (Select Max(tid) From ##TSku);
If(#tot_rows1 <> 0)
Begin
While #curr_row1 <= #tot_rows1
Begin
declare #col_name nvarchar(15) = null,
#sqlstat nvarchar(500) = null;
set #col_name = 'Assoc_Item_' + Convert(nvarchar(2), #curr_row1);
set #sqlstat = 'update ##RelPro set ' + #col_name + ' = (Select relsku From ##TSku Where tid = ' + Convert(nvarchar(2), #curr_row1) + ') Where RowID = ' + Convert(nvarchar(2), #curr_row);
Exec(#sqlstat);
set #curr_row1 = #curr_row1 + 1;
End
End
set #curr_row = #curr_row + 1;
End
Select * From ##RelPro;
END
GO
I don't think that is possible (though refer to the update below); as far as I know a table variable only exists within the scope that declared it. You can, however, use a temp table (use the create table syntax and prefix your table name with the # symbol), and that will be accessible within both the scope that creates it and the scope of your dynamic statement.
UPDATE: Refer to Martin Smith's answer for how to use a table-valued parameter to pass a table variable in to a dynamic SQL statement. Also note the limitation mentioned: table-valued parameters are read-only.
Here is an example of using a dynamic T-SQL query and then extracting the results should you have more than one column of returned values (notice the dynamic table name):
DECLARE
#strSQLMain nvarchar(1000),
#recAPD_number_key char(10),
#Census_sub_code varchar(1),
#recAPD_field_name char(100),
#recAPD_table_name char(100),
#NUMBER_KEY varchar(10),
if object_id('[Permits].[dbo].[myTempAPD_Txt]') is not null
DROP TABLE [Permits].[dbo].[myTempAPD_Txt]
CREATE TABLE [Permits].[dbo].[myTempAPD_Txt]
(
[MyCol1] char(10) NULL,
[MyCol2] char(1) NULL,
)
-- an example of what #strSQLMain is : #strSQLMain = SELECT #recAPD_number_key = [NUMBER_KEY], #Census_sub_code=TEXT_029 FROM APD_TXT0 WHERE Number_Key = '01-7212'
SET #strSQLMain = ('INSERT INTO myTempAPD_Txt SELECT [NUMBER_KEY], '+ rtrim(#recAPD_field_name) +' FROM '+ rtrim(#recAPD_table_name) + ' WHERE Number_Key = '''+ rtrim(#Number_Key) +'''')
EXEC (#strSQLMain)
SELECT #recAPD_number_key = MyCol1, #Census_sub_code = MyCol2 from [Permits].[dbo].[myTempAPD_Txt]
DROP TABLE [Permits].[dbo].[myTempAPD_Txt]
Using Temp table solves the problem but I ran into issues using Exec so I went with the following solution of using sp_executesql:
Create TABLE #tempJoin ( Old_ID int, New_ID int);
declare #table_name varchar(128);
declare #strSQL nvarchar(3072);
set #table_name = 'Object';
--build sql sting to execute
set #strSQL='INSERT INTO '+#table_name+' SELECT '+#columns+' FROM #tempJoin CJ
Inner Join '+#table_name+' sourceTbl On CJ.Old_ID = sourceTbl.Object_ID'
**exec sp_executesql #strSQL;**