how to use variable name as table name in update statement - sql-server

I have a table(Lets say'A') that contains the list of all tables in a database.I have defined a cursor that iterate through the tables name in 'A'.I want to update the table column defined in a cursor.
I have created 2 cursors.One to iterate over the tables names and other one to iterate over the column names.
DECLARE #MyCursor CURSOR;
DECLARE #MyField nvarchar(255);
BEGIN
SET #MyCursor = CURSOR FOR
select distinct Table_name from DataTable where Data <>'No'
set #a=0
OPEN #MyCursor
FETCH NEXT FROM #MyCursor
INTO #MyField
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #column_cursor CURSOR;
DECLARE #columnField nvarchar(255);
SET #column_cursor = CURSOR FOR
select Column_name from DataTable where TABLE_NAME=#MyField and Data
<>'No'
OPEN #column_cursor
FETCH NEXT FROM #column_cursor
INTO #columnField
WHILE ##FETCH_STATUS = 0
BEGIN
update #MyField set #columnField=''+#MyField+'_'+#columnField+#a
FETCH NEXT FROM #column_cursor
INTO #columnField
END;
CLOSE #column_cursor ;
DEALLOCATE #column_cursor;
FETCH NEXT FROM #MyCursor
INTO #MyField
END;
CLOSE #MyCursor ;
DEALLOCATE #MyCursor;
END;
Here in the update statement #MyField is giving error :"Must declare the table variable #MyField".

