SQL - using SET with a variable table value - sql

This is my code:
DECLARE #LoopCounter INT = 1,#max INT,#table nvarchar(100),#academic nvarchar(100)
SELECT #max = max(id)
FROM #tablelist
WHILE(#LoopCounter <= #max)
BEGIN
SET #table = (SELECT TABLE_NAME
FROM #tablelist WHERE id = #LoopCounter)
SET #academic = (SELECT F6
FROM #table WHERE F5 = Academic)
SET #LoopCounter = #LoopCounter + 1
END
where #tablelist is a list of all my tables in the database that are relevent.
The step:
SET #academic = (SELECT F6
FROM #table WHERE F5 = Academic)
does not work... I've tried with sp_execute but I get thrown back standard errors, at the moment the error is 'Must declare the standard variable '#table'. I have also tried an EXEC but it doesn't like that either.
What I want to do is define #academic to be a value from the #table The problem I'm having is the SET does not like being from #table.
Any help would be fab!

I think you want dynamic SQL:
DECLARE #LoopCounter INT = 1,
#max INT,#table nvarchar(100),
#academic nvarchar(100);
DECLARE #SQL NVARCHAR(MAX);;
SELECT #max = max(id)
FROM #tablelist;
WHILE(#LoopCounter <= #max)
BEGIN
SET #table = (SELECT TABLE_NAME FROM #tablelist WHERE id = #LoopCounter) ;
SET #SQL = '
SELECT #academic = F6
FROM [table]
WHERE f5 = 'Academic'
';
SET #SQL = REPLACE(#SQL, '[Table]', #table_name);
EXEC sp_executesql #SQL,
N'#academic NVARCHAR(100)',
#academic=#academic;
SET #LoopCounter = #LoopCounter + 1
END;
All that said, this is not an example of good coding (even ignoring the fact that I'm not escaping the table name).
You should not have multiple tables with the same columns, distinguished only by a variant of the name. Instead, you should have a single table with all the rows, and perhaps an additional column or two for identifying the columns.
Having to use dynamic SQL can illustrate a problem with the data model. And in this case, I think that it does.

Related

How to drop multi temporary table?

How to drop multiple temporary table from SQL Server
Below code give this error :
msg 156, Level 15, State 1, Line 5
Incorrect syntax near the keyword 'drop'.
declare #deptno int = 1
while #deptno > (Select COUNT(*) from tbl_deptseat)+1
Begin
Declare #deptnamevar nvarchar(20) = '##dept'+ cast(#deptno as nvarchar(10))
exec (drop table (#deptnamevar))
End
declare #deptno int = 1
while #deptno < (Select COUNT(*) from tbl_deptseat)+1
Begin
Declare #deptnamevar nvarchar(20) = '##dept'+ cast(#deptno as nvarchar(10))
Declare #dropquery nvarchar(20) = 'drop table '+ #deptnamevar
exec (#dropquery)
set #deptno = #deptno + 1
End
This seems like a very strange way of approaching data processing. I wouldn't recommend putting such logic in table names. Instead, the logic belongs in columns.
But, you want to use dynamic SQL:
declare #deptno int = 1;
declare #sql nvarchar(max);
while #deptno < (Select COUNT(*) from tbl_deptseat)+1
Begin
Declare #deptnamevar nvarchar(20) = '##dept'+ cast(#deptno as nvarchar(10));
set #sql = 'drop table ' + #deptnamevar;
exec(#sql) ;
set #deptno = #deptno + 1;
End;

SQL Server INSERT in Loop

I have this SQL Script:
DECLARE #Loop INT
SET #Loop = 1
DECLARE #Result table([1] int, [2] int,[3] int,[4] int,[5]);
WHILE (#Loop <=5)
BEGIN
INSERT INTO #Result(#Loop)
SELECT Id FROM Students WHERE Id=#Loop
SET #Loop= #Loop+ 1
END
I got an error in this line:
INSERT INTO #Result(#Loop)
Is it possible to use this way to insert data into column names using loop ? I mean dynamicaly
Thanks
This is as close as I can get to what you have.
I'm using dynamic sql to build the insert sql.
I'm using a temporary table #Result instead of a variable #Result because the scope of the #Result variable would mean that this technique would not work.
DECLARE #Loop INT;
SET #Loop = 1;
CREATE TABLE #Result([1] int, [2] int, [3] int, [4] int, [5] int);
DECLARE #Sql AS NVARCHAR(MAX);
DECLARE #LoopNVARCHAR AS NVARCHAR(10);
WHILE (#Loop <= 5)
BEGIN
SET #LoopNVARCHAR = CAST(#Loop AS NVARCHAR(10));
SET #Sql = N'INSERT INTO #Result([' + #LoopNVARCHAR + ']) SELECT Id FROM Students WHERE Id = ' + #LoopNVARCHAR;
exec (#Sql)
SET #Loop = #Loop + 1
END
SELECT * FROM #Result
DROP TABLE #Result

Get column names in SQL server that satisfy a where condition on data

I just had a random doubt while working with SQL-server to which i thought i could get it clarified here.
Say- i have a condition that i want to find out all the column names in the database which satisfy my where condition on data.
Example:-
There are some 20-30 tables in a SQL-Server DB.Now all i need is a query to find out the list of column names which have "Ritesh" as a data field in them.
I don't know if it is really possible in the first place.
I hope i am clear. Please, any help will be most appreciated.
Thank You.
Ritesh.
This should work, but be aware, this will take a while to execute in large databases. I have assumed that the search string might be just a part of the data contained and am using wildcards. I feel this is purely academic, as I am unable to imagine a scenario, where this will be required.
--you need to iterate the whole columns of entire table to find the matched record
--another thing is that you need dynamic sql to find the table name
DECLARE #Value varchar(50) --value for that find the column Name
SET #Value = 'Ritesh'
CREATE TABLE #Table
(
TableName Varchar(500),ColumnName Varchar(500),
Id int Identity(1,1) --use for iteration
)
CREATE TABLE #Results
(
TableName varchar(500),
ColumnName varchar(500)
)
INSERT INTO #Table
SELECT
TABLE_SCHEMA + '.' + TABLE_NAME AS TableNam,
Column_name AS ColumnName
FROM INFORMATION_SCHEMA.COLUMNS
WHERE Data_type IN ('char', 'nchar', 'varchar', 'nvarchar')
--change the datatype based on the datatype of sample data you provide
-- also remember to change the wildcard, if the input datatype is not a string
DECLARE #Count Int --total record to iterated
SET #Count = 0;
SELECT
#Count = COUNT(*)
FROM #Table
DECLARE #I int --initial value one to iterate
SET #I = 1;
DECLARE #TableName varchar(500)
SET #TableName = ''
DECLARE #ColumnName varchar(500)
SET #ColumnName = ''
DECLARE #Str nvarchar(1000)
SET #Str = ''
DECLARE #param nvarchar(1000)
SET #param = ''
DECLARE #TableNameFound varchar(max)
SET #TableNameFound = ''
DECLARE #Found bit
SET #Found = 0;
WHILE #I<=#Count
BEGIN
SET #Found = 0;
SELECT
#TableName = TableName,
#ColumnName = ColumnName
FROM #Table
WHERE Id = #I;
SET #param = '#TableName varchar(500),#ColumnName varchar(500),#Value varchar(50),#TableNameFound varchar(max),#Found bit output'
SET #str = 'Select #Found=1 From ' + #TableName + ' where ' + #ColumnName + ' Like ' + '''' + '%' + #Value + '%' + ''''
-- here we are using tablename and actual value to find in table
EXEC sp_executesql #str,
#param,
#TableName,
#ColumnName,
#Value,
#TableNameFound,
#Found OUTPUT
IF #Found=1
BEGIN
INSERT INTO #Results (TableName, ColumnName)
SELECT
#TableName,
#ColumnName
END
--increment value of #I
SET #I = #I + 1;
END
--Display Results
SELECT * FROM #Results
--Clean Up
DROP TABLE #Table
DROP TABLE #Results

How to store a dynamic SQL result in a variable in T-SQL?

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!

Loops within dynamic SQL

I have code that I'd like to apply to a number of tables but rather than simply copy and replace table names, I'd like to use some kind of loop or cursor to simplify things.
I envision setting up an array of my tables names and using an index to iterate over the list, retrieving each table name and using dynamic SQL to intersperse the table name where applicable in my code.
Since there's no 'array' construct, as far as I know, within SQL, I'm not sure how this would work.
Any ideas about how to go about this?
Here is one way of doing it:
--Declare a table variable to hold your table names (and column names in case needed)
declare #listOfTablesToUpdate table (tableName varchar(100), columnNameToUpdate varchar(50))
--insert the tables that you want to work with.
insert into #listOfTablesToUpdate values ('Table1', 'column2')
insert into #listOfTablesToUpdate values ('Table2', 'column3')
insert into #listOfTablesToUpdate values ('Table3', 'column4')
--Cursor for iterating
declare #tableCursor cursor,
#tableName varchar(100),
#columnName varchar(50)
set #tableCursor = cursor for select * from #listOfTablesToUpdate
open #tableCursor
fetch next from #tableCursor into #tableName, #columnName
while(##fetch_status = 0)
begin
--dynamic sql
declare #sql varchar(max)
--Your logic here...this is just an example
set #sql = 'update '+#tableName+' set '+#columnName+' = '+<value>+' where '+#columnName +' = '+<someothervalue>
exec #sql
fetch next from #tableCursor into #tableName, #columnName
end
close #tableCursor
deallocate #tableCursor
Another approach involves preparing a helper function and a procedure that allow one to apply different SQL statements to each object (table, database, et cetera) in a list. The helper function comes from a SSRS Parameter question and splits apart a comma delimited list into a table.
-- from https://stackoverflow.com/questions/512105/passing-multiple-values-for-a-single-parameter-in-reporting-services
CREATE FUNCTION [dbo].[fn_MVParam]
(#RepParam NVARCHAR(4000), #Delim CHAR(1)= ',')
RETURNS #Values TABLE (Param NVARCHAR(4000))AS
BEGIN
DECLARE #chrind INT
DECLARE #Piece NVARCHAR(100)
SELECT #chrind = 1
WHILE #chrind > 0
BEGIN
SELECT #chrind = CHARINDEX(#Delim,#RepParam)
IF #chrind > 0
SELECT #Piece = LEFT(#RepParam,#chrind - 1)
ELSE
SELECT #Piece = #RepParam
INSERT #Values(Param) VALUES(CAST(#Piece AS VARCHAR))
SELECT #RepParam = RIGHT(#RepParam,LEN(#RepParam) - #chrind)
IF LEN(#RepParam) = 0 BREAK
END
RETURN
END
GO
Below is the code for the ProcessListSQL procedure.
-- #SQL to execute shall include {RP} as the replacement expression that
-- will evaluate to all the items in the comma delimited list
-- Also, please include a double quote " rather than two single quotes ''
-- in the input statement.
CREATE PROCEDURE [dbo].[ProcessListSQL] (
#CommaDelimitedList AS NVARCHAR(MAX),
#SQLtoExecute AS NVARCHAR(MAX) )
AS BEGIN
DECLARE #Statements TABLE
( PK INT IDENTITY(1,1) PRIMARY KEY,
SQLObject NVARCHAR (MAX)
)
SET #SQLtoExecute = REPLACE (#SQLtoExecute, '"', '''')
INSERT INTO #Statements
SELECT PARAM FROM [dbo].[fn_MVParam](#CommaDelimitedList,',')
DECLARE #i INT
SELECT #i = MIN(PK) FROM #Statements
DECLARE #max INT
SELECT #max = MAX(PK) FROM #Statements
DECLARE #SQL AS NVARCHAR(MAX) = NULL
DECLARE #Object AS NVARCHAR(MAX) = NULL
WHILE #i <= #max
BEGIN
SELECT #Object = SQLObject FROM #Statements WHERE PK = #i
SET #SQL = REPLACE(#SQLtoExecute, '{RP}', #Object)
-- Uncommend below to check the SQL
-- PRINT #SQL
EXECUTE sp_executesql #SQL
SELECT #Object = NULL
SELECT #SQL = NULL
SET #i = #i + 1
END
END
GO
The ProcessListSQL procedure take two parameters. The first is a comma delimited string that contains the list of objects that will be cycled through. The second parameter is a string that contains the SQL that will be executed with each of the objects in the first parameter.
In the below example, four databases are created. Note that {rp} is replaced with each of the objects in the first parameter and double quotes are needed in each place where single quotes are needed in the SQL statement.
EXECUTE ProcessListSQL 'rice,apples,cheese,tomatos',
'CREATE DATABASE [{rp}] CONTAINMENT = NONE
ON PRIMARY ( NAME = N"{rp}",
FILENAME = N"D:\data\user\{rp}.mdf" ,
SIZE = 4096KB ,
FILEGROWTH = 1024KB )
LOG ON
( NAME = N"{rp}_log",
FILENAME = N"D:\DATA\USER\{rp}_log.ldf" ,
SIZE = 1024KB ,
FILEGROWTH = 10%)'