How to drop multi temporary table? - sql

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;

Related

SQL Server stored procedure with while condition containing table variable

I have a table where the name of the country changes regularly, like my_table_US_NA, my_table_CAN_NA, my_table_MEX_NA and so on:
create table my_table_US_NA(id int)
insert into my_table_US_NA(id) values (1)
insert into my_table_US_NA(id) values (2)
insert into my_table_US_NA(id) values (3)
insert into my_table_US_NA(id) values (4)
select * from my_table_US_NA
id
----
1
2
3
4
I have a stored procedure like this:
create procedure my_looping_procedure (#Country varchar(10))
as
begin
declare #MyTable varchar(50), #COUNTER int
set #COUNTER = 1
set #MyTable = concat('my_table_', #Country, '_NA')
while (#COUNTER <= (select max(id) from #MyTable))
begin
set #COUNTER = #COUNTER + 1
print #COUNTER
end
end
When I try to compile the procedure, I get this error:
Msg 1087, Level 16, State 1, Procedure my_looping_procedure, Line 15 [Batch Start Line 0]
Must declare the table variable "#MyTable"
I tried moving the while loop into its own little variable:
create procedure my_looping_procedure (#Country varchar(10))
as
begin
declare #MyTable varchar(50),
#sql_loop varchar(max),
#COUNTER int
set #COUNTER = 1
set #MyTable = concat('my_table_', #Country, '_NA')
-- inner variable here
select #sql_loop = '
while (' + #COUNTER + '<= (select max(id) from ' + #MyTable + '))
begin
set ' + #COUNTER + ' = ' + #COUNTER + ' + 1
print ' + #COUNTER + '
end'
exec(#sql_loop)
end
That compiles but returns an error when I try to execute it exec my_looping_procedure:
Msg 245, Level 16, State 1, Procedure my_looping_procedure, Line 16 [Batch Start Line 26]
Conversion failed when converting the varchar value 'WHILE (' to data type int.
I tried declaring and setting all the variables inside #sql_loop:
alter procedure my_looping_procedure (#Country varchar(10))
as
begin
declare #sql_loop varchar(max)
select #sql_loop = '
declare
#MyTable varchar(50),
#COUNTER INT
SET #COUNTER = 1
set #MyTable = concat(''my_table_'', ' + #Country + ', ''_NA'')
WHILE (#COUNTER <= (select max(id) from ' + #MyTable + '))
BEGIN
SET #COUNTER = #COUNTER + 1
print #COUNTER
end'
exec(#sql_loop)
end
This compiles but still errors on execution:
Msg 1087, Level 16, State 1, Line 38
Must declare the table variable "#MyTable".
I then declared the #MyTable variable in the beginning again:
alter procedure my_looping_procedure (#Country varchar(10))
as
begin
declare
#MyTable varchar(50),
#sql_loop varchar(max)
set #MyTable = concat('my_table_', #Country, '_NA')
select #sql_loop = '
declare
#MyTable varchar(50),
#COUNTER INT,
#Country varchar(10),
SET #COUNTER = 1
set #MyTable = concat(''my_table_'', ' + #Country + ', ''_NA'')
WHILE (#COUNTER <= (select max(id) from ' + #MyTable + ' ))
BEGIN
SET #COUNTER = #COUNTER + 1
print #COUNTER
end'
exec(#sql_loop)
end
This actually compiles but complains about the country:
Msg 207, Level 16, State 1, Line 37
Invalid column name 'US'.
Finally, I commented out the initial table set statement:
alter procedure my_looping_procedure (#Country varchar(10))
as
begin
declare
#MyTable varchar(50),
#sql_loop varchar(max)
-- set #MyTable = concat('my_table_', #Country, '_NA')
select #sql_loop = '
declare
#MyTable varchar(50),
#COUNTER INT,
#Country varchar(10),
#MaxCount int
SET #COUNTER = 1
set #MyTable = concat(''my_table_'', ' + #Country + ', ''_NA'')
WHILE (#COUNTER <= (select max(id) from ' + #MyTable + ' ))
BEGIN
SET #COUNTER = #COUNTER + 1
print #COUNTER
end'
exec(#sql_loop)
end
This compiles AND runs, but does nothing.
Can anybody figure out what I'm doing wrong?
Some background:
This is an example of the problem with the parameter and the while loop, not the actual code. As for why it's done this way, the initial design was just for one hard-coded country. When more countries were added, the scripts were copied with new countries hard-coded.
The initial designer is no longer with the company. My current task is just to make a generic piece of code that can be used no matter how many more countries we add. There are hundreds of scripts like this and very little time and few resources on the project.
I genuinely appreciate the suggestions of using a temp table, but the tables are used in other processes. Until we iron out the underlying issues with the process, we are stuck with this design.
Without questioning why you are doing it this way (but those comments are very useful and should be carefully considered). Here is your working code:
create table #my_table_US_NA(id int);
insert into #my_table_US_NA(id) values (1),(2),(3),(4);
declare #MyTable varchar(50), #Country varchar(10);
set #Country = 'US';
set #MyTable = quotename(concat('#my_table_', #Country, '_NA'));
declare #Sql nvarchar(max) = 'declare #COUNTER INT = 1; WHILE (#COUNTER <= (select max(id) from [' + #MyTable + ']))
BEGIN
SET #COUNTER = #COUNTER + 1
print #COUNTER
end';
exec(#Sql);
drop table #my_table_US_NA;
Note 1: I've added quotename as per Larnu's suggestion to avoid the possibility of injection.
Note 2: Your table design doesn't align with how relational databases are intended to be used. You wouldn't normally have a separate table for each country, you would normally have a country column which allows you to segment the table by country. No good design should end up relying on dynamic SQL, sure you might need it for some edge cases but not your main business flow.
I think that you want to gather the data from the country-specific table and then loop through the country-specific data. I would take the approach of using a "temp" table so that you can insert data from a dynamic SQL statement. Here's what I mean:
create procedure my_looping_procedure as
begin
create table #MyTable (id int)
declare #COUNTER int, #Country varchar(3), #MyTable varchar(50), #sql varchar(100)
SET #COUNTER = 1
set #Country = 'US'
set #MyTable = concat('my_table_', #Country, '_NA')
set #sql = 'insert #MyTable (id) select * from ' + #MyTable
exec(#sql)
WHILE (#COUNTER<= (select max(id) from #MyTable))
BEGIN
SET #COUNTER = #COUNTER + 1
print #COUNTER
end
end
go
exec my_looping_procedure
I eventually resolved the issue by declaring the expression inside the while loop as a text string, like so: set #WhileExpr = concat('#COUNTER <= (select max(id) from ', #MyTable) then using it inside the while parenthesis WHILE (' + #WhileExpr + '))
I apologize for wasting your time.

Values not passed to dynamic query in sql server

Is it possible to print the Dynamic select statement after passing the parameters values.When i print the SELECT #SQL.It is giving only select statement without parameter values.In my below procedure the dynamic select statement not giving correct output after passing the parameters.But when i directly passing the the parameter values into the select statement it is giving correct output.In my below procedure splitting function is working fine.Else part in
if statement is not working properly.
CREATE TYPE TableVariable AS TABLE
(
id int identity(1,1),
field_ids INT,
value VARCHAR(MAX)
)
Alter PROCEDURE Testing
(
#TableVar TableVariable READONLY,
#Catalog_id INT
)
AS
Declare #maxPK INT
Declare #pk INT
Declare #fid INT
Declare #is_List SMALLINT
Declare #val VARCHAR(MAX)
Declare #field_Type VARCHAR(50)
Declare #Where VARCHAR(MAX)
Declare #SQL NVARCHAR(MAX);
Set #pk = 1
BEGIN
BEGIN TRY
SET NOCOUNT ON;
Select #maxPK = count(*) From #TableVar
SELECT #Catalog_id
Set #SQL = 'SELECT DISTINCT v1.entity_id from values v1 inner join listings l ON v1.entity_id = l.entity_id WHERE l.c_id=#Catalog_id'
While #pk <= #maxPK
BEGIN
SELECT #fid= field_ids FROM #TableVar where id=#pk;
SELECT #val= value FROM #TableVar where id=#pk;
SELECT #field_Type=type,#is_List=is_list FROM FIELD WHERE ID=#fid
IF (#is_List = 0)
BEGIN
SET #SQL += ' and exists (select 1 from values v'+convert(varchar(15),#pk+1)+' where v1.entity_id = v'+convert(varchar(15),#pk+1)+'.entity_id and v'+convert(varchar(15),#pk+1)+'.field_id=#fid and(value IN(SELECT val FROM spliting(#val,'',''))))'
SELECT #fid
END
else IF (#is_List = 1 OR #field_Type = 'xy')
BEGIN
SET #SQL += ' and exists (select 1 from values v'+convert(varchar(15),#pk+1)+' where v1.entity_id = v'+convert(varchar(15),#pk+1)+'.entity_id and v'+convert(varchar(15),#pk+1)+'.field_id=#fid and(value in(#val)))'
SELECT #fid
END
Select #pk = #pk + 1
END
EXECUTE SP_EXECUTESQL #SQL, N'#Catalog_id int,#fid int,#val varchar(max)',#Catalog_id=#Catalog_id,#fid=#fid,#val=#val
SELECT #SQL
END TRY
BEGIN CATCH
END CATCH
END
DECLARE #DepartmentTVP AS TableVariable;
insert into #DepartmentTVP values(1780,'Smooth As Silk Deep Moisture Shampoo,Smooth As Silk Deeper Moisture Conditioner')
--insert into #DepartmentTVP values(1780,'Smooth As Silk Deeper Moisture Conditioner')
insert into #DepartmentTVP values(1782,'037-05-1129')
insert into #DepartmentTVP values(2320,'["fairtrade","usda_organic","non_gmo_verified"]')
SELECT * FROM #DepartmentTVP
EXEC Testing #DepartmentTVP,583
Yes right before the statment:
EXECUTE SP_EXECUTESQL #SQL, N'#Catalog_id int,#fid int,#val varchar(max)',#Catalog_id=#Catalog_id,#fid=#fid,#val=#val
type:
print #SQL

Dynamic Table Name and Paramers in SQL Stored Procedure

create procedure dbo.move_pos
(
#id int,
#tbl varchar(50)
)
as
begin
declare #pos int
exec('select '+#pos+'=POS from '+#tbl+' where id='+#id)
exec('update '+#tbl+' set POS=POS+1 where POS<'+#pos)
end
In above procedure column POS is of type int. But when I m executing this procedure it is showing following error :
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '='.
I m using SQL SERVER 2012. Need help. Thanks in advance !!!
I would recommend rethinking all this dynamic sql stored procedures.
However, if you really must use dynamic sql, try this instead:
create procedure dbo.move_pos
(
#id int,
#tbl varchar(50)
)
as
begin
declare #sql nvarchar(max);
set #sql = 'update ' + QUOTENAME(#tbl) + '
set POS = POS + 1
where POS < (
select POS
from ' + QUOTENAME(#tbl) + '
where id = '+ cast(#id as nvarchar(10)
)'
exec(#sql)
end

Getting an error when passing the table name as parameter to a function

I am new to SQL query and here I am trying to get the complete name from dbo.Customer_List table and have written this code. However when try to run am getting the following error. I don't know what I am doing wrong.
Error message is:
Msg 1087, Level 16, State 1, Procedure getFullName, Line 11
Must declare the table variable "#tblName".
Msg 1087, Level 16, State 1, Procedure getFullName, Line 14
Must declare the table variable "#tblName".
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near 'Last_Name'.
Code is:
IF OBJECT_ID (N'dbo.getFullName', N'FN') IS NOT NULL
DROP FUNCTION getFullName
GO
Create function dbo.getFullName(#tblName varchar(30),#fstName varchar(50), #lstName varchar(50) ) returns varchar(101)
As
Begin
Declare #rowCount int
Declare #rowIteration int
Declare #temp varchar(101)
Select #rowCount = count(*) from #tblName
Set #rowIteration = 1
While ( #rowIteration <= #rowCount)
Select #temp = #fstName+' '+#lstName from #tblName where #tblName.Customer_Id = #rowIteration
Begin
Set #rowIteration = #rowIteration + 1
End
return #temp
End
Go
Declare #tblName varchar(30),#fstName varchar(50), #lstName varchar(50)
set #tblName = convert(varchar(30),'dbo.Customer_List')
set #fstName = convert(varchar(50),'dbo.Customer_List.First_Name')
set #lstName = convert(varchar(50),'dbo.Customer_List.Last_Name')
Execute ('select dbo.getFullName('+ #tblName+','+ #fstName+','+ #lstName )
You are essentially trying to perform dynamic sql here without performing it properly. You can't just pass in a variable as a table name, that's why you're getting your error.
You need to recreate this as a stored procedure (or at least you will in sql-server which does not like DML transactions in functions) and use the following dynamic sql:
Declare #sql nvarchar(100)
Set #sql = 'Set #int = (Select count(*) from ' + #tblName + ')'
execute sp_executesql #sql, N'#int int output', #int = #rowCount output

Return value from exec(#sql)

I want get the value from Exec(#sql) and assign to #Rowcount(int)
Here is my query:
'SET #RowCount = (select count(*)
FROM dbo.Comm_Services
WHERE CompanyId = '+cast(#CompanyId as char)+' and '+#condition+')'
On the one hand you could use sp_executesql:
exec sp_executesql N'select #rowcount=count(*) from anytable',
N'#rowcount int output', #rowcount output;
On the other hand you could use a temporary table:
declare #result table ([rowcount] int);
insert into #result ([rowcount])
exec (N'select count(*) from anytable');
declare #rowcount int = (select top (1) [rowcount] from #result);
DECLARE #nReturn int = 0
EXEC #nReturn = Stored Procedure
Was playing with this today... I believe you can also use ##ROWCOUNT, like this:
DECLARE #SQL VARCHAR(50)
DECLARE #Rowcount INT
SET #SQL = 'SELECT 1 UNION SELECT 2'
EXEC(#SQL)
SET #Rowcount = ##ROWCOUNT
SELECT #Rowcount
Then replace the SELECT 1 UNION SELECT 2 with your actual select without the count. I'd suggest just putting 1 in your select, like this:
SELECT 1
FROM dbo.Comm_Services
WHERE....
....
(as opposed to putting SELECT *)
Hope that helps.
that's my procedure
CREATE PROC sp_count
#CompanyId sysname,
#codition sysname
AS
SET NOCOUNT ON
CREATE TABLE #ctr
( NumRows int )
DECLARE #intCount int
, #vcSQL varchar(255)
SELECT #vcSQL = ' INSERT #ctr FROM dbo.Comm_Services
WHERE CompanyId = '+#CompanyId+' and '+#condition+')'
EXEC (#vcSQL)
IF ##ERROR = 0
BEGIN
SELECT #intCount = NumRows
FROM #ctr
DROP TABLE #ctr
RETURN #intCount
END
ELSE
BEGIN
DROP TABLE #ctr
RETURN -1
END
GO
If i understand you correctly, (i probably don't)
'SELECT #RowCount = COUNT(*)
FROM dbo.Comm_Services
WHERE CompanyId = ' + CAST(#CompanyId AS CHAR) + '
AND ' + #condition