在声明标量变量中错过了什么

时间:2019-10-09 07:17:14

标签: sql-server tsql

在下面的这段代码中,我有错误消息:

/*Months need to be refreshed*/
DECLARE @Month NVARCHAR(2)
DECLARE @Year NVARCHAR(4)
DECLARE @Row NVARCHAR(1)

SELECT @MONTH=MONTH, @YEAR=YEAR
FROM calendar

select month, year, 1 as row into #period from calendar;

insert into #period (month, year, row)
values (CASE WHEN @MONTH=1 THEN 12 ELSE @MONTH-1 END,CASE WHEN @MONTH=1 THEN @YEAR-1 ELSE @YEAR END,2)

insert into #period (month, year, row)
values (CASE WHEN @MONTH=2 THEN 12 ELSE @MONTH-2 END,CASE WHEN @MONTH=2 THEN @YEAR-1 ELSE @YEAR END,3)

/*Refresh latest month*/
DECLARE @Updstm NVARCHAR(MAX)
DECLARE @Month1 NVARCHAR(MAX)
DECLARE @Month2 VARCHAR(2)
DECLARE @Year1 NVARCHAR(4)
DECLARE @ROW1 VARCHAR(25) 
DECLARE @MAX_ROW1 VARCHAR(25)  

SET @MAX_ROW1=(SELECT MAX([ROW]) FROM #period)
SET @ROW1=1 WHILE @ROW1<=@MAX_ROW1

BEGIN
SELECT @Month1 = N'SELECT @SVMonth2 = SVMonth FROM #period WHERE [ROW]='+@ROW1
EXEC sp_executesql @Month1, N'@Month2 VARCHAR(2) OUTPUT', @Month2 OUTPUT

SET @Updstm= ''
SET @Updstm= '
INSERT INTO #remove
select memberid, '+@Month1+' as month
from member'+@Month1+' where memberid in ("A2019358219",
"A3012467679",
"A5513538670")';

EXECUTE sp_executesql @Updstm

SET @ROW1=@ROW1+1

END

错误消息是:

  

关键字“ SELECT”附近的语法不正确
  必须声明标量变量“ @ Month2”。

我错过了什么?

日历样本数据:

Month | Year
9     | 2019

会员示例数据:

MemberId    | Sales  | Qty
A2019358219 | 166703 | 90
A3012467679 | 170489 | 34
A5513538670 | 38689  | 18

3 个答案:

答案 0 :(得分:1)

您的WHILE循环缺少END:

DECLARE @Updstm NVARCHAR(MAX)
DECLARE @Month1 NVARCHAR(MAX)
DECLARE @Month2 VARCHAR(2)
DECLARE @Year1 NVARCHAR(4)
DECLARE @ROW1 VARCHAR(25) 
DECLARE @MAX_ROW1 VARCHAR(25)  

SET @MAX_ROW1=(SELECT MAX([ROW]) FROM #curr_period)
SET @ROW1=1 WHILE @ROW1<=@MAX_ROW1


BEGIN
    SELECT @Month1 = N'SELECT @Month2 = Month FROM #curr_period WHERE [ROW]=' + @ROW1
    EXEC sp_executesql @Month1, N'@Month2 VARCHAR(2) OUTPUT', @Month2 OUTPUT
END

答案 1 :(得分:1)

好的,下面是一些半工作代码,即正在运行,但是我不知道它是否满足您的要求。

这应该是您发布的任何其他SQL问题的模板,这些问题是您在其中设置数据,尝试查询然后发布预期结果的。 90%的时间您将通过此操作自己解决问题。对于最后10%的用户,您可以轻松地尝试帮助设置和重现该问题。

为了使此代码正常工作,我对必须解决的每个问题都发表了评论。

/* FIRST SETUP TEST DATA TO DEMONSTRATE THE ISSUE*/
create table #remove (id varchar(12), month int)
create table #member1 (memberid varchar(12))
create table #member12 (memberid varchar(12))
create table #calendar (year int, month int)

/* Add enough sample data here to demonstrate the issue */
insert into #calendar (month, year) select 1, 2019;
insert into #member1 (memberid) select 'A5513538670';
insert into #member12 (memberid) select 'A5513538670';

/* NOW FOR THE CODE WHICH DOESN"T YET WORK */

/*Months need to be refreshed*/
DECLARE @Month NVARCHAR(2);
DECLARE @Year NVARCHAR(4);
DECLARE @Row NVARCHAR(1);

SELECT @MONTH=1, @YEAR=2019
FROM #calendar; -- calendar

-- Missing column svmonth as required in the dynamic SQL
--select month, year, 1 as row into #period from (select 1 month, 2019 year) x;
select month, month svmonth, year, 1 as row into #period from #calendar;

-- Missing column svmonth as required in the dynamic SQL
--insert into #period (month, year, row)
--  values (CASE WHEN @MONTH=1 THEN 12 ELSE @MONTH-1 END, CASE WHEN @MONTH=1 THEN @YEAR-1 ELSE @YEAR END,2)
--insert into #period (month, year, row)
--  values (CASE WHEN @MONTH=2 THEN 12 ELSE @MONTH-2 END, CASE WHEN @MONTH=2 THEN @YEAR-1 ELSE @YEAR END,3)
insert into #period (month, svmonth, year, row)
  values (CASE WHEN @MONTH=1 THEN 12 ELSE @MONTH-1 END, CASE WHEN @MONTH=1 THEN 12 ELSE @MONTH-1 END, CASE WHEN @MONTH=1 THEN @YEAR-1 ELSE @YEAR END,2)
-- Can't use with this data because it causes a month of -1 which breaks the last dynamic code
--insert into #period (month, svmonth, year, row)
--  values (CASE WHEN @MONTH=2 THEN 12 ELSE @MONTH-2 END, CASE WHEN @MONTH=2 THEN 12 ELSE @MONTH-2 END, CASE WHEN @MONTH=2 THEN @YEAR-1 ELSE @YEAR END,3)

/* Refresh latest month */
DECLARE @Updstm NVARCHAR(MAX);
DECLARE @Month1 NVARCHAR(MAX);
DECLARE @Month2 VARCHAR(2);
DECLARE @Year1 NVARCHAR(4);
DECLARE @ROW1 VARCHAR(25);
DECLARE @MAX_ROW1 VARCHAR(25);
-- Missing variable
DECLARE @SVMonth2 VARCHAR(2);

SET @MAX_ROW1 = (SELECT MAX([ROW]) FROM #period);
SET @ROW1 = 1;

WHILE @ROW1<=@MAX_ROW1 BEGIN
  SELECT @Month1 = N'SELECT @SVMonth2 = SVMonth FROM #period WHERE [ROW] = ' + @ROW1;

  -- select the dynamic SQL in order to work out what is wrong with it.
  -- select @Month1;

  -- Passed in @Month2 but internally used @SVMonth2
  --EXEC sp_executesql @Month1, N'@Month2 VARCHAR(2) OUTPUT', @Month2 OUTPUT;
  EXEC sp_executesql @Month1, N'@SVMonth2 VARCHAR(2) OUTPUT', @SVMonth2 OUTPUT;

  SET @Updstm= '';
  -- Used @Month1 instead of @SVMonth2, and doubled quoted ID's instead of using 2 single quotes
  --SET @Updstm= '
  --INSERT INTO #remove (id, month)
  --  select memberid, ' + @SVMonth2 + ' as month
  --  from #member' + @SVMonth2 + ' where memberid in ("A2019358219",
  --  "A3012467679",
  --  "A5513538670")';
  SET @Updstm= '
  INSERT INTO #remove (id, month)
    select memberid, ' + @SVMonth2 + ' as month
    from #member' + @SVMonth2 + ' where memberid in (''A2019358219'',
    ''A3012467679'',
    ''A5513538670'')';

  -- select the dynamic SQL in order to work out what is wrong with it.
  --select @Updstm;

  EXECUTE sp_executesql @Updstm;

  SET @ROW1=@ROW1+1;

END

/* CLEAN UP */

drop table #calendar;
drop table #period;
drop table #remove;
drop table #member1;
drop table #member12;

答案 2 :(得分:0)

应该是

EXEC sp_executesql @Month1, N'@Month2 VARCHAR(2) OUTPUT', @SomeProcVar = @Month2 OUTPUT

查看此link