【问题标题】:Debugging dynamic sql + dynamic tables in MS SQL Server 2008在 MS SQL Server 2008 中调试动态 sql + 动态表
【发布时间】:2010-03-19 03:02:56
【问题描述】:

我有一个使用动态 sql 的杂乱存储过程。

我可以在运行时通过添加print @sql; 来调试它,其中@sql; 是包含动态SQL 的字符串,就在我调用execute (@sql); 之前。

现在,多页存储过程还创建动态表并在查询中使用它们。我想在执行execute 之前将这些表打印到控制台,以便我确切地知道查询要做什么。

但是,SQL Server 08 不喜欢这样。当我尝试时:

print #temp_table; 并尝试编译 S.P。我收到此错误:


在此上下文中不允许使用名称“#temp_table”。有效表达式是常量、常量表达式和(在某些情况下)变量。不允许使用列名。


请帮忙。

编辑:

说到 SQL,我是个菜鸟。但是,以下语句:select * from #tbl; 在非交互运行时不会向控制台打印任何内容;打印语句虽然有效。

以下语句的语法不正确:print select * from #tbl;。如果 stdout 不是一个选项,我有没有办法将 select 的输出重定向到文件?

谢谢。

【问题讨论】:

    标签: debugging sql-server-2008 dynamic-sql dynamic-tables


    【解决方案1】:

    当我们使用动态 SQl 时,我们首先在 sp 中有一个调试输入变量(将其设为最后一个并给它一个默认值 0(表示不在调试模式下,这样就不会破坏现有的代码调用过程)。

    现在,当您在调试模式下运行它时,您打印而不是执行,或者您打印并执行但最后总是回滚。如果需要查看各个阶段的数据,最好的做法是第二种。然后在回滚之前,将要查看的数据放入表变量中(这很重要,它不能是临时表)。回滚后,从表变量中选择(回滚时没有超出范围)并运行 print tstatments 以查看已运行的查询。

    【讨论】:

      【解决方案2】:

      以这种方式调试,您将获得输出的唯一方法是

      select * from #temp_table;
      

      或者,查看 SQL Server Management Studio 中内置的调试功能。例如,此网页可能会对您有所帮助

      SQL Server Performance . com

      【讨论】:

      • 那会打印到控制台吗?如果这是我正在执行的唯一语句,它会这样做。事实上,我只是试了一下——它不打印任何东西。 print @sql; 声明虽然有效。
      • 一个 SP 将输出每个不去别处的选择,例如作为插入或@variable 更新的一部分
      • @CResults,您能详细说明一下吗?我不确定我是否理解这条评论。
      • 例如 create proc MyProc as Select * from MyTable;从 MyTable 中选择 *; SP 将向您输出两个记录集。 print @sql 将工作,因为 @sql 是一个字符串。 #temp_table 不是,它是一个记录集。
      • @CResults:动态sql有问题。它返回: Msg 4104, Level 16, State 1, Line 1 无法绑定多部分标识符“X.Y”。我正在尝试调试一个令人讨厌的连接。这是一个 Catch-22 - proc 需要正确执行才能调试它:) 我需要在 400 行 SQL 中做一个小修复,所以要去掉导致错误的部分并使用二进制文件并不容易搜索/分而治之。真正有用的是能够将表格转换为字符串并打印出来。
      【解决方案3】:

      您可以打印变量,但不能打印表格。但是,您可以从 #table 中选择。

      现在,如果在执行的单个语句中创建、填充和修改表,那么您可以查看表的状态,就像它在 修改之前一样,但数据将从那以后发生了变化。

      当然,一旦动态 sql 完成,#table 就不再可用,所以你被卡住了!

      为了解决这个问题,您可以在动态 SQL 中与 #table 一起插入 ##Table(注意双井号),然后在动态 sql 执行结束时查询该 ##table。

      【讨论】:

      • @Raj,它其实是静态sql和动态sql的混合体,所以动态表是在使用它的动态sql一起patch之前创建的。我的问题仍然是:如何将该选择的结果打印到控制台、文件等?
      • @Hamish,如果您执行 SELECT 将打印到控制台。
      【解决方案4】:

      尽管我讨厌游标,但试试这个:

      SET NOCOUNT ON
      CREATE TABLE #TempTable1
      (ColumnInt      int        
      ,ColumnVarchar  varchar(50)
      ,ColumnDatetime datetime   
      )
      INSERT INTO #TempTable1 VALUES (1,'A',GETDATE())
      INSERT INTO #TempTable1 VALUES (12345,'abcdefghijklmnop','1/1/2010')
      INSERT INTO #TempTable1 VALUES (null,null,null)
      INSERT INTO #TempTable1 VALUES (445454,null,getdate())
      SET NOCOUNT OFF
      
      DECLARE @F_ColumnInt      int
             ,@F_ColumnVarchar  varchar(50)
             ,@F_ColumnDatetime datetime
      
      DECLARE CursorTempTable1 CURSOR FOR
          SELECT
              ColumnInt, ColumnVarchar, ColumnDatetime
          FROM #TempTable1
          ORDER BY ColumnInt
          FOR READ ONLY
      
      --populate and allocate resources to the cursor
      OPEN CursorTempTable1
      
      PRINT '#TempTable1 contents:'
      PRINT '    '+REPLICATE('-',20)
             +'  '+REPLICATE('-',50)
             +'  '+REPLICATE('-',23)
      
      --process each row
      WHILE 1=1
      BEGIN
      
          FETCH NEXT FROM CursorTempTable1
              INTO @F_ColumnInt, @F_ColumnVarchar, @F_ColumnDatetime
      
          --finished fetching all rows?
          IF @@FETCH_STATUS <> 0
          BEGIN --YES, all done fetching
              --exith the loop
              BREAK
          END --IF finished fetching
      
          PRINT '    '+RIGHT(   REPLICATE(' ',20)   +   COALESCE(CONVERT(varchar(20),@F_ColumnInt),'null')                               ,20)
                 +'  '+LEFT(                            COALESCE(@F_ColumnVarchar,'null')                        +   REPLICATE(' ',50)   ,50)
                 +'  '+LEFT(                            COALESCE(CONVERT(char(23),@F_ColumnDatetime,121),'null') +   REPLICATE(' ',23)   ,23)
      
      END --WHILE
      
      --close and free the cursor's resources
      CLOSE CursorTempTable1
      DEALLOCATE CursorTempTable1
      

      输出:

      #TempTable1 contents:
      --------------------  --------------------------------------------------  -----------------------
                      null  null                                                null                   
                         1  A                                                   2010-03-18 13:28:24.260
                     12345  abcdefghijklmnop                                    2010-01-01 00:00:00.000
                    445454  null                                                2010-03-18 13:28:24.260
      

      如果我知道您的临时表有 PK,我会给出一个无光标循环示例。

      【讨论】:

      • @KM,如果您要创建光标,最好创建一个#Cursor
      • @Raj 更多,如果我知道有问题的表的 PK 结构,我可以编写一个无游标循环,如下所示:stackoverflow.com/questions/2478908/… 但这个游标足够通用,可以让 OP 获得代码工作。什么是#Cursor
      • @KM #cursor 就像一个#temp 表。仅适用于当前连接。
      猜你喜欢
      • 2011-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-26
      • 2012-08-11
      • 2014-03-30
      • 2013-07-22
      • 1970-01-01
      相关资源
      最近更新 更多