【问题标题】:Execute Dynamic Query in a Loop in SQL在 SQL 中循环执行动态查询
【发布时间】:2016-02-26 08:46:27
【问题描述】:

我正在尝试在 SQL/PDW 的 while 循环内执行动态查询。此查询将为我提供最大/最小日期以及事实表中日期的不同计数。我需要为我的数据库中的所有模式执行此操作(所有模式都具有相同的表结构)。我尝试执行的查询如下:

DECLARE @intCNT INT
SET @intCNT = 1
DECLARE @strSQL1 VARCHAR(1000)
DECLARE @strSQL2 VARCHAR(1000)
DECLARE @strSQL3 VARCHAR(100)


SET @strSQL1 = 'SELECT MAX(FT_DT) AS MAX_DT, 
                    MIN(FT_DT) AS MIN_DT,  
                    COUNT(DISTINCT FT_DT) AS DT_CNT 
                FROM '

SET @strSQL2 = CONCAT('(SELECT TABLE_SCHEMA
                        FROM 
                            (SELECT ROW_NUMBER() OVER(ORDER BY TABLE_SCHEMA) AS ROW_NUM, 
                                TABLE_SCHEMA
                            FROM INFORMATION_SCHEMA.TABLES
                            WHERE TABLE_NAME = ''FT_TBL''
                                AND TABLE_SCHEMA LIKE ''F%'')T
                        WHERE ROW_NUM = ',@intCNT,')' )

SET @strSQL3 = '.FT_TBL'

EXEC (@strSQL1 + @strSQL2 + @strSQL3)

执行此操作时,出现以下错误:

Msg 102, Level 15, State 1, Line 11
Incorrect syntax near '.'.

这与语法有关吗?我想让这个在我的 PDW 实例上工作。我也在 SQL Server 中尝试过,但得到了同样的错误

【问题讨论】:

  • 不确定第三部分在做什么,您需要执行 strSQL2,然后将其作为表名添加到 strSQL1,这将使您的查询为 select * from "name generated from subquery result"。
  • 使用动态 sql 的一个重要工具是 PRINT 语句。打印您尝试执行的 sql 字符串,通常语法错误会很明显。
  • 对于所有模式,我需要的是“从 .FT_TBL 中选择 ----”。我需要在执行结束时将完整的结果集保存在一个表中。
  • strSQL2 不应是动态查询。如果您运行它并将strSQL1TABLE_SCHEMA 连接起来,您最终将获得包含所有表格的完整脚本。在strSQL2 运行一次之后。
  • 当然没有 row_number 和 @intcnt。在这种情况下这将是无用的。

标签: sql sql-server parallel-data-warehouse


【解决方案1】:

您的代码可以用带有以下查询的游标替换,以便您为每个架构进行选择

DECLARE @Schema_Name VarChar

DECLARE MY_CURSOR CURSOR 
  LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR 
SELECT DISTINCT TABLE_SCHEMA
FROM TABLE_SCHEMA
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'FT_TBL'
AND TABLE_SCHEMA LIKE 'F%'

OPEN MY_CURSOR
FETCH NEXT FROM MY_CURSOR INTO @Schema_Name 
WHILE @@FETCH_STATUS = 0
BEGIN 
    --Do something with Id here
    execute CONCAT(CONCAT('SELECT MAX(FT_DT) AS MAX_DT, 
                MIN(FT_DT) AS MIN_DT,  
                COUNT(DISTINCT FT_DT) AS DT_CNT 
            FROM ',@Schema_Name),'FT_TBL')
    FETCH NEXT FROM MY_CURSOR INTO @Schema_Name
END
CLOSE MY_CURSOR
DEALLOCATE MY_CURSOR

【讨论】:

  • 非常感谢您的回复。我在并行数据仓库中,不支持游标:(
  • 虽然我希望它对你有用,即使只是作为了解要寻找什么的基础。
  • 我发现并行你必须使用表作为队列而不是游标rusanu.com/2010/03/26/using-tables-as-queues
【解决方案2】:

你真正想要执行的是:

SELECT MAX(FT_DT) AS MAX_DT, 
                    MIN(FT_DT) AS MIN_DT,  
                    COUNT(DISTINCT FT_DT) AS DT_CNT 
                FROM 
(SELECT TABLE_SCHEMA
                        FROM 
                            (SELECT ROW_NUMBER() OVER(ORDER BY TABLE_SCHEMA) AS ROW_NUM, 
                                TABLE_SCHEMA
                            FROM INFORMATION_SCHEMA.TABLES
                            WHERE TABLE_NAME = 'FT_TBL'
                                AND TABLE_SCHEMA LIKE 'F%')T
                        WHERE ROW_NUM = 1)
.FT_TBL

@strSQL3 中的 .FT_TBL 会破坏您的查询。也许应该是

set @strSQL3 = ' FT_TBL'

【讨论】:

  • 什么解析错误?,如果是 '' 我已修复它,但我无法真正测试它
  • 谢谢。我应该在这里使用动态 sql 吗?当我执行您的选择语句(没有任何变量)时,我得到:Msg 103010, Level 16, State 1, Line 1 Parse error at line: 14, column: 1: Incorrect syntax near '.'.
  • 我写的语句是你执行的,不是你执行的。下面我已经写了如何纠正这个问题,删除“。”根据您的查询
猜你喜欢
  • 1970-01-01
  • 2015-02-07
  • 1970-01-01
  • 2014-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多