Is there a way to create XML type variable in Microsoft SQL Server and append values to it using a cursor? It should work like this:
Create empty XML type variable
Open cursor
Create dynamic SQL query in cursor depending on cursor value that generates result which is XML
In each fetch append result of query to XML variable
Is this even possible?
Problem is, I am generating XML, but the query to get it is dynamic and each query gets results from another table which I get using cursor and
select TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
For each table_name I get from this cursor, there is another query which generates XML result, which should all be merged into one XML.
This is done by making query as string variable which is executed later and should append to the XML variable.
This would be sample how one of such dynamic queries could look like where later TABLENAME should be replaced with table_name from cursor and then execute query:
select
_TABLENAME_ as 'TABLE/#path',
(select
t1.id as 'value/#id',
t1.name as 'value',
t2.name as 'value_jp'
from
_TABLE_NAME t1, _TABLENAME_ + '_locale' t2
where
t1.ID = t2.FK_Id and t2.FK_Locale = 38
for xml path(''), root('rows'), type)
for xml path('')
Related
I am trying do the following using SSIS. I am using SDT latest version and querying SQL Server 2008 R2.
Could somebody suggest if I am doing it wrong and if there is a better way in doing it
I basically need to execute a stored procedures from the source and store the results it in the destination. There are around 20 stored procedures.
Each of the stored procedures takes XML as input. I have created a Control task within that a data flow task. Within the data flow i am creating the oledb source.
I have selected Data access mode as SQL command. I am created my query below but when i preview , I get error saying that declare statement is not supported
DECLARE #xmldata XML
SET #xmldata = (SELECT DISTINCT TOP 1000 (mc.companyId) AS id
FROM ciqMarketCap mc
JOIN ciqCompany c ON c.companyid = mc.companyid
WHERE c.companyStatusTypeId NOT IN (5, 6)
AND c.companyTypeId IN (1, 4)
FOR XML PATH(''), TYPE, ROOT('partyIds'))
EXEC getPartiesMarketData #xmldata
How do I execute the rest of the stored procedures? Do I need to create several oledb sources?
I recommend doing in steps:
Create variables in SSIS:
xmldata string set = ""
SQLquery string set formula of "Exec getPartiesMarketData " + #xmldata
In execute sql task enter sql statement into Direct Input:
SELECT DISTINCT top 1000 (mc.companyId) as id
FROM ciqMarketCap mc
JOIN ciqCompany c
ON c.companyid = mc.companyid
WHERE c.companyStatusTypeId NOT IN (5,6) AND c.companyTypeId IN (1,4) for xml path(''), type, root('partyIds')
Change the result set to XML
Map result xmldata
Then in another execute sql connected you will do your real query:
SQL Source type: variable
Source Variable: SQLquery
I haven't tested this, but I am pretty sure it will work.
If I run this dynamic query:
declare #test nvarchar(1000) = 'select * into #tmp7 from bauser'
execute(#test)
and then try to query #tmp7 with:
select * from #tmp7
error is thrown:
Invalid object name '#tmp7'.
However if I run the same query manually:
select * into #tmp7 from bauser
Everything is OK. Temporary table is created and filled with results.
Why is it not working with dynamic query execution?
SCOPE!
The temporary table exists only in the scope of the dynamic executed query
If you do want to make the select put it inside the dynamic query
declare #test nvarchar(1000) = 'select * into #tmp7 from bauser
select * from #tmp7'
execute(#test)
Also you can check if a such object exists by using this
select * from sys.sysobjects so where so.name like '%tmp7%'
See this similar question
SQL Server 2005 and temporary table scope
Edit
A temp table IS A TABLE so yes you can add columns, indexes, etc. Those tables resides in fact in the TempDB database and you can even "find" them (they can be seen with strange long names) but they are destroyed after the execution of your EXEC.
Maybe your problem is to try the dynamic approach or is not related to your question at all. Try to post a new question what you got and what you need to do to get further assistance.
If you create temp table using dynamic SQL, it will not be available out of dynamic SQL scope.
You need to create it out of dynamic SQL and then use INSERT INTO to populate the table.
-- use this trick to create the temp table easily.
SELECT * INTO #tmp7
FROM bauser
WHERE 1=2
declare #test nvarchar(1000) = 'insert into #tmp7 select * from bauser'
execute(#test)
I need to log the stored procedure name to determine which stored procedure are being used.
To accomplish this I am embedding an insert statement in each of the stored procedures we have to log it's usage.
I could hard code the SP name in the INSERT statement but I am looking for an elegant way to get the current stored procedure name rather than hard coding, this is primarily to be able to search for and remove identical lines of code after the project.
I have a table called tblUsed (ID INT, dateused date, sprocused varchar(50)) and was planning to do an insert in each query.
INSERT INTO [stockist].[dbo].[tblUsed]
([objectName])
VALUES
(*procname*)
I just need to get the name of the proc for this to work.
If there are any other ways to accomplish this I would be happy to hear them.
Thank you in advance.
Let's look at this from the ground up for you.
To get the name of the stored procedure you need to run the OBJECT_NAME(object_id [, database_id ]) metadata function(more info here). As you are running this T-SQL within the object in question, you won't need the database_id so the code you'll run will look something like this:
OBJECT_NAME(*object_id*)
To get the object id for the current T-SQL module you will need to use the ##PROCID metadata function(more info here) giving you the following code:
OBJECT_NAME(##PROCID)
In this case your INSERT statement will look like this:
INSERT INTO tblUsed (sprocused)
VALUES (OBJECT_NAME(##PROCID))
If you use multiple schema's you will probably need to be record which schema you are in using the OBJECT_SCHEMA(object_id [, database_id ]) metadata function(more info here) giving you this:
OBJECT_SCHEMA_NAME(##PROCID) + '.' + OBJECT_NAME(##PROCID)
In this case your INSERT statement will look like this:
INSERT INTO tblUsed (sprocused)
VALUES (OBJECT_SCHEMA_NAME(##PROCID) + '.' + OBJECT_NAME(##PROCID))
One other possible way to accomplish this without all the overhead of an unnecessary insert in all your queries is through the use of DMVs(Dynamic management views) here is a sample query (from this SO thread)
SELECT sc.name
, p.name
FROM sys.procedures AS p
INNER JOIN sys.schemas AS sc
ON p.[schema_id] = sc.[schema_id]
LEFT OUTER JOIN sys.dm_exec_procedure_stats AS st
ON p.[object_id] = st.[object_id]
WHERE st.[object_id] IS NULL
ORDER BY p.name;
NB: This will only give you the information from the last time SQL was restarted.
As a result of this question you might want to ensure that none of your procs are referenced anywhere else in the db you can do this like so:
SELECT referencing_schema_name
, referencing_entity_name
FROM sys.dm_sql_referencing_entities ('*schemaname.objectname*', 'OBJECT');
Does the command FOR XML in MS SQL Server save the file in disk?
I'm creating a trigger to log operations in a table and part of this trigger is create a XML with the affected row. I'm thinking of using the FOR XML to generate the XML.
SELECT *
FROM TBL_Test
WHERE ID=3040
FOR XML RAW
My worry is that I will be using it in a trigger and I donĀ“t want to save files in the server every time I call the FOR XML function.
In addition: would you guys know how to parse it to varchar?
Thanks in advance for any help!
Like any SELECT query, a query with the FOR XML clause will return the result to the client and not save the result to disk.
You can use a scalar subquery to assign the result XML to a varchar variable instead of returning to the client:
DECLARE #xml varchar(MAX) =
(
SELECT *
FROM dbo.TBL_Test
WHERE ID=3040
FOR XML RAW
);
Is there a way to cause the result set of a SQL Server stored procedure (or any result set, after the fact) to be encoded in XML format?
I want the result set to be encoded in XML as if the FOR XML RAW clause was used during selection.
However the complex stored procedure logic and its internal SELECT statements should not be modified to return XML because the procedure is used for its standard/non-XML result set most of the time.
Update: Emphasis on the fact I'm looking for an answer in the SQL Server environment - the
results should be returned as if SQL Server has directly encoded them itself, as XML, just like it does when using the built-in XML features like the FOR XML clause.
You would insert the data from the SP into a temp table, then select from that FOR XML
This won't work if the SP itself already does a INSERT .. EXEC SPROC because you cannot nest them
Working examples
use tempdb;
create proc giveme
as
select a = 1, b = GETDATE()
union all
select 2, b = '20100101'
Using INSERT.. EXEC
declare #t table (a int, b datetime)
insert #t
exec giveme
select * from #t for xml raw
Using OPENQUERY
exec sp_addlinkedserver 'localhost'
exec sp_serveroption #server = 'localhost'
,#optname = 'DATA ACCESS'
,#optvalue = 'TRUE'
select *
from openquery(localhost, 'exec tempdb..giveme')
for xml raw
You could try using OPENROWSET in cooperation with FOR XML to do the transformation.
By 'after the fact', do you mean still within the SQL Server environment? Or are you talking about a client program?
Within SQL, you could probably write a sproc that acts as a wrapper for your other sprocs, along these lines. The wrapper sproc would handle the FOR XML work.
In .NET, there are a number of ways to do this.
You can try inserting the result set from the stored procedure into a table variable( or temporary table) and selecting the table rows with the FOR XML clause.
Here is an example:
DECLARE #MyDataTable AS TABLE ( col1 int,...., colN int)
Make sure that the #MyDataTable has the same columns as the stored procedure result set(s).
INSERT INTO #MyDataTable
EXECUTE mysp_GetData #param1=value,....,#paramN;
SELECT * FROM #MyDataTable
FOR XML AUTO