[英]How to store results of a Dynamic Query in a temp table without creating a table?
We are writing a stored procedure responsible for getting a stored procedure name and returning a result containing the stored procedure columns and their data types.我们正在编写一个存储过程,负责获取存储过程名称并返回包含存储过程列及其数据类型的结果。 However, we bumped into a problem executing a dynamic query to return the results of stored procedure, but we can't store it in a temp table!
但是,我们在执行动态查询以返回存储过程的结果时遇到了问题,但我们无法将其存储在临时表中!
You can see our query below:您可以在下面看到我们的查询:
DECLARE @ProcName VARCHAR(100)='spGetOraganizationsList',
@ParamName VARCHAR(100),@DataType VARCHAR(20),
@Query NVARCHAR(MAX)='EXEC '+'spGetOraganizationsList '
SELECT PARAMETER_NAME,DATA_TYPE
INTO #Tmp
FROM information_schema.PARAMETERS
WHERE SPECIFIC_NAME=@ProcName
DECLARE ParamCursor CURSOR
FOR SELECT * FROM #Tmp
OPEN ParamCursor
FETCH NEXT FROM ParamCursor
INTO @ParamName,@DataType
WHILE @@FETCH_STATUS = 0
BEGIN
SET @Query=@Query+@ParamName+'=Null,'
FETCH NEXT FROM ParamCursor INTO @ParamName,@DataType
END
CLOSE ParamCursor
DEALLOCATE ParamCursor
DROP TABLE #Tmp
EXEC sp_executesql @Query
The thing is I can't store the results of it in a temp table, and OPENROWSET
does not accept variables.问题是我无法将它的结果存储在临时表中,并且
OPENROWSET
不接受变量。
I think it comes from sql concept that it doesn't trust in result of stored procedures and because of that we cannot select on it or store it in a table by 'making in query table' method.我认为它来自 sql 概念,它不信任存储过程的结果,因此我们无法通过“在查询表中制作”方法对其进行选择或将其存储在表中。 Unless you create a table and define it's columns and sql trust to you and you insert result of it into this table for example take below situation
除非您创建一个表并为您定义它的列和 sql 信任并将其结果插入到该表中,例如以下情况
Create table test (name varchar(10),family varchar(20))
Insert into test
Exec sp-testResult
Now if you define wrong column for your table you will receive query runtime error .actually sql doesn't predict result of sp and leaves it to you to define result of your stored procedure.现在,如果您为表定义了错误的列,您将收到查询运行时错误。实际上 sql 不会预测 sp 的结果,而是由您来定义存储过程的结果。
Why not create a view instead of creating and dropping the tables. 为什么不创建视图而不是创建和删除表。
CREATE VIEW "VIEW_NAME" AS "SQL Statement";
An unrelated example:- 一个不相关的例子:
CREATE VIEW V_Customer
AS SELECT First_Name, Last_Name, Country
FROM Customer;
You can certainly INSERT the results of a stored procedure into a TEMP table:您当然可以将存储过程的结果插入到 TEMP 表中:
CREATE PROCEDURE PurgeMe
AS
SELECT convert(int, 1) AS DaData
UNION
SELECT convert(int, 2)
GO
CREATE TABLE #Doodles (AnInteger int)
INSERT #Doodles EXECUTE PurgeMe
SELECT * FROM #Doodles
Questions arise about the SCOPE of TEMP tables, however.然而,关于 TEMP 表的 SCOPE 的问题出现了。 You might find that in your calling routine you will not be able to see a TEMP table created within your routine.
您可能会发现,在您的调用例程中,您将看不到在例程中创建的 TEMP 表。
The solution to the SCOPE problem is to do the following: SCOPE 问题的解决方案是执行以下操作:
If this is of interest I can make a longer post with a stored procedure to do the above.如果对此感兴趣,我可以使用存储过程制作更长的帖子来执行上述操作。 It was written to facilitate dynamic SQL
它是为了方便动态 SQL 而编写的
Use global temp table and dynamic OPENROWSET
使用全局临时表和动态
OPENROWSET
DROP TABLE ##Tmp;
GO
DECLARE @ProcName VARCHAR(100)='spGetOraganizationsList',
@ParamName VARCHAR(100), @DataType VARCHAR(20),
-- Mind to specify database and schema of the SP
@Query NVARCHAR(MAX)=' EXEC [mydb].[dbo].spGetOraganizationsList ';
SELECT PARAMETER_NAME,DATA_TYPE
INTO #Tmp
FROM information_schema.PARAMETERS
WHERE SPECIFIC_NAME=@ProcName;
-- Build SP exec
DECLARE ParamCursor CURSOR
FOR SELECT * FROM #Tmp
OPEN ParamCursor
FETCH NEXT FROM ParamCursor
INTO @ParamName,@DataType
WHILE @@FETCH_STATUS = 0
BEGIN
SET @Query=@Query+@ParamName+'=Null,'
FETCH NEXT FROM ParamCursor INTO @ParamName,@DataType
END
CLOSE ParamCursor
DEALLOCATE ParamCursor
SET @Query = left(@Query, len(@Query) - 1);
-- Build ad hoc distributed query which creates ##Tmp from SP exec.
SET @Query = 'SELECT * INTO ##Tmp FROM OPENROWSET(''SQLNCLI'', ''Server=localhost;Trusted_Connection=yes;'',''' + @Query + ''')';
EXEC (@Query);
-- Created by dynamic sql `##Tmp` is availabe in the current context.
SELECT *
FROM ##Tmp;
Don't forget to enable ad hoc distributed queries first.不要忘记首先启用即席分布式查询。
sp_configure 'Show Advanced Options', 1
GO
RECONFIGURE
GO
sp_configure 'Ad Hoc Distributed Queries', 1
GO
RECONFIGURE
GO
EDIT编辑
My answer solves only one problem, storing the result of a dynamic proc call in a temp table.我的回答只解决了一个问题,将动态 proc 调用的结果存储在临时表中。 And there are more problems.
还有更多的问题。
First, @p=null
just will not compile if the type of @p
is user-defined table type.首先,如果
@p
的类型是用户定义的表类型, @p=null
将不会编译。 You need kind of declare @t myType; exec mySp ... ,@p=@t ...
你需要
declare @t myType; exec mySp ... ,@p=@t ...
declare @t myType; exec mySp ... ,@p=@t ...
. declare @t myType; exec mySp ... ,@p=@t ...
.
Next is the 'cannot retrieve matadata for sp because contain dynamic query' error you commented on.接下来是您评论的“无法检索 sp 的 matadata 因为包含动态查询”错误。 Looks like you need an application, SqlClr or standalone, which would be capable to read and parse Datasets returned by procs.
看起来你需要一个应用程序,SqlClr 或独立的,它能够读取和解析 procs 返回的数据集。
Finally, if an SP contains conditional sql which can return a result set of different schema depending on parameter values, the result of all those efforts is still questionable.最后,如果一个 SP 包含条件 sql,它可以根据参数值返回不同模式的结果集,所有这些努力的结果仍然值得怀疑。
Write select query as you want in the stored procedure.在存储过程中根据需要编写选择查询。 You will get the result without creating temp table.
您无需创建临时表即可获得结果。
In C#, you can use an SqlDataReader or a DataTable to get the results from a stored procedure without knowing the schema beforehand.在 C# 中,您可以使用 SqlDataReader 或 DataTable 从存储过程中获取结果,而无需事先知道架构。 If you then want to write that data to a temporary table, I think you can do that from C# (though I've never tried to do it).
如果您想将该数据写入临时表,我认为您可以从 C# 中做到这一点(尽管我从未尝试过这样做)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.