Can I loop create Triggers for all tables? - sql-server

I have such script which in theory allows me to create the same Trigger for each table in DB:
DECLARE #insertTriggers VARCHAR(MAX) = '';
SELECT #insertTriggers = #insertTriggers1 + *Some Trigger creation code ending with 'GO'"
FROM INFORMATION_SCHEMA.TABLES
EXEC(#insertTriggers);
When I use PRINT and copy it to different query it works because I can seperate CREATE TRIGGERS with keyword GO. Here it doesn't work. What can I do? Do I have to make a seperate code for each Trigger?

You can use this as template to create your triggers..
DECLARE #TriggerTemplate NVARCHAR(MAX)
DECLARE #TriggerNameTemplate NVARCHAR(250)
DECLARE #Tables TABLE (ID INT IDENTITY, TableName VARCHAR(100))
INSERT #Tables
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.Tables WHERE TABLE_TYPE = 'BASE TABLE'
DECLARE #ID INT, #TableName VARCHAR(100)
DECLARE #SQL NVARCHAR(MAX), #TriggerName NVARCHAR(250)
WHILE EXISTS (SELECT 1 FROM #Tables)
BEGIN
SELECT TOP 1 #ID = ID, #TableName = TableName FROM #Tables
SET #TriggerName = REPLACE(#TriggerNameTemplate,'#TableName#', QUOTENAME(#TableName))
IF EXISTS(SELECT * FROM sys.triggers WHERE name = #TriggerName)
BEGIN
SET #SQL = 'DROP TRIGGER ' + #TriggerName
EXEC (#SQL)
END
SET #SQL = REPLACE(#TriggerTemplate,'#TableName#', QUOTENAME(#TableName))
EXEC(#SQL)
DELETE #Tables WHERE ID = #ID
END

As per my comment, I developed this SP for audit purposes and it might not work for you originally, but if you alter it, I'm sure it'll assist you.
Otherwise, alter your question of what you need the triggers to do and I will then alter my answer to work for you...
if exists(select 1 from sysobjects where name = 'kv_sp_dbAudits_tr_AW')
drop procedure kv_sp_dbAudits_tr_AW
go
set ansi_nulls on
go
set quoted_identifier on
go
create procedure kv_sp_dbAudits_tr_AW(#tablename varchar(150),#switch bit)
as
BEGIN
if exists(select name from sysobjects where name = 'TempTableTriggers')
drop table TempTableTriggers;
create table TempTableTriggers (tablename varchar(100),columns varchar(max),columnvars varchar(max),columnvarst varchar(max),columnalloc varchar(max))
declare #query varchar(max)
, #loop int
, #dbname varchar(50) = (select db_name())+'_Audit'
, #table varchar(100)
, #tableau varchar(100)
, #trigger varchar(100)
, #column varchar(max)
, #columnvars varchar(max)
, #columnvarst varchar(max)
, #columnalloc varchar(max)
, #crlf char(2) = char(13)+char(10)
declare #Tables table
( id int identity primary key
, TableName varchar(100)
, TriggerName varchar(100)
, Columns varchar(max))
if #tablename like ''+'%'+''
set #tablename = #tablename
else
set #tablename = ''+#tablename+''
set #trigger = #tablename+'_Audit_kvtr_AW'
begin
if #switch = 1
begin
if exists(select name from sysobjects where name = #trigger)
begin
set #tablename = (select name from sysobjects where name = #tablename)
set #query = #crlf
set #query = #query + #crlf
set #query = #query + #crlf
set #query = #query + #crlf
set #query = #query + replicate('-',80)+#crlf
set #query = #query + #crlf
set #query = #query + 'The audit trigger "'+#tablename+'_Audit_kvtr_AW'+'" already exists!'
print (#query)
end
else
begin
if #tablename = 'all'
insert into #Tables
( TableName )
select
name
from sysobjects
where xtype = 'u'
and name not like '%audit%'
and name <> 'TempTableTriggers'
order by name
else
insert into #Tables
( TableName )
select
name
from sysobjects
where xtype = 'u'
and name not like '%audit%'
and name <> 'TempTableTriggers'
and name = #tablename
order by name
select #loop = min(id) from #Tables
while #loop is not null
begin
begin
set #query = ' declare #columns varchar(max)
select #columns = stuff((select '','' + char(10)+quotename(Column_Name)
from information_schema.columns
where table_name = '''+(select TableName from #Tables where id = #loop)+'''
and Column_Name <> ''cAllocs''
and data_type not in (''text'',''image'',''ntext'')
group by column_name, data_type, character_maximum_length, ordinal_position
order by ordinal_position
for xml path(''''), type).value(''.'', ''nvarchar(max)''),1,1,'''')
insert into TempTableTriggers (tablename,columns)
select distinct
table_name
, #columns
from information_schema.columns
where table_name = '''+(select TableName from #Tables where id = #loop)+''''
exec (#query)
end
select #loop = min(id) from #Tables where id>#loop
end
insert into #Tables
(TriggerName,TableName,Columns)
select
TableName,TableName,columns
from TempTableTriggers
select #loop = min(id) from #Tables
while #loop is not null
begin
begin
select #trigger = TriggerName+'_Audit_kvtr_AW'
, #tableau = TableName+'_Audit'
, #table = TableName
, #column = Columns
from #Tables
where id = #loop
set #query = 'create trigger '+#trigger+' on '+#table+#crlf
set #query = #query+ 'with encryption'+#crlf
set #query = #query+ 'after insert, update, delete'+#crlf
set #query = #query+ 'as'+#crlf
set #query = #query+ '/***********************************************************************************************************************************'+#crlf
set #query = #query+ 'Description : To insert any change made in '+#table+' into '+#dbname+'.dbo.'+#table+'_Audit'+#crlf
set #query = #query+ 'Author : Attie Wagner'+#crlf
set #query = #query+ 'Creation Date : 30 October 2018'+#crlf
set #query = #query+ 'Modified By : Attie Wagner'+#crlf
set #query = #query+ 'Modified Date : 28 January 2019'+#crlf
set #query = #query+ '************************************************************************************************************************************/'+#crlf
set #query = #query+ #crlf
set #query = #query+ 'begin'+#crlf
set #query = #query+ #crlf
set #query = #query+ 'set nocount on'+#crlf
set #query = #query+ #crlf
set #query = #query+ 'if (select trigger_nestlevel(object_id('''+#trigger+'''))) > 1'+#crlf
set #query = #query+ 'return'+#crlf
set #query = #query+ #crlf
set #query = #query+ 'declare #inserted varchar(15) = '''''+#crlf
set #query = #query+ 'declare #deleted varchar(15) = '''''+#crlf
set #query = #query+ 'declare #updated varchar(15) = '''''+#crlf
set #query = #query+ 'declare #action varchar(15) = '''''+#crlf
set #query = #query+ 'if((exists(select * from inserted)) and (exists(select * from deleted)))'+#crlf
set #query = #query+ ' set #updated = ''updated'''+#crlf
set #query = #query+ 'else'+#crlf
set #query = #query+ 'if(exists(select * from inserted))'+#crlf
set #query = #query+ ' set #inserted = ''new'''+#crlf
set #query = #query+ 'else'+#crlf
set #query = #query+ 'if(exists(select * from deleted))'+#crlf
set #query = #query+ ' set #deleted = ''deleted'''+#crlf
set #query = #query+ 'set #action = (select case when #inserted = ''new'' then ''new'' when #updated = ''updated'' then ''updated'' when #deleted = ''deleted'' then ''deleted'' else '''' end)'+#crlf
set #query = #query+ #crlf
set #query = #query+ 'declare #kvAgent varchar(100) = (select cAgentName from _rtblAgents where idAgents = [dbo]._efnAgentIDFromConnection(''dbo''))'+#crlf
set #query = #query+ #crlf
set #query = #query+ 'if #action in (''new'',''updated'')'+#crlf
set #query = #query+ #crlf
set #query = #query+ 'begin'+#crlf
set #query = #query+ 'insert into ['+#dbname+'].dbo.'+#tableau+' ('+#column+','+#crlf+'kvUsername,'+#crlf+'kvDTStamp,'+#crlf+'kvAction)'+#crlf
set #query = #query+ #crlf
set #query = #query+ 'select '+#column+','+#crlf+'#kvAgent,'+#crlf+'getdate(),'+#crlf+'#action'+#crlf
set #query = #query+ 'from inserted'+#crlf
set #query = #query+ 'end;'+#crlf
set #query = #query+ #crlf
set #query = #query+ 'if #action = ''deleted'''+#crlf
set #query = #query+ #crlf
set #query = #query+ 'begin'+#crlf
set #query = #query+ 'insert into ['+#dbname+'].dbo.'+#tableau+' ('+#column+','+#crlf+'kvUsername,'+#crlf+'kvDTStamp,'+#crlf+'kvAction)'+#crlf
set #query = #query+ #crlf
set #query = #query+ 'select '+#column+','+#crlf+'#kvAgent,'+#crlf+'getdate(),'+#crlf+'#action'+#crlf
set #query = #query+ 'from deleted'+#crlf
set #query = #query+ 'end;'+#crlf
set #query = #query+ #crlf
set #query = #query+ 'begin'+#crlf
set #query = #query+ 'delete '+quotename(#dbname)+'.dbo.'+#table+'_Audit'+#crlf
set #query = #query+ 'where datediff(month,kvDTStamp,getdate()) > 12'+#crlf
set #query = #query+ 'end;'+#crlf
set #query = #query+ #crlf
set #query = #query+ 'end;'+#crlf
exec (#query)
end
select #loop = min(id) from #Tables where id>#loop
end
end
drop table TempTableTriggers;
end
else
begin
if #tablename = 'all'
insert into #Tables
( TriggerName )
select name from sysobjects
where xtype = 'tr'
and name like '%_Audit_kvtr_AW'
order by name
else
insert into #Tables
( TriggerName )
select name from sysobjects
where xtype = 'tr'
and name like '%_Audit_kvtr_AW'
and name = #tablename+'_Audit_kvtr_AW'
order by name
select #loop = min(id) from #Tables
while #loop is not null
begin
begin
set #trigger = (select TriggerName from #Tables where id = #loop)
set #query = 'if exists(select name from sysobjects where name = '''+#trigger+''')'+#crlf
set #query = #query+'drop trigger '+#trigger
exec (#query)
end
select #loop = min(id) from #Tables where id>#loop
end
end
end
END;

Related

How to create a temptable for this query

I would like to create a temptable that will hold the result of this query:
set #sql = 'use ' + #dbname + '; select db_name() , name from sys.tables where is_ms_shipped = 0 and type_desc = ''USER_TABLE'' '
exec (#sql)
Here is the full query I have:
declare #minx int = 0
declare #maxx int = (select max(id) from #DBS)
declare #sql nvarchar(1000)
declare #dbname varchar (130)
declare #count int
Select *
from #DBS
while (#count is not null
and #count <= #maxx)
begin
select #dbname = dbname
from #DBS where id = #count
print 'id = ' + convert (varchar, #count) + ' dbname = ' + #dbname
set #sql = 'use ' + #dbname + '; select db_name() , name from sys.tables where is_ms_shipped = 0 and type_desc = ''USER_TABLE'' '
exec (#sql)
set #count = #count + 1
break
end;
I have tried so many things and always getting error messages.
Anybody could give me an insight?
Not sure how you populate #DBS but:
CREATE TABLE #tables(db sysname, table_name sysname);
DECLARE #dbs cursor,
#context nvarchar(1000),
#sql nvarchar(max);
SET #sql = N'INSERT #tables(db, table_name)
SELECT DB_NAME(), name
FROM sys.tables
WHERE type = ''U'' AND is_ms_shipped = 0;';
SET #dbs = CURSOR FOR SELECT QUOTENAME(dbname)
+ N'.sys.sp_executesql' FROM #DBS;
OPEN #dbs;
FETCH NEXT FROM #dbs INTO #context;
WHILE ##FETCH_STATUS = 0
BEGIN
EXECUTE #context #sql;
FETCH NEXT FROM #dbs INTO #context;
END
SELECT db, table_name FROM #tables;
Also see this related question.

get value into output variable when executing stored procedure through dynamic query

i am using sql server 2008 r2, I have created a dynamic stored procedure because this is my requirement to implement to filteration of data based on certain conditions. I am not able to get value into #RecordCount
ALTER PROCEDURE [dbo].[sp_getAssetListAudit]
#type nvarchar(20),
#typeid nvarchar(5),
#clientId nvarchar(5),
#PageIndex nvarchar(5),
#PageSize nvarchar(5),
#RecordCount nvarchar(5) output
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQL nvarchar(max)
SET #SQL ='
select ROW_NUMBER() OVER ( ORDER BY ad.arid ASC )
AS rownum, ad.arid,ad.ast_code,ad.ast_descp,isnull(cat.name,'''') ''cat'',ISNULL(loc.name,'''') ''loc'',isnull(gp.name,'''') ''grp'',
isnull(cc.name,'''') ''cc'' ,
ad.ast_qty ''qty'' into #Results
from tbl_AssetDetails ad
left join tbl_Category cat on ad.ast_cat = cat.catid
left join tbl_Subcategory scat on ad.ast_subcat = scat.subcatid
left join tbl_Location loc on loc.lid = ad.ast_loc
left join tbl_Group gp on gp.gid = ad.ast_grp
left join tbl_CostCenter cc on cc.ccid = ad.ast_costcen
where ad.ast_status not in (3,-1) AND ad.clientId = '+#clientId+' AND '
IF(#type='cat')
SET #SQL = #SQL +' ad.ast_cat='+#typeid+' AND '
IF(#type='subcat')
SET #SQL = #SQL +' ad.ast_subcat='+#typeid+' AND '
IF(#type='loc')
SET #SQL = #SQL +' ad.ast_loc='+#typeid+' AND '
IF(#type='grp')
SET #SQL = #SQL +' ad.ast_grp='+#typeid+' AND '
IF(#type='cc')
SET #SQL = #SQL +' ad.ast_costcen='+#typeid+' AND '
IF(#type='ast')
SET #SQL = #SQL +' ad.arid='+#typeid+' AND '
SET #SQL = #SQL +' 1=1 '
SET #SQL =#SQL + ' SELECT '+#RecordCount+' = count(*) FROM #Results '
SET #SQL = #SQL +' SELECT * FROM #Results WHERE rownum
BETWEEN('+#PageIndex+' -1) * '+#PageSize+' + 1 AND((('+#PageIndex+' -1) * '+#PageSize+'+ 1) + '+#PageSize+') - 1 '
SET #SQL = #SQL + ' drop table #Results '
EXEC sp_executesql #SQL, #RecordCount OUTPUT
END
I am not able to get value into #RecordCount and subsequently no result set.
You need to assign the value to the OUTPUT parameter:
SET #SQL =#SQL + ' SELECT #RecordCount = count(*) FROM #Results; '
You also need to pass the parameter definitions to sp_executesql as in #wannuanguo's answer. You should use also use parameters for #typeid, #pageindex, etc. too instead of literals in the query.
Add the second parameter for sp_executesql:
EXEC sp_executesql #SQL, N'#RecordCount nvarchar(5) output',#RecordCount OUTPUT

Create dynamic stored procedure for all databases with specific table

I would like to add the following stored procedure to all existing databases which contain the table schichten. All my approaches have failed so I'm looking for help here.
This is my approach:
IF object_id('tempdb.dbo.#database') is not null
drop TABLE #database
GO
CREATE TABLE #database(id INT identity primary key, name sysname)
GO
SET NOCOUNT ON
INSERT INTO #database(name)
SELECT name
FROM sys.databases
WHERE source_database_id is null
ORDER BY name
SELECT * FROM #database
DECLARE #id INT, #cnt INT, #sql NVARCHAR(MAX), #currentDb SYSNAME;
SELECT #id = 1, #cnt = max(id) FROM #database
WHILE #id <= #cnt
BEGIN
BEGIN TRY
SELECT #currentDb = name
FROM #database
WHERE id = #id
IF OBJECT_ID(#currentDb+'.dbo.schichten') IS NOT NULL
CREATE PROCEDURE #currentDb.[dbo].[Ausw_Tabelle_Taxi_Pers_Jahr]
#ColumnName nvarchar(MAX),
#Selector nvarchar(MAX),
#Gesamtergebnis nvarchar(MAX)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #sql1 AS NVARCHAR(MAX),
#ASSelector nvarchar(MAX),
#IFPers nvarchar(MAX);
IF #Selector = 'konz'
BEGIN
SET #ASSelector = 'Taxi'
SET #IFPers=''
END
ELSE
BEGIN
SET #ASSelector = 'Personal'
SET #IFPers = '[name] AS Name,'
END
SET #sql1 = N';WITH temp AS (SELECT *
FROM (
SELECT
ISNULL((DATENAME(m,[datum])+ cast(datepart(yyyy,[datum]) as varchar(5))),0) AS MONTHYEAR,
ISNULL(['+ #Selector +'],0) AS '+ #ASSelector +','+ #IFPers +'
ISNULL((ISNULL([umsum],0) +
ISNULL([sonst_0],0) +
ISNULL([sonst_7],0) +
ISNULL([sonst_16],0) +
ISNULL([sonst_z],0) -
ISNULL([ff],0)),0) AS UMSATZSUMME
FROM [dbo].[schichten]
) AS SOURCE
PIVOT (SUM([UMSATZSUMME]) FOR [MONTHYEAR] IN ('+ #ColumnName + N' )) AS UMSAETZE )
SELECT *, '+ #Gesamtergebnis +' AS Gesamtergebnis FROM temp ORDER BY '+ #ASSelector +''
EXEC sp_executesql #sql
END
END TRY
BEGIN CATCH
END CATCH
SET #id = #id + 1;
END
GO
I am hoping that there is someone who can help me.
You have to execute the create procedure separately, so if you wrap it up into a variable and use exec sp_executesql it should work.
IF object_id('tempdb.dbo.#database') is not null
drop TABLE #database
GO
CREATE TABLE #database(id INT identity primary key, name sysname)
GO
SET NOCOUNT ON
INSERT INTO #database(name)
SELECT name
FROM sys.databases
WHERE source_database_id is null
ORDER BY name
SELECT * FROM #database
DECLARE #id INT, #cnt INT, #sql NVARCHAR(MAX), #currentDb SYSNAME;
SELECT #id = 1, #cnt = max(id) FROM #database
WHILE #id <= #cnt
BEGIN
BEGIN TRY
SELECT #currentDb = name
FROM #database
WHERE id = #id
IF OBJECT_ID(#currentDb+'.dbo.schichten') IS NOT NULL
begin
set #sql = 'CREATE PROCEDURE '+#currentDb+'.[dbo].[Ausw_Tabelle_Taxi_Pers_Jahr]
#ColumnName nvarchar(MAX),
#Selector nvarchar(MAX),
#Gesamtergebnis nvarchar(MAX)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #sql1 AS NVARCHAR(MAX),
#ASSelector nvarchar(MAX),
#IFPers nvarchar(MAX);
IF #Selector = ''konz''
BEGIN
SET #ASSelector = ''Taxi''
SET #IFPers=''''
END
ELSE
BEGIN
SET #ASSelector = ''Personal''
SET #IFPers = ''[name] AS Name,''
END
SET #sql1 = N'';WITH temp AS (SELECT *
FROM (
SELECT
ISNULL((DATENAME(m,[datum])+ cast(datepart(yyyy,[datum]) as varchar(5))),0) AS MONTHYEAR,
ISNULL([''+ #Selector +''],0) AS ''+ #ASSelector +'',''+ #IFPers +''
ISNULL((ISNULL([umsum],0) +
ISNULL([sonst_0],0) +
ISNULL([sonst_7],0) +
ISNULL([sonst_16],0) +
ISNULL([sonst_z],0) -
ISNULL([ff],0)),0) AS UMSATZSUMME
FROM [dbo].[schichten]
) AS SOURCE
PIVOT (SUM([UMSATZSUMME]) FOR [MONTHYEAR] IN (''+ #ColumnName + N'' )) AS UMSAETZE )
SELECT *, ''+ #Gesamtergebnis +'' AS Gesamtergebnis FROM temp ORDER BY ''+ #ASSelector +''''
EXEC sp_executesql #sql1
END'
EXEC sp_executesql #sql
END TRY
BEGIN CATCH
END CATCH
SET #id = #id + 1;
END
GO
Assuming this is a one time need as opposed to a nightly maintenance task, you can use a built-in stored procedure, sys.sp_MSforeachdb, to execute a statement in each database. It is safe to use and has been discussed extensively on the web. However, it is an undocumented feature and can be removed without notice by Microsoft so you don't want to depend on it for recurring tasks.
Create and validate your statement in one database, then use this stored procedure to execute it in all of the databases. ? is the placeholder for the database name.
EXEC sys.sp_MSforeachdb #command1 =
'IF OBJECT_ID(''?.dbo.schichten'') IS NOT NULL
AND OBJECT_id(''?.[dbo].[Ausw_Tabelle_Taxi_Pers_Jahr]'') IS NOT NULL
BEGIN
CREATE PROCEDURE ?.[dbo].[Ausw_Tabelle_Taxi_Pers_Jahr]
#ColumnName nvarchar(MAX),
#Selector nvarchar(MAX),
#Gesamtergebnis nvarchar(MAX)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #sql1 AS NVARCHAR(MAX),
#ASSelector nvarchar(MAX),
#IFPers nvarchar(MAX);
IF #Selector = ''konz''
BEGIN
SET #ASSelector = ''Taxi''
SET #IFPers=''''
END
ELSE
BEGIN
SET #ASSelector = ''Personal''
SET #IFPers = ''[name] AS Name,''
END
SET #sql1 = N'';WITH temp AS (SELECT *
FROM (
SELECT
ISNULL((DATENAME(m,[datum])+ cast(datepart(yyyy,[datum]) as varchar(5))),0) AS MONTHYEAR,
ISNULL([''+ #Selector +''],0) AS ''+ #ASSelector +'',''+ #IFPers +''
ISNULL((ISNULL([umsum],0) +
ISNULL([sonst_0],0) +
ISNULL([sonst_7],0) +
ISNULL([sonst_16],0) +
ISNULL([sonst_z],0) -
ISNULL([ff],0)),0) AS UMSATZSUMME
FROM [dbo].[schichten]
) AS SOURCE
PIVOT (SUM([UMSATZSUMME]) FOR [MONTHYEAR] IN (''+ #ColumnName + N'' )) AS UMSAETZE )
SELECT *, ''+ #Gesamtergebnis +'' AS Gesamtergebnis FROM temp ORDER BY ''+ #ASSelector +''''
EXEC sp_executesql #sql1
END
'

Error while extracing XML data from XML file in sql server

DECLARE #TablesList TABLE
(
TableName VARCHAR(500),
RefTable VARCHAR(500),
RefTableIDColumn VARCHAR(500)
)
DECLARE #Query AS VARCHAR(MAX)
SET #Query = 'DECLARE #badIds AS VARCHAR(500) DECLARE #TableXML AS XML'
SET #Query = #Query + ' SELECT #TableXML = xCol FROM (SELECT * FROM OPENROWSET (BULK ''\\10.0.0.60\Temp\path\DataItemTables.xml'', SINGLE_CLOB)AS xCol) AS R(xCol)'
SET #Query = #Query + ' INSERT INTO #TablesList SELECT ref.value(''tablename[1]'',''nvarchar(500)'') AS tablename,'
SET #Query = #Query + ' ref.value(''refTable[1]'',''nvarchar(500)'') AS refTable, ref.value(''refTableIDColumn[1]'',''nvarchar(500)'') AS refTableIDColumn FROM'
SET #Query = #Query + ' #TableXML.nodes(''//Table[#name="Description"]'') AS R(ref)'
SET #Query = #Query +'select * from #TablesList'
EXEC(#Query)
I am executing the above script. But I am getting an error as below
Msg 1087, Level 15, State 2, Line 1
Must declare the table variable "#TablesList".
Msg 1087, Level 15, State 2, Line 1
Must declare the table variable "#TablesList".
What I am doing wrong. But when I write the query in dynamic form like below , it works fine. The problem is that I want to remove all the dynamic portion of the SP .
DECLARE #Query AS VARCHAR(MAX)
SET #Query ='DECLARE #TablesList TABLE ( TableName VARCHAR(500),RefTable VARCHAR(500),RefTableIDColumn VARCHAR(500))'
SET #Query = #Query + ' DECLARE #badIds AS VARCHAR(500) DECLARE #TableXML AS XML'
SET #Query = #Query + ' SELECT #TableXML = xCol FROM (SELECT * FROM OPENROWSET (BULK ''\\10.0.0.60\Temp\Path\DataItemTables.xml'', SINGLE_CLOB)AS xCol) AS R(xCol)'
SET #Query = #Query + ' INSERT INTO #TablesList SELECT ref.value(''tablename[1]'',''nvarchar(500)'') AS tablename,'
SET #Query = #Query + ' ref.value(''refTable[1]'',''nvarchar(500)'') AS refTable, ref.value(''refTableIDColumn[1]'',''nvarchar(500)'') AS refTableIDColumn FROM'
SET #Query = #Query + ' #TableXML.nodes(''//Table[#name="Description"]'') AS R(ref)'
SET #Query = #Query +'select * from #TablesList'
EXEC(#Query)
You can only access a table variable in the same scope where it is declared. Since your EXEC is in a different scope, the table variable is not recognized. One way to solve this is to use a temp table instead:
CREATE TABLE #TablesList
(
TableName VARCHAR(500),
RefTable VARCHAR(500),
RefTableIDColumn VARCHAR(500)
)
DECLARE #Query AS VARCHAR(MAX)
SET #Query = 'DECLARE #badIds AS VARCHAR(500) DECLARE #TableXML AS XML'
SET #Query = #Query + ' SELECT #TableXML = xCol FROM (SELECT * FROM OPENROWSET (BULK ''\\10.0.0.60\Temp\path\DataItemTables.xml'', SINGLE_CLOB)AS xCol) AS R(xCol)'
SET #Query = #Query + ' INSERT INTO #TablesList SELECT ref.value(''tablename[1]'',''nvarchar(500)'') AS tablename,'
SET #Query = #Query + ' ref.value(''refTable[1]'',''nvarchar(500)'') AS refTable, ref.value(''refTableIDColumn[1]'',''nvarchar(500)'') AS refTableIDColumn FROM'
SET #Query = #Query + ' #TableXML.nodes(''//Table[#name="Description"]'') AS R(ref)'
SET #Query = #Query +'select * from #TablesList'
EXEC(#Query)

Table variable in Stored Procudure

Hi I have developed a stored procedure in which I declared the a table variable called #TEMP_TABLE but for this line
SET #SQL1 = 'UPDATE PO_STAGE set PO_STAGE.ISVALID = ''N''
FROM ERP_ADMIN.'+#STAGE_TABLE+' PO_STAGE, #TEMP_TABLE TMP
where PO_STAGE.ERP_PO_ID = TMP.ERP_POID'
exec (#SQL1)
I am getting "Must declare the table variable "#TEMP_TABLE"." error.
Please help me in this regards.Below is the code for Stored Procedure.
CREATE PROCEDURE [ERP_ADMIN].[VALIDATE_PURCHASE_ORDER]
#STAGE_TABLE nvarchar(50)
-- #errorProperty nvarchar(50) output,
-- #errorValue nvarchar(120) output
AS
BEGIN
SET NOCOUNT ON;
DECLARE #rule INTEGER
DECLARE #approvalcheckingrecord VARCHAR(200)
DECLARE #APP_VALIDFROMDATE DATETIME,
#APP_VALIDTODATE DATETIME,
#numUpdated INTEGER,
#numInserted INTEGER,
#systodate VARCHAR(160),
#SQL1 [nvarchar](1200),
#SQL2 [nvarchar](1200),
#SOUCOL [nvarchar](200)
-- SELECT #systodate = CONVERT(VARCHAR(23), ERP_ADMIN.GETCURRENTDATE(), 110) +' '+ CONVERT(VARCHAR(23), ERP_ADMIN.GETCURRENTDATE(), 108)
--SELECT #systodate = CONVERT(VARCHAR(23), GETDATE(), 110) +' '+ CONVERT(VARCHAR(23), GETDATE(), 108)
SET #SQL1 = ''
SET #SQL1 = 'SELECT ERP_SOURCE_COLUMN
FROM [ERP_ADMIN].[ERP_STAGE_PROP_MAPPING] where [ERP_SOURCE_TABLE] = '''+#STAGE_TABLE+''' and [ERP_REPORT_COLOMNS] = ''Y'''
-- PRINT #SQL1
SET #SQL2 = 'DECLARE rpt_cursor CURSOR GLOBAL FOR ' + #SQL1
exec (#SQL2)
DECLARE #SOURCE_COLOMN nvarchar(80)
SET #SOUCOL = ''
OPEN rpt_cursor
WHILE (0 = 0)
--begin of while
BEGIN
FETCH NEXT FROM rpt_cursor INTO #SOURCE_COLOMN
IF (##FETCH_STATUS = -1)
BREAK
IF (#SOUCOL = '')
SET #SOUCOL = 'convert(nvarchar(255),ISNULL('+#SOURCE_COLOMN+',''''))+'',''+'
ELSE
SET #SOUCOL = #SOUCOL + 'convert(nvarchar(255),ISNULL('+#SOURCE_COLOMN+',''''))+'',''+'
END
CLOSE rpt_cursor
DEALLOCATE rpt_cursor
PRINT #SOUCOL
DECLARE #TEMP_TABLE TABLE (
ERP_POID nvarchar(50),
ERRORCD nvarchar(50),
ERRORMSG nvarchar(120)
)
SET #SQL1 = ''
SET #SQL1 = 'SELECT ERP_SOURCE_COLUMN
FROM [ERP_ADMIN].[ERP_STAGE_PROP_MAPPING] where [ERP_SOURCE_TABLE] = '''+#STAGE_TABLE+''' and [ERP_REPORT_COLOMNS] = ''Y'''
SET #SQL1 = 'SELECT [ERP_SOURCE_TABLE]
,[ERP_SOURCE_COLUMN]
,[ERP_MANDATORY_CHECK]
,[ERP_DATA_CHECK]
,[ERP_ERROR_PROPERTY1]
,[ERP_ERROR_VALUE1]
,[ERP_ERROR_PROPERTY2]
,[ERP_ERROR_VALUE2]
FROM [ERP_ADMIN].[ERP_STAGE_PROP_MAPPING] where [ERP_SOURCE_TABLE] = '''+#STAGE_TABLE+''' and ([ERP_MANDATORY_CHECK] IN (''K'',''Y'') or [ERP_DATA_CHECK] IN (''D'',''N''))'
PRINT #SQL1
SET #SQL2 = 'DECLARE stage_cursor CURSOR GLOBAL FOR ' + #SQL1
/** DECLARE stage_cursor CURSOR LOCAL FOR
/****** Script for SelectTopNRows command from SSMS ******/
SELECT [ERP_SOURCE_TABLE]
,[ERP_SOURCE_COLUMN]
,[ERP_MANDATORY_CHECK]
,[ERP_DATA_CHECK]
,[ERP_ERROR_PROPERTY1]
,[ERP_ERROR_VALUE1]
,[ERP_ERROR_PROPERTY2]
,[ERP_ERROR_VALUE2]
FROM [ERP_ADMIN].[ERP_STAGE_PROP_MAPPING] where [ERP_SOURCE_TABLE] = '+#STAGE_TABLE+' and ([ERP_MANDATORY_CHECK] IN ('K','Y') or [ERP_DATA_CHECK] IN ('D','N')) **/
exec(#SQL2)
DECLARE #CUR_SOURCE_TABLE [nvarchar](120),
#CUR_SOURCE_COLUMN [nvarchar](120),
#CUR_MANDATORY_CHECK [nvarchar](20),
#CUR_DATA_CHECK [nvarchar](20),
#CUR_ERROR_PROPERTY1 [nvarchar](50),
#CUR_ERROR_VALUE1 [nvarchar](120),
#CUR_ERROR_PROPERTY2 [nvarchar](50),
#CUR_ERROR_VALUE2 [nvarchar](120)
OPEN stage_cursor
WHILE (0 = 0)
--begin of while
BEGIN
FETCH NEXT FROM stage_cursor INTO
#CUR_SOURCE_TABLE,
#CUR_SOURCE_COLUMN,
#CUR_MANDATORY_CHECK,
#CUR_DATA_CHECK,
#CUR_ERROR_PROPERTY1,
#CUR_ERROR_VALUE1,
#CUR_ERROR_PROPERTY2,
#CUR_ERROR_VALUE2
IF (##FETCH_STATUS = -1)
BREAK
SET #SQL1 = ''
SET #SQL2 = ''
PRINT #CUR_SOURCE_COLUMN
-- IF(#CUR_SOURCE_COLUMN = 'ERP_PO_DOCNUMBER')
IF (#CUR_MANDATORY_CHECK = 'Y' OR #CUR_MANDATORY_CHECK = 'K')
BEGIN
-- SET #SQL1 = 'SELECT ''aaa'' as column1, ERP_PO_DOCNUMBER as column2
-- from PURCHASE_ORDER_STAGE where '+ #CUR_SOURCE_COLUMN +' IS NULL'
SET #SQL1 = 'SELECT ERP_PO_ID, '''+#CUR_ERROR_PROPERTY1+''' as column1,'+#SOUCOL+'''|1| ERR_01 '''''+#CUR_ERROR_VALUE1+'''+'' or null in input Worksheet'' as column2
from [ERP_ADMIN].'+#STAGE_TABLE+' where '+ #CUR_SOURCE_COLUMN +' IS NULL'
PRINT #SQL1
INSERT INTO #TEMP_TABLE
exec (#SQL1)
END
IF (LTRIM(RTRIM(#CUR_DATA_CHECK)) = 'D')
BEGIN
-- SET #SQL1 = 'SELECT ''aaa'' as column1, ERP_PO_DOCNUMBER as column2
-- from PURCHASE_ORDER_STAGE where '+ #CUR_SOURCE_COLUMN +' IS NULL'
SET #SQL1 = 'SELECT ERP_PO_ID, '''+#CUR_ERROR_PROPERTY2+''' as column1,'+#SOUCOL+'''|1| ERR_01 '''''+#CUR_ERROR_VALUE2+'''+'' in the input Worksheet'' as column2
from [ERP_ADMIN].'+#STAGE_TABLE+' where isdate('+ #CUR_SOURCE_COLUMN +') =0'
PRINT #SQL1
INSERT INTO #TEMP_TABLE
exec (#SQL1)
END
IF (LTRIM(RTRIM(#CUR_DATA_CHECK)) = 'N')
BEGIN
PRINT #CUR_SOURCE_COLUMN
SET #SQL1 = 'SELECT ERP_PO_ID, '''+#CUR_ERROR_PROPERTY2+''' as column1,'+#SOUCOL+'''|1| ERR_01 '''''+#CUR_ERROR_VALUE2+'''+'' in the input Worksheet'' as column2
from [ERP_ADMIN].'+#STAGE_TABLE+' where isnumeric('+ #CUR_SOURCE_COLUMN +') =0'
PRINT #SQL1
INSERT INTO #TEMP_TABLE
exec (#SQL1)
END
END
CLOSE stage_cursor
DEALLOCATE stage_cursor
SET #SQL1 = ''
SET #SQL1 = 'UPDATE PO_STAGE set PO_STAGE.ISVALID = ''N'' FROM ERP_ADMIN.'+#STAGE_TABLE+' PO_STAGE, #TEMP_TABLE TMP where PO_STAGE.ERP_PO_ID = TMP.ERP_POID'
PRINT #SQL1
exec (#SQL1)
/** DECLARE update_stage_cursor CURSOR LOCAL FOR
SELECT ERP_POID FROM #TEMP_TABLE
DECLARE #CURPOID [nvarchar](50)
OPEN update_stage_cursor
WHILE (0 = 0)
--begin of while
BEGIN
FETCH NEXT FROM update_stage_cursor INTO
#CURPOID
IF (##FETCH_STATUS = -1)
BREAK
END
CLOSE update_stage_cursor
DEALLOCATE update_stage_cursor **/
-- SELECT A.ERP_PO_ID FROM ERP_ADMIN.PURCHASE_ORDER_STAGE A, #TEMP_TABLE B where ERP_PO_ID = B.ERP_POID
SELECT ERRORCD, ERRORMSG FROM #TEMP_TABLE
END
GO
You should pass #TEMP_TABLE as parameter. To pass Table parameter you should create table type at first:
IF NOT EXISTS (SELECT 1 FROM sys.types WHERE NAME = 'TEMP_TABLE_TYPE')
CREATE TYPE TEMP_TABLE_TYPE AS TABLE(
ERP_POID nvarchar(50),
ERRORCD nvarchar(50),
ERRORMSG nvarchar(120)
);
And use it:
exec sp_executesql #Sql, N'#TEMP_TABLE TEMP_TABLE_TYPE readonly', #TEMP_TABLE
For epxplonation you can use this link Passing table variable into dynamic sql.
If you find this way not obvious, I advise to use temporary table instead of table varible:
CREATE TABLE #TEMP_TABLE (
ERP_POID nvarchar(50),
ERRORCD nvarchar(50),
ERRORMSG nvarchar(120)
);

Resources