Как объявить массив внутри хранимой процедуры MS SQL Server?

85

Мне нужно объявить 12 десятичных переменных, соответствующих году каждого месяца, курсором я суммирую значения этих переменных, а затем обновляю некоторую информацию о продажах.

Я не знаю, есть ли у sql server такой синтаксис

 Declare MonthsSale(1 to 12) as decimal(18,2)

Этот код работает нормально. !

CREATE PROCEDURE [dbo].[proc_test]
AS
BEGIN

--SET NOCOUNT ON;

DECLARE @monthsales TABLE ( monthnr int,    amount decimal(18,2)    )


-- PUT YOUR OWN CODE HERE


-- THIS IS TEST CODE
-- 1 REPRESENTS JANUARY, ...
INSERT @monthsales (monthnr, amount) VALUES (1, 100)
INSERT @monthsales (monthnr, amount) VALUES (1, 100)

INSERT @monthsales (monthnr, amount) VALUES (2, 200)
INSERT @monthsales (monthnr, amount) VALUES (3, 300)
INSERT @monthsales (monthnr, amount) VALUES (4, 400)
INSERT @monthsales (monthnr, amount) VALUES (5, 500)
INSERT @monthsales (monthnr, amount) VALUES (6, 600)
INSERT @monthsales (monthnr, amount) VALUES (7, 700)
INSERT @monthsales (monthnr, amount) VALUES (8, 800)
INSERT @monthsales (monthnr, amount) VALUES (9, 900)
INSERT @monthsales (monthnr, amount) VALUES (10, 1000)
INSERT @monthsales (monthnr, amount) VALUES (11, 1100)
INSERT @monthsales (monthnr, amount) VALUES (12, 1200)


SELECT monthnr, SUM(amount) AS SUM_MONTH_1 FROM @monthsales WHERE monthnr = 1 GROUP BY monthnr
SELECT monthnr, SUM(amount) AS SUM_MONTH_2 FROM @monthsales WHERE monthnr = 2 GROUP BY monthnr
SELECT monthnr, SUM(amount) AS SUM_MONTH_3 FROM @monthsales WHERE monthnr = 3 GROUP BY monthnr
SELECT monthnr, SUM(amount) AS SUM_MONTH_4 FROM @monthsales WHERE monthnr = 4 GROUP BY monthnr
SELECT monthnr, SUM(amount) AS SUM_MONTH_5 FROM @monthsales WHERE monthnr = 5 GROUP BY monthnr
SELECT monthnr, SUM(amount) AS SUM_MONTH_6 FROM @monthsales WHERE monthnr = 6 GROUP BY monthnr
SELECT monthnr, SUM(amount) AS SUM_MONTH_7 FROM @monthsales WHERE monthnr = 7 GROUP BY monthnr
SELECT monthnr, SUM(amount) AS SUM_MONTH_8 FROM @monthsales WHERE monthnr = 8 GROUP BY monthnr
SELECT monthnr, SUM(amount) AS SUM_MONTH_9 FROM @monthsales WHERE monthnr = 9 GROUP BY monthnr
SELECT monthnr, SUM(amount) AS SUM_MONTH_10 FROM @monthsales WHERE monthnr = 10 GROUP BY monthnr
SELECT monthnr, SUM(amount) AS SUM_MONTH_11 FROM @monthsales WHERE monthnr = 11 GROUP BY monthnr
SELECT monthnr, SUM(amount) AS SUM_MONTH_12 FROM @monthsales WHERE monthnr = 12 GROUP BY monthnr

-- END TEST CODE
END
РикардоБальда
источник

Ответы:

143

Вы можете объявить табличную переменную (объявление переменной типа table):

declare @MonthsSale table(monthnr int)
insert into @MonthsSale (monthnr) values (1)
insert into @MonthsSale (monthnr) values (2)
....

Вы можете добавлять дополнительные столбцы по своему усмотрению:

declare @MonthsSale table(monthnr int, totalsales tinyint)

Вы можете обновить переменную таблицы, как и любую другую таблицу:

update m
set m.TotalSales = sum(s.SalesValue)
from @MonthsSale m
left join Sales s on month(s.SalesDt) = m.MonthNr
Андомар
источник
26

Есть ли причина, по которой вы не используете табличную переменную и агрегатный оператор SUM вместо курсора? SQL отлично справляется с операциями, ориентированными на наборы. В 99,87% случаев, когда вы используете курсор, есть более эффективная альтернатива, ориентированная на набор:

declare @MonthsSale table
(
MonthNumber int,
MonthName varchar(9),
MonthSale decimal(18,2)
)

insert into @MonthsSale
select
    1, 'January', 100.00
union select    
    2, 'February', 200.00
union select    
    3, 'March', 300.00
union select    
    4, 'April', 400.00
union select    
    5, 'May', 500.00
union select    
    6, 'June', 600.00
union select    
    7, 'July', 700.00
union select    
    8, 'August', 800.00
union select    
    9, 'September', 900.00
union select    
    10, 'October', 1000.00
union select    
    11, 'November', 1100.00
union select    
    12, 'December', 1200.00

select * from @MonthsSale   
select SUM(MonthSale) as [TotalSales] from @MonthsSale
Пол Смит
источник
12
Видимо, в MSSQL2012 теперь можно вставлять в таком формате: ЗНАЧЕНИЯ (1, 'Январь', 100.00), (2, 'Февраль', 200.00) - источник: blog.sqlauthority.com/2012/10/27/…
andrewb
3
Эта функция полностью ускользнула от моего внимания; очевидно, что это работает и в SQL 2008.
Пол Смит
8

T-SQL не поддерживает массивы, о которых я знаю.

Какая у вас структура таблицы? Вероятно, вы могли бы разработать запрос, который делает это вместо этого:

select
month,
sum(sales)
from sales_table
group by month
order by month
Патрик Берлесон
источник
Только в качестве дополнительного комментария я хотел бы отметить, что синтаксис T [n] .v немного более сжат, чем (выберите v из T, где Ti = n). На самом деле, это намного короче. Я бы очень хотел, чтобы T-SQL добавил это.
участник дебатов
3

Отличный вопрос и отличная идея, но в SQL вам нужно сделать это:

Для типа данных datetime примерно так:

declare @BeginDate    datetime = '1/1/2016',
        @EndDate      datetime = '12/1/2016'
create table #months (dates datetime)
declare @var datetime = @BeginDate
   while @var < dateadd(MONTH, +1, @EndDate)
   Begin
          insert into #months Values(@var)
          set @var = Dateadd(MONTH, +1, @var)
   end

Если все, что вам действительно нужно, это числа, сделайте следующее -

create table #numbas (digit int)
declare @var int = 1        --your starting digit
    while @var <= 12        --your ending digit
    begin
        insert into #numbas Values(@var)
        set @var = @var +1
    end
Датчанин Томас
источник