Error while extracing XML data from XML file in sql server - 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)

Related

How can I turn this dynamic query into a procedure or function?

I have a dynamic query that pulls from a list of tables with the names of those stored in another table but I would like to be able to use the resulting set in another query.
declare #t table( tablename varchar(50))
declare #sql varchar(max)
set #sql = ''
insert into #t
SELECT t.svc_table AS table_name FROM svc_defs AS t
SELECT #sql = #sql + 'Select convert(varchar(5),svc_defs.svc_id) as svcid, data_id, crid, d_custid, d_active From ' + tablename +
' inner join svc_defs on svc_defs.svc_table = ' + '''' + tablename + '''' + ' union ' from #t
--remove the trailing 'union'
Select #sql = substring(#sql, 1, len(#sql) - 6)
exec (#sql)
You can create scalar user defined function, which returns the sql statement.
CREATE FUNCTION dbo.udf_GenerateSelectQuery()
Returns nvarchar(max)
AS
BEGIN
declare #t table( tablename SYSNAME)
declare #sql Nvarchar(max)
set #sql = ''
insert into #t
SELECT t.TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES AS t
SELECT #sql = #sql + 'Select convert(varchar(5),svc_defs.svc_id) as svcid, data_id, crid, d_custid, d_active From ' + tablename +
' inner join svc_defs on svc_defs.svc_table = ' + '''' + tablename + '''' + ' union ' from #t
--remove the trailing 'union'
Select #sql = substring(#sql, 1, len(#sql) - 6)
RETURN #sql
END
you can call it as
declare #sqlstmt NVARCHAR(max) = dbo.udf_GenerateSelectQuery()
SELECT #sqlstmt
or as
declare #sqlstmt NVARCHAR(max)
SET #sqlstmt = (SELECT dbo.udf_GenerateSelectQuery())
SELECT #sqlstmt

Can I loop create Triggers for all tables?

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;

Using table type param in SQL server stored procedure

I use table type param (#listdraftIds) and split data in table to compare with data in DB but the error is as below. Help me, thank you.
CREATE OR ALTER PROCEDURE [dbo].[sp_sel_contract]
(
#listDraftId nvarchar(max),
#Page int,
#PageNumber int,
#TotalRecord int OUTPUT
)
AS
BEGIN
SET NOCOUNT ON
BEGIN
DECLARE #listdraftIds TABLE (draftIds nvarchar(max))
INSERT INTO #listdraftIds VALUES(#listDraftId)
DECLARE #sql varchar(MAX)
SET #sql= ' ALTER DATABASE '+ quotename(db_name()) + ' SET COMPATIBILITY_LEVEL = 130 ';
EXEC(#sql)
END
DECLARE #query NVARCHAR(MAX)
DECLARE #newquery NVARCHAR(MAX)
DECLARE #RowIndex int
SET #RowIndex = (#Page-1) * #PageNumber
SET #query = ''
SET #query = #query + ' SELECT DISTINCT'
SET #query = #query + ' [d].[draft_id], '
...
SET #query = #query + 'WHERE '
SET #query = #query + ' [d].[del_flg] = ''FALSE'''
SET #query = #query + 'AND '
SET #query = #query + ' [d].[draft_id] '
SET #query = #query + 'IN ('
SET #query = #query + ' SELECT DISTINCT '
SET #query = #query + ' value AS draft_id '
SET #query = #query + 'FROM '
SET #query = #query + ' #listdraftIds '
SET #query = #query + 'CROSS APPLY STRING_SPLIT(draftIds, '','') '
SET #query = #query + 'WHERE '
SET #query = #query + ' RTRIM(value) <> '''' )'
PRINT #query
SET #newquery = ' SET #TotalRecord = (SELECT COUNT(*) FROM (' + #query +') AS t) '
SET #newquery = #newquery + ' ORDER BY '
SET #newquery = #newquery + ' [draft_date] DESC, [d].[draft_id] DESC, [g].[detail_no] ASC'
SET #newquery = #newquery + ' OFFSET #RowIndex ROWS FETCH NEXT #PageNumber ROWS ONLY'
EXECUTE sp_executesql #newquery,
#listDraftId = #listDraftId,
#RowIndex = #RowIndex,
#PageNumber = #PageNumber,
#TotalRecord = #TotalRecord OUTPUT
END
Then Exec proc:
DECLARE #return_value int,
#TotalRecord int
EXEC #return_value = [dbo].[sp_sel_draft_condition_api1]
#listDraftId = N'123,345',
#Page = 1,
#PageNumber = 20,
#TotalRecord = #TotalRecord OUTPUT
SELECT #TotalRecord as N'#TotalRecord'
SELECT 'Return Value' = #return_value
GO
Error:
Msg 102, Level 15, State 1, Line 3
Incorrect syntax near '30302'.
Msg 1087, Level 15, State 2, Line 3
Must declare the table variable "#listdraftIds".
Msg 137, Level 15, State 2, Line 3
Must declare the scalar variable "#PageNumber".
few issue here with the stored procedure
First, sp_executesql execute in its own context. So variable declared outside of it is not recognized. Which means, if you need to use a variable, you need to pass it into sp_executesql.
Your sp_executesql statement does not defined any variable
it should be
EXECUTE sp_executesql #newquery,
N'#RowIndex int, #PageNumber int, #TotalRecord int OUTPUT',
#RowIndex = #RowIndex,
#PageNumber = #PageNumber,
#TotalRecord = #TotalRecord OUTPUT
Note that I didn't include the #listDraftId. That is because you can't pass a table variable into sp_executesql. One alternative is to use a temp table
So in your sp_sel_contract
create table #listdraftId ( draftIds nvarchar(max) )
And then you can reference the temp table #listdraftId in you dynamic query
Actually looking at your dynamic query, you don't required a table variable or temp table. You only have one value of #listDraftId that is pass into sp_sel_contract and then it is pass into the dynamic query. So you can pass that variable directly into the dynamic query. Example :
EXECUTE sp_executesql #newquery,
N'#listDraftId nvarchar(max), #RowIndex int, #PageNumber int, #TotalRecord int OUTPUT',
#listDraftId = #listDraftId,
#RowIndex = #RowIndex,
#PageNumber = #PageNumber,
#TotalRecord = #TotalRecord OUTPUT
EDIT :
Now i have a closer look at your dynamic query ? I don't see a need to use dynamic query at all. You can achieve what you want with normal query

sql Append for value with single quotes

am having below query
DECLARE #fNAME varchar(40) = 'Obrain'
DECLARE #query nvarchar(256)
SET #query = 'UPDATE TableName SET columnname = ''' + #fNAME + ''''
select #query
which results as expected
UPDATE TableName SET columnname = 'Obrain'
But if i change input #fname with single quotes
DECLARE #fNAME varchar(40) = 'O''brain'
DECLARE #query nvarchar(256)
SET #query = 'UPDATE TableName SET columnname = ''' + #fNAME + ''''
select #query
i get below result where am having issue with single quotes
UPDATE TableName SET columnname = 'O'brain'
How do i fix this query with minor changes
What is the better way to do this
The right way to do this? Use sp_executesql and parameters:
DECLARE #fNAME varchar(40) = 'O''brain';
DECLARE #query nvarchar(256);
SET #query = '
UPDATE TableName SET columnname = #fNAME'
EXEC sp_executesql #query, N'#fNAME varchar(40)', #fName=#fName;

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

Resources