sql-server – T-SQL动态SQL和临时表

看起来#通过EXECUTE字符串方法使用动态sql创建的#temptables具有不同的作用域,不能在同一个存储过程中被“固定”sql引用.
但是,我可以引用一个动态sql语句在子序列动态sql中创建的临时表,但似乎存储过程不会将查询结果返回给调用客户端,除非sql已修复.

一个简单的2表情景:
我有2张桌子我们叫他们订单和项目. Order具有OrderId的主键,Items具有ItemId的主键. Items.OrderId是标识父订单的外键.订单可以有1到n个项目.

我希望能够为用户提供一个非常灵活的“查询构建器”类型界面,以允许用户选择他想要查看的项目.过滤条件可以基于Items表和/或来自父Order表的字段.如果一个项目满足过滤条件,包括父项和条件,如果存在,则该项应该在查询中返回,也可以返回父级.

通常,我想大多数人会在Item表和父Order表之间构建一个连接.我想要执行2个单独的查询.一个返回所有符合条件的项目,另一个返回所有不同的父订单.原因是两倍,你可能也可能不同意.

一个原因是我需要查询父Order表中的所有列,如果单个查询将Orders表加入到Items表中,我将多次重写Order信息.由于每个订单通常有大量的项目,所以我想避免这种情况,因为这会导致更多的数据被转移到胖客户端.相反,如上所述,我想在数据集中单独返回两个表,并使用其中的两个表填充自定义的Order和子项目客户端对象. (我对LINQ或实体框架还不够了解,手工构建我的对象).我想返回两个表而不是一个表的第二个原因是因为我已经有另一个过程返回给定OrderId的所有项目以及父Order,我想使用相同的2表方法,以便我可以重用客户端代码,从返回的2个数据表中填充自定义的Order和Client对象.

我所希望的是这样的:

在客户端上构造一个动态sql字符串,它将订单表连接到Items表,并根据Winform胖客户端应用程序创建的自定义过滤器指定的每个表进行过滤.客户端上的sql构建将如下所示:

Tempsql =“

INSERT INTO #ItemsToQuery
   OrderId,ItemsId
FROM
   Orders,Items 
WHERE
   Orders.OrderID = Items.OrderId AND
   /* Some unpredictable Order filters go here */
  AND
   /* Some unpredictable Items filters go here */
"

然后,我会调用一个存储过程,

CREATE PROCEDURE GetItemsAndOrders(@tempsql as text)
   Execute (@tempsql) --to create the #ItemsToQuery table

SELECT * FROM Items WHERE Items.ItemId IN (SELECT ItemId FROM #ItemsToQuery)

SELECT * FROM Orders WHERE Orders.OrderId IN (SELECT disTINCT OrderId FROM #ItemsToQuery)

这种方法的问题是#ItemsToQuery表,因为它是由动态sql创建的,从以下2个静态sql中无法访问,并且如果我将静态sql更改为动态sql,则不会将结果传回胖客户端.

3周围想到,但我正在寻找一个更好的一个

1)可以通过从客户端执行动态构造的sql来执行第一个sql.然后可以将结果作为表传递到上述存储过程的修改版本.我很熟悉将表格数据传递给XML.如果我这样做,那么存储的proc可以使用静态sql将数据插入到临时表中,所以可以被查询而没有问题. (我也可以调查传递新的表类型参数而不是XML.)但是,我想避免将潜在的大型列表传递给存储过程.

2)我可以执行客户端的所有查询.

一个是这样的:

SELECT Items.* FROM Orders,WHERE Order.OrderId = Items.OrderId AND(dynamic filter)
SELECT Orders.* FROM Orders,Items WHERE Order.OrderId = Items.OrderId AND(dynamic filter)

这仍然使我有能力重用我的客户端对象人口代码,因为订单和项目继续在两个不同的表中返回.

我有一种感觉,我可以使用我的存储过程中的表数据类型有一些选项,但这对我来说也是新的,我会欣赏一点勺子喂养那个.

如果你甚至在我写的文件中扫描了这么远的话,我感到很惊讶,但如果是这样,我就会对你如何完成最好的想法感到高兴.

解决方法

您需要首先创建表,然后它将在动态sql中可用

这个工作

create table #temp3 (id int)
exec ('insert #temp3 values(1)')

select * from #temp3

这不行

exec ('create table #temp2 (id int)
     insert #temp2 values(1)')

select * from #temp2

换一种说法:

>创建临时表
>执行proc
>从temp表中选择

这是完整的例子

create proc prTest2 @var varchar(100)
as
exec (@var)
go

create table #temp (id int)

exec prTest2 'insert #temp values(1)'

select * from #temp

相关文章

SELECT a.*,b.dp_name,c.pa_name,fm_name=(CASE WHEN a.fm_n...
if not exists(select name from syscolumns where name=&am...
select a.*,pano=a.pa_no,b.pa_name,f.dp_name,e.fw_state_n...
要在 SQL Server 2019 中设置定时自动重启,可以使用 Window...
您收到的错误消息表明数据库 'EastRiver' 的...
首先我需要查询出需要使用SQL Server Profiler跟踪的数据库标...