Jak zadeklarować tablicę wewnątrz procedury składowanej MS SQL Server?

85

Muszę zadeklarować 12 zmiennych dziesiętnych, odpowiadających rokowi każdego miesiąca, za pomocą kursora sumuję wartości tych zmiennych, a następnie aktualizuję niektóre informacje o sprzedaży.

Nie wiem, czy serwer sql ma taką składnię

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

Ten kod działa OK. !

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
RicardoBalda
źródło

Odpowiedzi:

143

Możesz zadeklarować zmienną tabelaryczną (Deklarowanie zmiennej typu table):

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

Możesz dodać dodatkowe kolumny, jak chcesz:

declare @MonthsSale table(monthnr int, totalsales tinyint)

Możesz zaktualizować zmienną tabeli jak każdą inną tabelę:

update m
set m.TotalSales = sum(s.SalesValue)
from @MonthsSale m
left join Sales s on month(s.SalesDt) = m.MonthNr
Andomar
źródło
26

Czy jest jakiś powód, dla którego zamiast kursora nie używasz zmiennej tabeli i zagregowanego operatora SUMA? SQL wyróżnia się w operacjach zorientowanych na zestaw. W 99,87% przypadków, gdy używasz kursora, istnieje bardziej wydajna zorientowana na zestaw alternatywa:

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
Paul Smith
źródło
12
Najwyraźniej w MSSQL2012 można teraz wstawiać w tym formacie: WARTOŚCI (1, 'styczeń', 100.00), (2, 'luty', 200.00) - źródło: blog.sqlauthority.com/2012/10/27/…
andrewb
3
Ta funkcja całkowicie umknęła mojej uwadze; najwyraźniej działa to również w SQL 2008.
Paul Smith
8

T-SQL nie obsługuje tablic, o których wiem.

Jaka jest struktura Twojego stołu? Prawdopodobnie możesz zaprojektować zapytanie, które zrobi to:

select
month,
sum(sales)
from sales_table
group by month
order by month
Patrick Burleson
źródło
Tylko na marginesie, chciałbym zauważyć, że składnia T [n] .v jest nieco bardziej zwięzła niż (wybierz v z T, gdzie Ti = n). Właściwie jest o wiele bardziej zwięzły. Bardzo chciałbym zobaczyć, jak T-SQL to dodaje.
debata
3

Świetne pytanie i świetny pomysł, ale w SQL musisz to zrobić:

Dla typu danych typu datetime, coś takiego:

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

Jeśli naprawdę chcesz tylko liczb, zrób to-

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
Dane Thomas
źródło