You are on good way but you can't use variable on table name place , you need to build your update command in variable and then execute dynamic sql.
You can see: Creating a dynamic sql query
in your case someting like
declare #sqlCommand varchar(max)
declare #MyField varchar(255) = 'table_name'
declare #columnField varchar(255) = 'column_NAME'
declare #columnValue varchar(255) = 'column_value'
set #sqlCommand = 'update '+ #MyField +' set '+#columnField+' = ' +#columnValue+ ' where 1=1;'
--select #sqlCommand
EXEC (#sqlCommand)

Related

SQL SERVER query cursor with dynamic LinkedServer

I want to monitor few SQL SERVER instances (about 31), and I want to prepare a procedure that will aggregate data from instances based on sys.servers list, but I cant dynamically ask a server.
DECLARE #instance_name sysname;
DECLARE instance_cursor CURSOR FOR
select data_source from sys.servers where is_linked = 1;
OPEN instance_cursor
FETCH NEXT FROM instance_cursor INTO #instance_name
WHILE ##FETCH_STATUS = 0
BEGIN
--Do something on a linked server
SELECT 1 FROM #instance_name.master.sys.master_files
FETCH NEXT FROM instance_cursor INTO #instance_name
END
CLOSE instance_cursor
DEALLOCATE instance_cursor
USE master
GO
IF OBJECT_ID('tempdb..#server_info') IS NOT NULL
DROP TABLE #server_info
CREATE TABLE #server_info
(
Col1 SQL_VARIANT,
Col2 SQL_VARIANT,
Col3 SQL_VARIANT,
Col4 SQL_VARIANT
) -- change data type as needed.
DECLARE #instance_name NVARCHAR(255);
DECLARE #sql NVARCHAR(MAX)
DECLARE instance_cursor CURSOR FOR
SELECT name FROM master.sys.servers WHERE is_linked = 1
ORDER BY name
OPEN instance_cursor
FETCH NEXT FROM instance_cursor INTO #instance_name
WHILE ##FETCH_STATUS = 0
BEGIN
--Do something on a linked server
SET #sql = 'INSERT INTO #server_info (Col1,Col2,Col3,Col4) SELECT .... FROM ' + #instance_name + '.master.sys...'
PRINT #sql -- verify for your syntax
EXEC (#sql)
FETCH NEXT FROM instance_cursor INTO #instance_name
END
CLOSE instance_cursor
DEALLOCATE instance_cursor
SELECT * FROM #server_info
I'm not found a perfect solution for this, but:
CREATE PROCEDURE [kk].[query_ls]
#SQL NVARCHAR(MAX)
AS
BEGIN
DECLARE #query NVARCHAR(MAX);
DECLARE #instance_name sysname;
DECLARE instance_cursor CURSOR FOR
select data_source from sys.servers where is_linked = 1;
OPEN instance_cursor
FETCH NEXT FROM instance_cursor INTO #instance_name
WHILE ##FETCH_STATUS = 0
BEGIN
SET #query = REPLACE(#SQL,'#server#',#instance_name )
EXEC (#query)
FETCH NEXT FROM instance_cursor INTO #instance_name
END
CLOSE instance_cursor
DEALLOCATE instance_cursor
END
And usage example:
EXEC [kk].[query_ls] N'use _dba INSERT INTO kk.cpuUsagePerDB select *,getdate() from [#server#]._dba.kk.[V_cpuUsagePerDB]'
Another solution can be achieved by OPENQUERY

Cursorfetch: The number of variables declared in the INTO list must match that of selected columns in SQL Server 2012

I created a stored procedure that validates certain columns given a table as parameter and decided to use Cursor. But I am getting this cursor fetch error when trying to execute the stored procedure.
I already double checked the columns and it matches the number of variables in INTO list. I tried modifying the stored procedure by writing this
SELECT Lot, ItemId, PO, Status, ErrorDetails
FROM Table1
instead of
SELECT #SQLSTATEMENT
after
SET #MyCursor = CURSOR FOR
and it works fine. But I want the source table to be a parameter so this won't work for me. Any ideas?
CREATE PROCEDURE [dbo].[ValidateData]
#TABLENAME_PARAM NVARCHAR(100)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #MyCursor CURSOR;
DECLARE #CustomerLot NVARCHAR(100),
#DeviceName NVARCHAR(100),
#PO NVARCHAR(100),
#Status NVARCHAR(1),
#ErrorDetails NVARCHAR(250);
DECLARE #TABLENAME NVARCHAR(100);
DECLARE #SQLSTATEMENT AS NVARCHAR(MAX);
SELECT #TABLENAME = Quotename (TABLE_NAME)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = #TABLENAME_PARAM
SET #SQLSTATEMENT = 'Select Lot, ItemId, PO, Status, ErrorDetails FROM ' + #TABLENAME + ' WHERE Status = ''N'''
BEGIN
SET #MyCursor = CURSOR FOR
SELECT #SQLSTATEMENT
OPEN #MyCursor
FETCH NEXT FROM #MyCursor INTO #CustomerLot, #DeviceName, #PO, #Status, #ErrorDetails
WHILE ##FETCH_STATUS = 0
BEGIN
BEGIN TRAN
--some validations here
COMMIT TRAN
FETCH NEXT FROM #MyCursor INTO #CustomerLot, #DeviceName, #PO, #Status, #ErrorDetails
END;
CLOSE #MyCursor;
DEALLOCATE #MyCursor;
END
END
GO
Try this-
CREATE PROCEDURE [dbo].[ValidateData] #TABLENAME_PARAM NVARCHAR(100)
AS
BEGIN
SET NOCOUNT ON;
--DECLARE #MyCursor CURSOR;
DECLARE
#CustomerLot NVARCHAR(100),
#DeviceName NVARCHAR(100),
#PO NVARCHAR(100),
#Status NVARCHAR(1),
#ErrorDetails NVARCHAR(250);
DECLARE #TABLENAME NVARCHAR(100);
DECLARE #SQLSTATEMENT AS NVARCHAR(MAX);
SELECT #TABLENAME = Quotename (TABLE_NAME)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = #TABLENAME_PARAM
SET #SQLSTATEMENT = 'DECLARE MyCursor CURSOR FOR Select Lot, ItemId, PO, Status, ErrorDetails FROM ' + #TABLENAME + ' WHERE Status = ''N'''
EXEC sp_executesql #sqlstatement
OPEN MyCursor
FETCH NEXT FROM MyCursor INTO #CustomerLot, #DeviceName, #PO, #Status, #ErrorDetails
WHILE ##FETCH_STATUS = 0
BEGIN
BEGIN TRAN
--some validations here
COMMIT TRAN
FETCH NEXT FROM MyCursor INTO #CustomerLot, #DeviceName, #PO, #Status, #ErrorDetails
END;
CLOSE MyCursor;
DEALLOCATE MyCursor
END
END
GO

Transact sql : must declare the scalar variable

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

Stored Procedures for inserting,Deleting and Updating evey single table of Information_Schema

I want to write a script to make stored procedures for insert , delete and update every single table of Information _ Schema , I came up with this code but I have problems in procedures input parameters and the way to insert , delete and update them, can anyone help me please?
DECLARE AutoProc CURSOR GLOBAL
FOR
SELECT TABLE_SCHEMA,TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE='BASE TABLE'
OPEN AutoProc
DECLARE #Schema NVARCHAR(100)
DECLARE #Table NVARCHAR(100)
DECLARE #TotalField NVARCHAR(600)=''
DECLARE #Parameters NVARCHAR(600)
FETCH NEXT
FROM AutoProc
INTO #Schema,#Table
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE AutoFields CURSOR GLOBAL
FOR
SELECT COLUMN_NAME,DATA_TYPE,CHARACTER_MAXIMUM_LENGTH
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA=#Schema AND
TABLE_NAME=#Table AND
TABLE_NAME
IN
(
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE= 'BASE TABLE'
)
OPEN AutoFields
DECLARE #FieldName NVARCHAR(100)
DECLARE #DataType NVARCHAR(50)
DECLARE #Size NVARCHAR(10)
FETCH NEXT
FROM AutoFields
INTO #FieldName,#DataType,#Size
WHILE ##FETCH_STATUS = 0
BEGIN
IF #DataType='NVARCHAR' OR #DataType='nvarchar'
BEGIN
SET #TotalField=#TotalField+'#'+#FieldName+' '+#DataType+'('+#Size+'),'
END
ELSE
BEGIN
SET #TotalField=#TotalField+'#'+#FieldName+' '+#DataType+','
END
FETCH NEXT
FROM AutoFields
INTO #FieldName,#DataType,#Size
END
CLOSE AutoFields
DEALLOCATE AutoFields
SET #Parameters =SUBSTRING(#TotalField,1,LEN(#TotalField)-1)
EXECUTE('
CREATE PROC USP_INS_'+#Schema+'_'+#Table+'
#parameters NVARCHAR(600)='+#Parameters+'
AS
BEGIN
INSERT '+#Schema+'.'+#Table+'
VALUES(#parameters)
END')
EXECUTE('
CREATE PROC USP_UPD_'+#Schema+'_'+#Table+'
#parameters NVARCHAR(600)='+#Parameters+'
AS
BEGIN
UPDATE '+#Schema+'.'+#Table+'
SET
END')
EXECUTE('
CREATE PROC USP_DEL_'+#Schema+'_'+#Table+'
parameters NVARCHAR(600)='+#Parameters+'
AS
BEGIN
DELETE '+#Schema+'.'+#Table+'
WHERE
END')
SET #TotalField=''
FETCH NEXT
FROM AutoProc
INTO #Schema,#Table
END
CLOSE AutoProc
DEALLOCATE AutoProc

Execute procedure executing same statement twice

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);

Resources