【问题标题】:Dynamic SQL, sp_executesql, and rebuilding the dynamic sql statement - Part 2动态 SQL、sp_executesql 和重建动态 sql 语句 - 第 2 部分
【发布时间】:2021-05-22 04:47:59
【问题描述】:

第 2 部分: 在他的文章“T-SQL 中的动态搜索条件...用于 SQL 2005 及更早版本”中,Erland Sommarskog 给出了如何将动态 sql 与 sp_executesql 一起使用的示例。

http://www.sommarskog.se/dyn-search-2005.html#sp_executesql

SELECT @sql =                                                  -- 19
'SELECT o.OrderID, o.OrderDate, od.UnitPrice, od.Quantity,     -- 20
        c.CustomerID, c.CompanyName, c.Address, c.City,        -- 21
        c.Region,  c.PostalCode, c.Country, c.Phone,           -- 22
        p.ProductID, p.ProductName, p.UnitsInStock,            -- 23
        p.UnitsOnOrder                                         -- 24
 FROM   dbo.Orders o                                           -- 25
 JOIN   dbo.[Order Details] od ON o.OrderID = od.OrderID       -- 26
 JOIN   dbo.Customers c ON o.CustomerID = c.CustomerID         -- 27
 JOIN   dbo.Products p ON p.ProductID = od.ProductID           -- 28
     WHERE  1 = 1'                                             -- 29
                                                               -- 30
IF @orderid IS NOT NULL                                        -- 31
   SELECT @sql = @sql + ' AND o.OrderID = @xorderid' +         -- 32
                        ' AND od.OrderID = @xorderid'          -- 33
                                                               -- 34
IF @fromdate IS NOT NULL                                       -- 35
   SELECT @sql = @sql + ' AND o.OrderDate >= @xfromdate'       -- 36

等等……

在另一个关于动态 sql 的 article 中,他写道:

在动态 SQL 中创建的临时表将无法从调用过程中访问,因为它们在动态 SQL 退出时被删除。

所以我的问题围绕着这个问题:如果您已经构建了动态 sql 语句一次,@sql中的SELECT语句返回col1、col2、col3、col4等, 如果您必须以不同的方式重新查询相同的结果集,您应该怎么做?例如,如果您必须返回另一个具有 COUNT 并按 col1 分组的结果集, 另一个结果集包含按 col2 分组的 COUNT,或者其他一些标准,其基础是原始 @sql 的结果集?

您是否必须为每个不同的场景重新构建@sql, 所以你最终得到@sql,@sql_2,@sql_3,...?

在这种情况下,动态 sql 是否仍然是最好的选择,或者它会是 最好使用插入 #temp 表的静态 sql,这样您就可以 重新查询#temp 表结果?

【问题讨论】:

    标签: sql-server tsql


    【解决方案1】:

    好的,下面是来自 msdn 站点的解决此问题的示例。

    http://social.msdn.microsoft.com/Forums/en/sqlreportingservices/thread/3ed6885a-fe18-41c0-bce4-76c44c737a1b

    问题是这样的:如果您创建临时表,并且在动态 sql 内部创建临时表,则您没有机会在动态 sql 外部访问临时表。 但是,如果您首先在动态 sql 之外创建临时表, 然后在动态sql的内部填充临时表,您可以在动态sql的外部访问填充的临时表。

    【讨论】:

    • 不是因为使用了CREATE语句,而是因为临时表是在动态SQL之外创建的
    • @Mitch - 没错。我最初的反应不够清楚。这就是这里的区别:如果您的临时表是在动态 sql 内部创建的,则无法在动态 sql 外部访问它,但是如果您在动态 sql 外部创建临时表,然后将其填充到动态 sql 内部,则可以最后访问动态 sql 之外的填充临时表。
    • 是的,我知道。也许你应该让你的答案更清楚,而不是添加评论......
    【解决方案2】:

    另一种方法是使用INSERT ... EXEC 设备,虽然比您自己发现的使用更有限。

    INSERT INTO sometable    /* or @vartable or #temptable */
    EXEC sp_executesql @sql  /* and @params, if needed */
    

    你不能在一个本身被另一个INSERT...EXEC调用的SP中使用它。

    【讨论】:

      【解决方案3】:

      在 SQL Server 中,如果您在动态 SQL 中创建临时表,则无法在调用过程中从非动态 SQL 访问该临时表。正如你所说。

      你有几个选择:

      • 预先创建临时表(在非动态 sql 中)。然后它可以从动态 sql 中使用,因此您可以插入其中。
      • 如果您不知道临时表结构,那么前面的选项似乎没有太大帮助。但是您可以先使用单个虚拟列创建临时表,然后从动态 sql 修改临时表的结构。看起来有点恶心,但有时很方便。
      • 使用 ## 全局临时表
      • 使用真实表格,可能带有“批次”标识符,以将您的结果与也插入真实表格的其他任何人的结果分开。
      • 使用动态 SQL 来创建/更改一个过程,该过程可以根据需要创建临时表。然后,您可以从非动态 SQL 调用该过程。相当多的工作,但有时很方便。
      • 按照您在问题中的建议,以不同的方式重建动态 sql,并分别执行它们。性能不如您多次处理数据,但通常这并不重要。

      【讨论】:

        猜你喜欢
        • 2010-10-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-09
        • 2013-04-30
        • 1970-01-01
        • 2017-05-18
        相关资源
        最近更新 更多