I'm trying to iterate over some tables and clear all records.
My code is the following :
DECLARE #table varchar(100)
DECLARE db_cursor CURSOR FOR select name from sys.tables where name like '%cfe_%'
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #table
WHILE ##FETCH_STATUS = 0
BEGIN
print #table
delete from #table
FETCH NEXT FROM db_cursor INTO #table
END
CLOSE db_cursor
DEALLOCATE db_cursor
But I receive "Must declare the table variable "#table" at the line "delete..."
I can't see the error.
Thank you
You shoud use dynamic query,
DECLARE #table varchar(100)
,#v_str nvarchar(200)
DECLARE db_cursor CURSOR FOR select name from sys.tables where name like '%cfe_%'
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #table
WHILE ##FETCH_STATUS = 0
BEGIN
print #table
set #v_str = 'delete from '+#table
exec(#v_str)
FETCH NEXT FROM db_cursor INTO #table
END
CLOSE db_cursor
DEALLOCATE db_cursor
You need dynamic delete statement... Try this :
DECLARE #cmd VARCHAR(4000)
DECLARE #table varchar(100)
DECLARE db_cursor CURSOR FOR select name from sys.tables where name like '%cfe_%'
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #table
WHILE ##FETCH_STATUS = 0
BEGIN
SET #cmd = 'DELETE FROM '+#table
EXEC (#cmd)
FETCH NEXT FROM db_cursor INTO #table
END
CLOSE db_cursor
DEALLOCATE db_cursor
Even better would be to not use a cursor here. Looping in sql is a last resort. Also, your query is not going to do exactly what you think it will because you are using like and wanting to find an underscore. The underscore in a LIKE predicate requires it to be escaped with square brackets. As posted your query will return any table with cfe in the name not cfe_.
Once you are comfortable that the dynamic sql string is what you want you can uncomment it to execute it.
declare #SQL nvarchar(max) = ''
select #SQL = #SQL + 'delete from ' + name + ';'
from sys.tables
where name like '%cfe[_]%'
select #SQL
--exec sp_executesql #SQL
We can also use while loop for this process
DECLARE #Min Int,#max Int
IF Object_id('Tempdb..#DeleteList')IS NOT NULL
DROP TABLE #DeleteList
CREATE TABLE #DeleteList (Id Int Identity,Name varchar(100))
INSERT INTO #DeleteList(Name)
SELECT name FROM sys.tables WHERE CHARINDEX('cfe_',name)>0
SELECT #Min=Min(Id) FROm #DeleteList
SELECT #max=MAX(Id) FROm #DeleteList
While(#Min<=#max)
Begin
Declare #TableName Varchar(50),
#Sql Nvarchar(max)
SELECT #TableName=Name From #DeleteList Where id=#Min
SET #Sql='DELETE From '+#TableName
Exec (#Sql)
SET #Min=#Min+1
END
But if the deleting tables have foreign key refrences it will throw error so that first you need delete records from child and then go to Parent table
You will need to do something like;
EXEC sp_executesql #statement = N'DELETE FROM ' + #table
because currently you are trying to delete from a String variable, not the table named the same as the variable
Related
I have the table contents as shown in this picture:
The formula column contains the the column names as variables in the formula expression.
I am trying to get a computed column Score corresponding for each emp_id,Tsk_id and processed date which would be calculated dynamically based on the formulae given in the formula column and push it to a temp table
I have tried to achieve it by dynamic SQL within a cursor using the below code which has been successful. Can Anyone suggest a better way to do it, maybe using a CTE or something ?
DECLARE #EMP_ID nVARCHAR(255)
DECLARE #TSK_ID nVARCHAR(255)
DECLARE #PROCESSEDDATE nVARCHAR(255)
DECLARE #SQLCMD nVARCHAR(max)
DECLARE #SQLTEXT nvarchar(max)
DECLARE db_cursor CURSOR FOR
SELECT EMP_ID,TSK_ID,PROCESSEDDATE from dbo.[Formula_Cal] group by EMP_ID,TSK_ID,PROCESSEDDATE
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #EMP_ID,#TSK_ID,#PROCESSEDDATE
WHILE ##FETCH_STATUS = 0
BEGIN
Set #SQLTEXT = (Select formula from dbo.[Formula_Cal] where EMP_ID=#EMP_ID and TSK_ID =#TSK_ID and PROCESSEDDATE=#PROCESSEDDATE )
Set #SQLCMD ='select emp_id,TSK_ID,convert(decimal(18,2),( ' +#SQLTEXT+ ')) As Score FROM [Formula_Cal] where TSK_ID = '+#TSK_ID+' and EMP_ID = '+#EMP_ID
--Select #SQLTEXT
--Select #SQLCMD
insert into dbo.TMP_ACHSCR(emp_id,TSK_id,Score)
Exec sp_executesql #SQLCMD
FETCH NEXT FROM db_cursor INTO #EMP_ID,#TSK_ID,#PROCESSEDDATE
END
CLOSE db_cursor
DEALLOCATE db_cursor
No this is easiest way (with minimal rewriting). You can access this with rewriting our formulas into function.
I have created a cursor which iterates through all the databases and displays the 1 record per database.
I would like the records to be inserted into 1 table where I can view it. The query may change which is why I don't want to create the table structure for a specific query and insert it. I wanted to use the "select into" clause but that will fail on the second time the cursor runs
DECLARE #DB_Name varchar(100)
DECLARE #Command nvarchar(200)
DECLARE database_cursor CURSOR FOR SELECT name FROM #DBNAME
OPEN database_cursor
FETCH NEXT FROM database_cursor INTO #DB_Name
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #Command = 'use [' + #DB_Name + '] Select '''+ #DB_Name + ''' ,'+
--Enter query below
'* from authentication where username like ''%clair#indicater%'' and password = ''Rohan2410'''
-- print #Command
EXEC sp_executesql #Command
FETCH NEXT FROM database_cursor INTO #DB_Name
END
CLOSE database_cursor
DEALLOCATE database_cursor
You should better use INSERT INTO ... instead of SELECT INTO, something like this:
DECLARE #DB_Name varchar(100)
DECLARE #Command nvarchar(200)
DECLARE database_cursor CURSOR FOR SELECT name FROM #DBNAME
OPEN database_cursor
FETCH NEXT FROM database_cursor INTO #DB_Name
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #Command = 'use [' + #DB_Name + ']
IF OBJECT_ID(''tempdb..##output'') IS NULL
BEGIN
SELECT NULL AS DB_Name,*
INTO ##output
FROM authentication WHERE 1=0
END
INSERT INTO ##output
Select '''+ #DB_Name + ''' ,'+
--Enter query below
'* from authentication where username like ''%clair#indicater%'' and password = ''Rohan2410'''
-- print #Command
EXEC sp_executesql #Command
FETCH NEXT FROM database_cursor INTO #DB_Name
END
CLOSE database_cursor
DEALLOCATE database_cursor
SELECT * FROM ##output
DROP TABLE ##output
Basically, on the first cursor iteration we will create an empty temp table with the correct structure. Then we just insert into that temp table.
I want to find count of set of tables. The table names are values in another table.
--like
select count(*) from tablename
--tablename is obtained from
select tablename from table1
--table1 has around 171 tablenames
I was using cursor to get each table name and select count for each, but it is taking time. Can you please help how to replace cursor code with set based solution?
Below is my cursor code
SET NOCOUNT ON;
if( OBJECT_ID('tempdb..#temptablenew') IS NOT NULL )
BEGIN
DROP table #temptablenew
END
select * into #temptablenew from table1
declare #srccount int
declare #tablename nvarchar(max);
declare #q2 nvarchar(max);
declare #id int;
declare my_cursor cursor
local static read_only forward_only
for
select id,tablename from #temptablenew
open my_cursor
fetch next from my_cursor
into #id,#tablename
while ##fetch_status = 0
begin
set #q2 =N'select #srccount= count(*) from '+#tablename+' with (nolock)';
execute sp_executesql #q2,#PARAMS = N'#srccount INT OUTPUT',
#srccount = #srccount OUTPUT
select #srccount,#id,#tablename
fetch next from my_cursor
into #id,#tablename
end
close my_cursor;
deallocate my_cursor;
Thanks in advance
Try this,
SET NOCOUNT ON;
declare #q2 nvarchar(max) = '';
SELECT #q2 = #q2 + 'SELECT COUNT(*) AS cnt, ''' + tablename + ''' AS TableName FROM ' + tablename + ' (NOLOCK); '
FROM table1
--Print #q2
execute sp_executesql #q2
I have written this procedure,
DECLARE CURS_TABLE CURSOR FOR
SELECT NAME FROM SYS.TABLES WHERE NAME LIKE 'AK_LIB_ADDRESS'
DECLARE #TABLE_NAME VARCHAR(100);
DECLARE #SQL VARCHAR(300);
OPEN CURS_TABLE
FETCH NEXT FROM CURS_TABLE INTO #TABLE_NAME;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #SQL = 'ALTER TABLE '+#TABLE_NAME+' ADD PRIMARY KEY(ID);';
EXEC (#SQL)
FETCH NEXT FROM CURS_TABLE INTO #TABLE_NAME
END
CLOSE CURS_TABLE;
DEALLOCATE CURS_TABLE;
The problem is the exec(#sql) executing the same statement twice, i checked by placing print statement,it's working fine with print statement if i comment exec line...
So please can u give me any idea where i'm doing wrong..?
You should do like this, used a temporary table instead of selecting directly from the sys.tables
SELECT NAME into #temp FROM SYS.TABLES WHERE NAME LIKE 'AK_LIB_ADDRESS%'
DECLARE CURS_TABLE CURSOR FOR
SELECT NAME from #temp
DECLARE #TABLE_NAME VARCHAR(100);
DECLARE #SQL VARCHAR(300);
OPEN CURS_TABLE
FETCH NEXT FROM CURS_TABLE INTO #TABLE_NAME;
WHILE ##FETCH_STATUS = 0
BEGIN
select #TABLE_NAME
SET #SQL = 'ALTER TABLE '+#TABLE_NAME+' ADD PRIMARY KEY(ID);';
EXEC (#SQL)
FETCH NEXT FROM CURS_TABLE INTO #TABLE_NAME
END
CLOSE CURS_TABLE;
DEALLOCATE CURS_TABLE;
Or add a Insensitive keyword to the cursor. The reason is that you are changing a heap to the B-tree inside the trigger, that's the reason you are getting inconsistent behaviour in the cursor.
DECLARE CURS_TABLE CURSOR INSENSITIVE FOR
SELECT NAME FROM SYS.TABLES WHERE NAME LIKE 'AK_LIB_ADDRESS%'
DECLARE #TABLE_NAME VARCHAR(100);
DECLARE #SQL VARCHAR(300);
set #SQL=N' select #minTableId = MIN(id) from ' + #AcDB + '.dbo.vTblOfRollNo '
Declare Cursor For
EXEC SP_EXECUTESQL #SQL
if i have declared all the variables in above query but Declaration of cursor in above
query shows ERROR.
What is Solution?
In order to execute a cursor over dynamic SQL you must put the output of your dynamic sql into a temporary table and then cursor over the temporary table like this:
DECLARE #TableName NVARCHAR(100)
DECLARE #SQL NVARCHAR(1000)
CREATE TABLE #TempTABLE(email NVARCHAR(200))
SET #TableName='Users'
SELECT #SQL='INSERT INTO #TempTable SELECT email FROM ' + #TableName
EXEC (#SQL)
DECLARE MyCursor CURSOR FOR SELECT * FROM #TempTable
OPEN MyCursor
DECLARE #Email NVARCHAR(200)
FETCH NEXT FROM MyCursor INTO #Email
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT 'Email = ' + #Email
FETCH NEXT FROM MyCursor INTO #Email
END
CLOSE MyCursor
DEALLOCATE MyCursor
DROP TABLE #TempTABLE
I dont think you need a cursor for this
try
DECLARE #AcDB VARCHAR(10),
#Sql NVARCHAR(MAX)
set #SQL=N' select MIN(id) from ' + #AcDB + '.dbo.vTblOfRollNo '
DECLARE #Temp TABLE(
MinID INT
)
INSERT INTO #Temp EXEC SP_EXECUTESQL #SQL
DECLARE #minTableId INT
SELECT TOP 1 #minTableId = MinID FROM #Temp
SELECT #minTableId
EDIT: Also here is the actual CURSOR documentation
DECLARE CURSOR (Transact-SQL)