动态SQL问题

时间:2012-11-30 14:22:14

标签: sql-server-2008 dynamic-sql

我有一个动态SQL,它位于存储过程中,但是当我运行存储过程时,我没有看到任何结果。这很奇怪,因为当我从字符串中删除SQL时,只需将其作为SQL查询运行,我就会得到结果。我已经尝试将Dynamic SQL打印出来,这样我就可以看到发生了什么,但这也不起作用。因此,我不知道自己做错了什么,并且会问是否有人可以看到什么是错的。以下是查询:

SELECT @SQL = @SQL + 'Select Production_Site, CSN, Target, Action, Fail '
SELECT @SQL = @SQL + 'From syn_products prod, '
SELECT @SQL = @SQL + '(select Production_Site, CSN, SUM([Target]) AS Target,SUM([Action]) AS Action,SUM([Fail]) AS Fail '
SELECT @SQL = @SQL + ' from '
SELECT @SQL = @SQL + ' ( '
SELECT @SQL = @SQL + ' select Production_Site, value, Period, YEAR, week, CSN '
SELECT @SQL = @SQL + ' from t_Pqe_Grocery '
SELECT @SQL = @SQL + ' unpivot ( '
SELECT @SQL = @SQL + ' value '
SELECT @SQL = @SQL + ' for col in (Grocery_Packaging_And_Coding, Grocery_Measurable, '
SELECT @SQL = @SQL + ' Grocery_Appearance, Grocery_Aroma, '
SELECT @SQL = @SQL + ' Grocery_Flavour, Grocery_Texture)) unp '
SELECT @SQL = @SQL + ' ) src '
SELECT @SQL = @SQL + ' pivot '
SELECT @SQL = @SQL + ' ( '
SELECT @SQL = @SQL + ' count(value) '
SELECT @SQL = @SQL + ' for value in ([Target], [Action], [Fail]) '
SELECT @SQL = @SQL + ' ) piv '
SELECT @SQL = @SQL + ' where Production_Site IN ( ''' + @Site + ''') AND YEAR BETWEEN ' + CONVERT(varchar(50),CONVERT(BIGINT,@ToYear))+ 'AND '+ CONVERT(varchar(50),CONVERT(BIGINT,@FromYear))+ 'AND Period BETWEEN ' + CONVERT(varchar(50),CONVERT(BIGINT,@ToPeriod))+ ' AND '+ CONVERT(varchar(50),CONVERT(BIGINT,@FromPeriod))+ 'AND Week BETWEEN ' + CONVERT(varchar(50),CONVERT(BIGINT,@ToWeek))+ ' AND '+CONVERT(varchar(50),CONVERT(BIGINT,@FromWeek))+ ' GROUP BY Production_Site CSN'
SELECT @SQL = @SQL + ' ) pit'
SELECT @SQL = @SQL + ' WHERE prod.pProductCode = pit.CSN AND prod.pPowerBrand = ''POW'''
EXECUTE(@SQL)

3 个答案:

答案 0 :(得分:1)

有时,以不同方式格式化查询有助于查找查询中的任何错误。您在查询字符串中缺少一些空格:

declare @sql varchar(max)
declare @Site varchar(10) = 'testSite'
declare @ToYear int = 2010
declare @FromYear int = 2012
declare @ToPeriod int = 45
declare @FromPeriod int = 56
declare @ToWeek int = 10
declare @FromWeek  int = 1

SET @SQL =
 'Select Production_Site, CSN, Target, Action, Fail 
  From syn_products prod
  inner join 
  (
    select Production_Site, CSN, SUM([Target]) AS Target,SUM([Action]) AS Action,SUM([Fail]) AS Fail 
    from 
    ( 
      select Production_Site, value, Period, YEAR, week, CSN 
      from t_Pqe_Grocery 
      unpivot 
      ( 
        value 
        for col in (Grocery_Packaging_And_Coding, 
                    Grocery_Measurable, Grocery_Appearance, 
                    Grocery_Aroma, Grocery_Flavour, Grocery_Texture)
      ) unp 
    ) src 
    pivot
    ( 
      count(value)
      for value in ([Target], [Action], [Fail])
    ) piv 
    where Production_Site IN ( ''' + @Site + ''') 
      AND YEAR BETWEEN ' + CONVERT(varchar(50),CONVERT(BIGINT,@ToYear))+ ' AND '+ CONVERT(varchar(50),CONVERT(BIGINT,@FromYear))
      + ' AND Period BETWEEN ' + CONVERT(varchar(50),CONVERT(BIGINT,@ToPeriod))+ ' AND '+ CONVERT(varchar(50),CONVERT(BIGINT,@FromPeriod)) 
      + ' AND Week BETWEEN ' + CONVERT(varchar(50),CONVERT(BIGINT,@ToWeek))+ ' AND '+CONVERT(varchar(50),CONVERT(BIGINT,@FromWeek))
    + ' GROUP BY Production_Site CSN
  ) pit
     on prod.pProductCode = pit.CSN 
  where prod.pPowerBrand = ''POW'''

select @sql

现在打印---请参阅SQL Fiddle with Demo - 我还将查询更改为使用ANSI连接语法而不是逗号分隔连接。

答案 1 :(得分:0)

这些可能是语法错误:

... CONVERT(BIGINT,@ToYear))+ 'AND '+ ...
                               ^--- no space

... @FromYear))+ 'AND Period BETWEEN ...
                  ^---no space

... @FromPeriod))+ 'AND Week BETWEEN
                    ^-- yet again no space

答案 2 :(得分:0)

您的一个变量可能是NULL。将NULL值连接到字符串将导致NULL字符串。在给出PRINT字符串时,EXECUTENULL都可以。

首先,您需要将@SQL参数设置为空字符串,或更改第一行以设置值而不是连接它。然后,您可能需要进行某种检查以验证参数是否为NULL,如果是,则删除条件或替换其他内容:

DECLARE @SQL VARCHAR(MAX)
SELECT @SQL = ''
SELECT @SQL = @SQL + ... -- now build the SQL Statement
SELECT @SQL = @SQL + ' where Production_Site IN ( ''' + ISNULL(@Site, '') + ''' ... -- check for NULLs here

PRINT ISNULL(@SQL, 'NULL) -- this should now print something even if the SQL is NULL

最后,小心SQL注入攻击!避免将参数连接到像这样的动态SQL语句中。而是参数化动态SQL,并将参数与EXECUTE语句一起传递。