看起来通过EXECUTE字符串方法创建的动态SQL生成的#temptables具有不同的作用域,不能被同一存储过程中的“固定”SQL引用。但是,在后续的动态SQL语句中,我可以引用由动态SQL语句创建的临时表,但似乎存储过程不会返回查询结果到调用客户端,除非SQL是固定的。
简单的两个表情况: 我有两张表。让我们称其为Orders和Items。Order具有OrderId的主键,Items具有ItemId的主键。Items.OrderId是标识父Order的外键。一个Order可以有1到n个项。
我希望能够向用户提供非常灵活的“查询构建器”类型界面,以允许用户选择要查看的项目。筛选条件可以基于Items表和/或父Order表中的字段。如果一个Item符合筛选条件,包括父Order上的条件(如果存在),则该Item应在查询中返回以及父Order。
通常,我认为,大多数人会构建项表和父Order表之间的连接。我想执行2个独立的查询。一个返回所有符合条件的项,另一个返回所有不同的父Order。原因有两个,你可能同意也可能不同意。
第一个原因是,我需要查询父Order表中的所有列,如果我执行单个查询将Orders表与Items表连接起来,我将重复多次Order信息。因为每个订单通常有大量的物品,所以我想避免这种情况,因为这将导致更多的数据传输到fat client上。相反,如上所述,我想在数据集中单独返回两个表,并在其中使用这两个表来填充自定义的Order和child Items客户端对象。(我还不太了解LINQ或Entity Framework。我手动构建我的对象)。第二个原因是我已经有另一个过程,可以返回给定OrderId的所有Items以及父Order,我想使用相同的2表方法,以便我可以重用客户端代码从返回的2个数据表填充我的自定义Order和Client 对象。
我希望能做的是这样的: 在Client上构建一个动态SQL字符串,将orders表连接到Items表,并根据Winform fat-client应用程序上创建的自定义筛选器在每个表上进行适当的筛选。在客户端上构建的SQL可能看起来像这样:
有三种方法可以解决这个问题,但我正在寻找更好的方法:
1) 可以通过在客户端执行动态构建的SQL来执行第一个SQL语句。然后,结果可以作为表传递给上述存储过程的修改版本。我熟悉将表数据作为XML传递。如果我这样做,存储过程可以使用静态SQL将数据插入临时表中,而该静态SQL由动态SQL创建,因此可以查询而不会出现问题。 (我也可以研究一下是否可以传递新的Table类型参数,而不是XML。) 然而,我想避免向存储过程传递潜在的大型列表。
2) 我可以从客户端执行所有查询。
第一个方法类似于这样:
简单的两个表情况: 我有两张表。让我们称其为Orders和Items。Order具有OrderId的主键,Items具有ItemId的主键。Items.OrderId是标识父Order的外键。一个Order可以有1到n个项。
我希望能够向用户提供非常灵活的“查询构建器”类型界面,以允许用户选择要查看的项目。筛选条件可以基于Items表和/或父Order表中的字段。如果一个Item符合筛选条件,包括父Order上的条件(如果存在),则该Item应在查询中返回以及父Order。
通常,我认为,大多数人会构建项表和父Order表之间的连接。我想执行2个独立的查询。一个返回所有符合条件的项,另一个返回所有不同的父Order。原因有两个,你可能同意也可能不同意。
第一个原因是,我需要查询父Order表中的所有列,如果我执行单个查询将Orders表与Items表连接起来,我将重复多次Order信息。因为每个订单通常有大量的物品,所以我想避免这种情况,因为这将导致更多的数据传输到fat client上。相反,如上所述,我想在数据集中单独返回两个表,并在其中使用这两个表来填充自定义的Order和child Items客户端对象。(我还不太了解LINQ或Entity Framework。我手动构建我的对象)。第二个原因是我已经有另一个过程,可以返回给定OrderId的所有Items以及父Order,我想使用相同的2表方法,以便我可以重用客户端代码从返回的2个数据表填充我的自定义Order和Client 对象。
我希望能做的是这样的: 在Client上构建一个动态SQL字符串,将orders表连接到Items表,并根据Winform fat-client应用程序上创建的自定义筛选器在每个表上进行适当的筛选。在客户端上构建的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创建的,因此以下两个静态SQL无法访问它。如果我将静态SQL更改为动态SQL,则不会向fat client返回任何结果。有三种方法可以解决这个问题,但我正在寻找更好的方法:
1) 可以通过在客户端执行动态构建的SQL来执行第一个SQL语句。然后,结果可以作为表传递给上述存储过程的修改版本。我熟悉将表数据作为XML传递。如果我这样做,存储过程可以使用静态SQL将数据插入临时表中,而该静态SQL由动态SQL创建,因此可以查询而不会出现问题。 (我也可以研究一下是否可以传递新的Table类型参数,而不是XML。) 然而,我想避免向存储过程传递潜在的大型列表。
2) 我可以从客户端执行所有查询。
第一个方法类似于这样:
SELECT Items.* FROM Orders, Items WHERE Order.OrderId = Items.OrderId AND (dynamic filter)
SELECT Orders.* FROM Orders, Items WHERE Order.OrderId = Items.OrderId AND (dynamic filter)
这仍然使我能够重复使用我的客户端对象填充代码,因为订单和物品继续以两个不同的表格返回。
我感觉我可以在存储过程中使用 Table 数据类型的一些选项,但这对我来说也是新的,如果您能给予一点指导,我将不胜感激。
如果你甚至看到了我写的这么远,我很惊讶,但如果您有任何想法如何最好地完成这个任务,我会非常感激。