编译错误 - 动态SQL

时间:2014-09-19 10:34:55

标签: sql-server ssms dynamic-sql

我尝试实现一些动态SQL来创建游标作为简单SELECT查询的扩展。游标用作在SQL Server Management Studio中打印从SELECT返回的GROUPED值作为消息的方式(类似于数据的可视摘要)。这种方法的目的是半任务相关,一半有助于我理解如何开发动态SQL。代码如下:

DECLARE @Focus VARCHAR(10);
SET @Focus = 'Completed'; /* User input event focus {Started, Completed} */
DECLARE @PeriodStartDate DATE, @PeriodEndDate DATE;
SET @PeriodStartDate = '04/01/2014';
SET @PeriodEndDate = GETDATE();
DECLARE @sql VARCHAR(MAX);
SET @sql = 
        'SELECT ' +
        'CASE DATEPART(M, ' + '[Event ' + CASE @Focus
                                                WHEN 'Started' THEN 'Start'
                                                WHEN 'Completed' THEN 'End'
                                                END + ' Date]) ' +
        ' WHEN 1 THEN ''January'' ' +
        ' WHEN 2 THEN ''February'' ' +
        ' WHEN 3 THEN ''March'' ' + 
        ' WHEN 4 THEN ''April'' ' +
        ' WHEN 5 THEN ''May'' ' +
        ' WHEN 6 THEN ''June'' ' +
        ' WHEN 7 THEN ''July'' ' +
        ' WHEN 8 THEN ''August'' ' +
        ' WHEN 9 THEN ''September'' ' +
        ' WHEN 10 THEN ''October'' ' +
        ' WHEN 11 THEN ''November'' ' +
        ' WHEN 12 THEN ''December'' ' +
        ' END AS [Event ' + @Focus + ' Month], ' +
        ' COUNT([Unique ID]) AS [Number of Events] ' +
        ' FROM [udf_Events](' + @Focus + ', ' + CAST(@PeriodStartDate AS VARCHAR) + ', ' + CAST(@PeriodEndDate AS VARCHAR) + ') ' +
        ' GROUP BY ' +
        ' DATEPART(M, ' + '[Event ' + CASE @Focus 
                                            WHEN 'Started' THEN 'Start' 
                                            WHEN 'Completed' THEN 'End'
                                            END + ' Date]) ' +
        ' ORDER BY ' +
        ' DATEPART(M, ' + '[Event ' + CASE @Focus
                                            WHEN 'Started' THEN 'Start'
                                            WHEN 'Completed' THEN 'End'
                                            END + ' Date]) '
;                                               
DECLARE Results CURSOR
FOR
    SELECT
        @sql;

我收到的错误讯息:

  

Msg 16924,Level 16,State 1,Line 71 Cursorfetch:Number of   在INTO列表中声明的变量必须与所选变量匹配   列。

通过使用EXEC(@sql)解决问题并尝试以SELECT语句执行查询(消除游标的复杂性),错误消息显示为:

  

无效的列名称“已完成”。

..这让我相信问题在于所选择的第一个字段中的CASE表达式。 udf_Events是一个带有三个参数的内联表值函数。除此之外,它还有[事件开始日期]和[事件结束日期]列,它们是光标在其上工作的值。

2 个答案:

答案 0 :(得分:0)

尝试此操作...查询中缺少'

DECLARE @Focus VARCHAR(10);
SET @Focus = 'Completed'; /* User input event focus {Started, Completed} */

DECLARE @temp VARCHAR(500);
IF(@Focus = 'Completed')
SET @temp = '[Event End Date]'
ELSE
SET @temp = '[Event Start Date]'

DECLARE @PeriodStartDate DATE, @PeriodEndDate DATE;
SET @PeriodStartDate = '04/01/2014';
SET @PeriodEndDate = GETDATE();
DECLARE @sql VARCHAR(MAX);
SET @sql = 
        'SELECT ' +
        'CASE DATEPART(M, ' + @temp  + ')' +
        ' WHEN 1 THEN ''January'' ' +
        ' WHEN 2 THEN ''February'' ' +
        ' WHEN 3 THEN ''March'' ' + 
        ' WHEN 4 THEN ''April'' ' +
        ' WHEN 5 THEN ''May'' ' +
        ' WHEN 6 THEN ''June'' ' +
        ' WHEN 7 THEN ''July'' ' +
        ' WHEN 8 THEN ''August'' ' +
        ' WHEN 9 THEN ''September'' ' +
        ' WHEN 10 THEN ''October'' ' +
        ' WHEN 11 THEN ''November'' ' +
        ' WHEN 12 THEN ''December'' ' +
        ' END AS [Event ' + @Focus + ' Month], ' +
        ' COUNT([Unique ID]) AS [Number of Events] ' +
        ' FROM [udf_Events](''' + @Focus + ''', ''' + CAST(@PeriodStartDate AS VARCHAR) + ''', ''' + CAST(@PeriodEndDate AS VARCHAR) + ''') ' +
        ' GROUP BY ' +
        ' DATEPART(M, ' + @temp + ')' +
        ' ORDER BY ' +
        ' DATEPART(M, ' + @temp + ')';                   

print    @sql

答案 1 :(得分:0)

您没有引用udf_Events来电中的日期,因此您最终会

[udf_Events](Completed, 2014-04-01, 2014-09-19)

而不是

[udf_Events](Completed, '2014-04-01', '2014-09-19')

修复方法是更改​​行

' FROM [udf_Events](' + @Focus + ', ' + CAST(@PeriodStartDate AS VARCHAR) + ', ' + CAST(@PeriodEndDate AS VARCHAR) + ') ' +

' FROM [udf_Events](' + @Focus + ', ''' + CAST(@PeriodStartDate AS VARCHAR) + ''', ''' + CAST(@PeriodEndDate AS VARCHAR) + ''') ' +

也就是说,如果udf_Events的参数为datetimes,那么我会考虑将格式更改为YYYYMMDD,因为这是明确的。为此,您可以使用CONVERT(char(8), <date>, 112),其中<date>是要转换的日期。

即:

' FROM [udf_Events](' + @Focus + ', ''' + CONVERT(char(8), @PeriodStartDate, 112) + ''', ''' + CONVERT(char(8), @PeriodEndDate, 112) + ''') ' +