Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server MSSQL存储过程动态创建临时表_Sql Server - Fatal编程技术网

Sql server MSSQL存储过程动态创建临时表

Sql server MSSQL存储过程动态创建临时表,sql-server,Sql Server,我们正在尝试编写一些自动报告来执行存储在表中的SQL语句。表数据通常在触发器调用的存储过程中使用,并使用通过触发器语句中创建的临时表传入的数据,该数据有一个表名,然后是一个作用于tempierted和tempedeleted的SQL语句,对应于触发器中插入和删除的对象,然后是一些电子邮件列,这些列决定了将输出发送到何处 这一切都可以从触发器语句中正常工作,因为每个触发器语句在执行过程中都会创建一次临时表:- SELECT * INTO #TempInserted FROM INSERTED SE

我们正在尝试编写一些自动报告来执行存储在表中的SQL语句。表数据通常在触发器调用的存储过程中使用,并使用通过触发器语句中创建的临时表传入的数据,该数据有一个表名,然后是一个作用于tempierted和tempedeleted的SQL语句,对应于触发器中插入和删除的对象,然后是一些电子邮件列,这些列决定了将输出发送到何处

这一切都可以从触发器语句中正常工作,因为每个触发器语句在执行过程中都会创建一次临时表:-

SELECT * INTO #TempInserted FROM INSERTED
SELECT * INTO #TempDeleted FROM DELETED
然后,触发器调用TriggerHandler存储过程,并将表名作为参数传递

但是,当我试图从常规存储过程中动态创建这些语句,以便将这些语句作为报告发出,这样我们就不会在批处理中重复这些语句时,我遇到了一个问题:-

SELECT * INTO #TempInserted FROM ...
从定义的表或对象(例如从INSERTED)可以很好地工作,但我发现它无法从动态查询中获取其模式

例如,我能做什么

SELECT TOP 1 * INTO #Test FROM TableA 
SELECT * FROM #Test
DROP TABLE #Test
但我不能那么做

EXECUTE sp_executesql N'SELECT TOP 1 * INTO #Test FROM TableA'
SELECT * FROM #Test
DROP TABLE #Test
因为Test是执行上下文的本地测试,而不是其父级。 但是,如果我已经创建了表架构,我可以在EXECUTE或存储过程中执行insert,因为temp表在范围内:-

SELECT * INTO #Test FROM TableA WHERE 1 = 2 -- create an empty schema
EXECUTE sp_executesql N'INSERT INTO #Test SELECT TOP 10 * FROM TableA'
SELECT * FROM #Test
DROP TABLE #Test
所以,这没关系,但当我想根据运行报告的表名动态创建该模式时,问题就来了。插页的作用是:-

SELECT * INTO #Test FROM TableA WHERE 1 = 2 -- create an empty schema
DECLARE @Table NVARCHAR(20) = 'TableA'
DECLARE @SQL NVARCHAR(200) = N'INSERT INTO #Test SELECT TOP 10 * FROM ' + @Table
EXECUTE sp_executesql @SQL
SELECT * FROM #Test
DROP TABLE #Test
但前提是临时表已经有一个模式。如果根据所选的表,尝试有条件地创建架构,则会出现解析错误:-

DECLARE @Table NVARCHAR(20) = 'TableA'
IF @Table = 'TableA'
    SELECT * INTO #Test FROM TableA WHERE 1 = 2 -- create an empty schema
IF @Table = 'TableB'
    SELECT * INTO #Test FROM TableB WHERE 1 = 2 -- create an empty schema

DECLARE @SQL NVARCHAR(200) = N'INSERT INTO #Test SELECT TOP 10 * FROM ' + @Table
EXECUTE sp_executesql @SQL
SELECT * FROM #Test
DROP TABLE #Test
假定数据库中已存在名为“Test”的对象。-因此,查询解析器没有遵循查询的结构,实际上只创建一次临时表。如果你这样做,这也是正确的

SELECT * INTO #Test FROM ....
DROP TABLE #Test
SELECT * INTO #Test FROM ....
那么,在SQLServer2012中有没有一种方法可以

SELECT * INTO #Test FROM (dynamic SQL statement)
或者绕过解析器,认为您正在创建两次对象

DECLARE @Table NVARCHAR(20) = 'TableA'
IF @Table = 'TableA'
    SELECT * INTO #Test FROM TableA WHERE 1 = 2 -- create an empty schema
IF @Table = 'TableB'
    SELECT * INTO #Test FROM TableB WHERE 1 = 2 -- create an empty schema
或者从现有数据库表的模式动态创建本地范围的临时表,其中表名存储在一个变量中。我发现的所有示例都使用SELECT*INTO测试代码,正如我所提到的,它需要一个静态定义的对象来创建

----编辑----

下面是一个我们为什么这样做的例子:- 如果某个项目类型在某个位置进行交易,则触发器可能会触发并生成警告电子邮件。这适用于我们当前的触发器。我们这样做的原因是,我们可以在将来编写一个UI,以便用户可以自己将其他项目类型添加到此列表中,而不是我们必须更新触发器-这也意味着我们可以控制/验证正在生成的SQL,在点击界面的幕后,这样我们的用户就不需要知道任何SQL,并且我们可以确保不会使用任何恶意的或会导致错误的东西

我们也不能在BLL中这样做,因为它来自我们的ERP系统,这意味着我们必须对基本对象进行更改,如果可以避免的话,这显然是不可取的

其中一些电子邮件可能会被遗漏/忽略/遗忘/不采取行动,因此用户定期以及在交易发生时请求相同的信息:-


因此,接下来,我们要为其中一些触发语句生成每日/每周/每月报告。现在,很明显,如果我们可以使用我们已经设置的现有SQL触发器语句,这将是理想的,因为如果一个语句被更改,它将自动影响定期报告-保持干燥。这还意味着,如果我们设置了一个新的触发器,我们只需在驱动定期报告存储过程的表中插入对触发器代码的引用,以及表名、频率等,就可以自动将其包含在报告中。同样,在将来,我们可以编写一个用户界面,这样用户就可以自己请求和安排这些报告,而不需要我们的干预。

我怀疑我在这里陷入了两难境地。然而,我找到了一种不太混乱的解决方法。我将项处理代码提取到另一个存储过程中,然后将其复合执行到动态SELECT into语句中——这样它就可以在同一执行实例中运行,从而可以访问在该实例中创建的临时表以及该实例的本地临时表:-

SET @SQL = 'SELECT * INTO #TestTable FROM ' + @Table + ' WHERE ' + @WhereClause
SET @SQL = @SQL + '; EXEC ReportProcess'
EXECUTE sp_executeSQL @SQL

ReportProcess存储过程随后可以访问临时表并对其进行处理,因此

您是否已经在触发器中执行了select*?至少听起来它可以解决您的所有问题我们目前在触发器中执行select*,正如我提到的,但我们现在正尝试重用这些语句并将它们分组为计划报告,因此我们将光标放在报告表上,然后单击crea
依次基于多个不同的表来插入和删除每个tempInsert和tempDelete,这就是问题所在。例如,TableA和TableB的触发器将分别创建这些临时表。我们希望围绕一个包含TableA和TableB值的表进行循环,然后执行如下操作:获取表名;使用触发器执行SP;获取下一个表名;环这就是问题所在有一个答案,但它并不漂亮:嵌套动态SQL。