Znam MsSQL, więc nigdy nie przyszło mi do głowy, aby zadać takie pytanie. Odpowiedzi podane tutaj wprowadziły mnie w coś, o czym nie miałem pomysłu !! Dzięki ..
Różnica między zmienną procedury a zmienną zdefiniowaną przez użytkownika specyficzną dla sesji polega na tym, że zmienna procedury jest inicjowana ponownie za NULLkażdym razem, gdy wywoływana jest procedura, podczas gdy zmienna specyficzna dla sesji nie jest:
Jak widać, var2(zmienna procedury) jest ponownie inicjowana za każdym razem, gdy wywoływana jest procedura, podczas gdy @var2(zmienna specyficzna dla sesji) nie jest.
(Oprócz zmiennych zdefiniowanych przez użytkownika, MySQL ma również pewne predefiniowane „zmienne systemowe”, które mogą być „zmiennymi globalnymi”, takimi jak @@global.portlub „zmiennymi sesji”, takimi jak @@session.sql_mode; te „zmienne sesji” nie są powiązane z konkretnymi sesjami zdefiniowanymi przez użytkownika zmienne).
Pamiętaj również, że dostępne są zmienne globalne: patrz SELECT @@version;na przykład. Jest to również powód, dla którego używanie DELIMITER @@nie jest tak naprawdę dobrym pomysłem.
Mchl
13
tworzy nowe pytania o nowe wyniki ... czy jest jakaś różnica między „var = var” a „var: = var” jak w twoim przykładzie?
confiq
13
@confiq: nie ma.
Quassnoi
9
Kolejne pytanie dla nowicjusza. Kiedy zaleca się stosowanie @vs nie?
pixelfreak
73
@confiq, @Quassnoi: istnieje jedna znacząca różnica między :=i =, i to znaczy, że :=działa wszędzie jako operator przypisywania zmiennych, podczas gdy =działa tylko w SETinstrukcjach i jest operatorem porównania wszędzie indziej. Więc SELECT @var = 1 + 1;pozostawi @var bez zmian i zwróci wartość logiczną (1 lub 0 w zależności od bieżącej wartości @var), podczas gdy SELECT @var := 1 + 1;zmieni @var na 2 i zwróci 2.
Poza przechowywanymi programami, variablebez @, jest zmienną systemową , której nie możesz sam zdefiniować.
Zakres tej zmiennej obejmuje całą sesję. Oznacza to, że dopóki istnieje połączenie z bazą danych, zmiennej można nadal używać.
Jest to w przeciwieństwie do MSSQL, w którym zmienna będzie dostępna tylko w bieżącej partii zapytań (procedura składowana, skrypt lub w inny sposób). Nie będzie dostępny w innej partii w tej samej sesji.
@RobM, nazywane są zmiennymi systemowymi , a nie zmiennymi sesyjnymi.
Pacerier
1
@Pacerier: Czy źle czytam dokumenty? „” „Aby wyraźnie wskazać, że zmienna jest zmienną sesyjną, poprzedź jej nazwę SESSION, @@ session. Lub @@.” ””
RobM
5
@RobM, czytasz to źle. Przeczytaj cały akapit, nie tylko akapit w punkcie wypunktowanym. Mówiąc najprościej, istnieją dwa rodzaje zmiennych sesji: 1) Zmienne sesji zdefiniowane przez użytkownika i 2) Zmienne sesji zdefiniowane przez system . Za pomocą nie można ustawić zmiennej sesji zdefiniowanej przez użytkownika @@. Na przykład set@@my_var=1, set@@session.my_var=1i set session my_var=1nie działa, ponieważ my_varnie jest to układ zmienna, podczas gdy możemy zrobić set@@big_tables=1, set@@session.big_tables=1i set session big_tables=1dlatego big_tablesjest zmienna systemowa.
Pacerier
1
@GovindRai: W odpowiedzi Quassnoi var2jest zmienną bez @przedrostka, ale nie jest zmienną systemową: jest zmienną proceduralną. Jest to dozwolone, ponieważ jest to procedura składowana (inaczej program przechowywany). Poza procedurami składowanymi zmienna bez @jest zmienną systemową.
LarsH
10
MSSQL wymaga, aby zmienne w ramach procedur były ZADEKLAROWANE, a ludzie używali składni @Variable (DECLARE @TEXT VARCHAR (25) = 'text'). Ponadto MS pozwala na deklarowanie w dowolnym bloku procedury, w przeciwieństwie do mySQL, który wymaga wszystkich DEKLARACJI na górze.
Chociaż dobrze w wierszu poleceń, uważam, że użycie „set = @variable” w ramach procedur przechowywanych w mySQL jest ryzykowne. Nie ma zasięgu, a zmienne działają ponad granicami zakresu. Jest to podobne do deklarowanych zmiennych w JavaScript bez prefiksu „var”, które są wówczas globalną przestrzenią nazw i tworzą nieoczekiwane kolizje i nadpisania.
Mam nadzieję, że dobrzy ludzie na mySQL pozwolą DECLARE @ Zmienna na różnych poziomach bloków w ramach procedury przechowywanej. Zwróć uwagę na @ (przy znaku). Prefiks @ pomaga oddzielić nazwy zmiennych od nazw kolumn tabeli - ponieważ często są one takie same. Oczywiście zawsze można dodać przedrostek „v” lub „l_”, ale znak @ jest przydatnym i zwięzłym sposobem, aby nazwa zmiennej pasowała do kolumny, z której można wyodrębnić dane bez blokowania jej.
MySQL jest nowy w procedurach przechowywanych i wykonał dobrą robotę dla swojej pierwszej wersji. Przyjemnością będzie zobaczenie, jak się tutaj przyjmują i obserwowanie dojrzałych aspektów serwera po stronie serwera.
Zasadniczo używam UserDefinedVariables (poprzedzone @) w ramach procedur przechowywanych. Ułatwia to życie, szczególnie gdy potrzebuję tych zmiennych w dwóch lub więcej procedur przechowywanych. Właśnie wtedy, gdy potrzebuję zmiennej tylko w JEDNEJ Procedurze Przechowywanej, używam Zmiennej Systemowej (bez poprzedzającego @).
@Xybo: Nie rozumiem, dlaczego używanie @variables w StoredProcedures powinno być ryzykowne. Czy mógłbyś wyjaśnić nieco „zakres” i „granice” (dla mnie jako nowicjusza)?
Narusza to podstawowe zasady inżynierii oprogramowania. Nie pisz innego wiersza kodu, dopóki nie dowiesz się dokładnie, jaki jest zakres, i dlaczego używanie zmiennych globalnych jest ogólnie okropnym pomysłem. Kiedy wziąłem 101 lekcji programowania, jak pamiętam, użycie globalnego dla prawie wszystkiego skutkowałoby automatycznym „F”. Istnieją specjalne wyjątki, ale z reguły - po prostu nie rób tego!
BuvinJ
Dlaczego? - @ Zmienne są absolutnie powszechne w każdej książce MySQL.
Peter
Jasne, w „płaskim” skrypcie bez wywołań funkcji, procedur, wyzwalaczy itp., A jeśli zamierzasz po prostu wykonać ten prosty skrypt lub ograniczony zestaw poleceń, a następnie zakończyć sesję (niszcząc w ten sposób globały). W takim przypadku skorzystaj z nich, jeśli chcesz. Ale NIE używaj ich wewnątrz funkcji! Jeśli po prostu zmienne globalne lub zakres Google są od razu dostępne, natychmiast znajdziesz szerokie poparcie dla idei, że są one powszechnie odrzucane. Oto punkt wyjścia: wiki.c2.com/?GlobalVariablesAreBad lub w celu uzyskania bardziej ogólnego wyjaśnienia: en.wikipedia.org/wiki/Global_variable
BuvinJ
2
W MySQL @variables są globalne. Łatwo to potwierdzić. Ustaw jedną poza funkcją, a następnie oceń ją w jednej. I odwrotnie, ustaw jedną wewnątrz funkcji i oceń ją poza nią. Zobaczysz, że funkcja nie chroni zakresu takich. Stają na sobie nawzajem.
BuvinJ
1
Używając terminologii MySQL, @@GLOBALzmienne są jeszcze bardziej „globalne” i podstępne. Przechodzą przez sesje! @variablesmają „zakres sesji”, więc przynajmniej pozostają w ten sposób ograniczone. Jednak w każdym normalnym języku, który określa się mianem zakresu „globalnego” (gdy przekraczają funkcje itp.). Pojęcie „globalne” w MySQL należy chyba nazwać „uniwersalnym”, ponieważ wykracza ono poza granice procesu, w którym jest uruchomiony. „Globalny” zwykle nie może tego zrobić w standardowym języku, ponieważ procesy nie współużytkują przestrzeni pamięci. Wynika to z trwałej (niestabilnej) tendencji SQL.
Odpowiedzi:
MySQL
ma pojęcie zmiennych zdefiniowanych przez użytkownika .Są to zmienne o luźnym typie, które mogą być inicjowane gdzieś w sesji i zachowują swoją wartość aż do końca sesji.
Są one poprzedzone
@
znakiem:@var
Możesz zainicjalizować tę zmienną za pomocą
SET
instrukcji lub wewnątrz zapytania:Po opracowaniu procedury składowanej w
MySQL
można przekazać parametry wejściowe i zadeklarować zmienne lokalne:Te zmienne nie są poprzedzone żadnymi prefiksami.
Różnica między zmienną procedury a zmienną zdefiniowaną przez użytkownika specyficzną dla sesji polega na tym, że zmienna procedury jest inicjowana ponownie za
NULL
każdym razem, gdy wywoływana jest procedura, podczas gdy zmienna specyficzna dla sesji nie jest:Jak widać,
var2
(zmienna procedury) jest ponownie inicjowana za każdym razem, gdy wywoływana jest procedura, podczas gdy@var2
(zmienna specyficzna dla sesji) nie jest.(Oprócz zmiennych zdefiniowanych przez użytkownika, MySQL ma również pewne predefiniowane „zmienne systemowe”, które mogą być „zmiennymi globalnymi”, takimi jak
@@global.port
lub „zmiennymi sesji”, takimi jak@@session.sql_mode
; te „zmienne sesji” nie są powiązane z konkretnymi sesjami zdefiniowanymi przez użytkownika zmienne).źródło
SELECT @@version;
na przykład. Jest to również powód, dla którego używanieDELIMITER @@
nie jest tak naprawdę dobrym pomysłem.@
vs nie?:=
i=
, i to znaczy, że:=
działa wszędzie jako operator przypisywania zmiennych, podczas gdy=
działa tylko wSET
instrukcjach i jest operatorem porównania wszędzie indziej. WięcSELECT @var = 1 + 1;
pozostawi @var bez zmian i zwróci wartość logiczną (1 lub 0 w zależności od bieżącej wartości @var), podczas gdySELECT @var := 1 + 1;
zmieni @var na 2 i zwróci 2.W MySQL
@variable
wskazuje zmienną zdefiniowaną przez użytkownika . Możesz zdefiniować własne.Poza przechowywanymi programami,
variable
bez@
, jest zmienną systemową , której nie możesz sam zdefiniować.Zakres tej zmiennej obejmuje całą sesję. Oznacza to, że dopóki istnieje połączenie z bazą danych, zmiennej można nadal używać.
Jest to w przeciwieństwie do MSSQL, w którym zmienna będzie dostępna tylko w bieżącej partii zapytań (procedura składowana, skrypt lub w inny sposób). Nie będzie dostępny w innej partii w tej samej sesji.
źródło
SET @@a = 'test';
, por. dev.mysql.com/doc/refman/5.1/en/set-statement.html@@
. Na przykładset@@my_var=1
,set@@session.my_var=1
iset session my_var=1
nie działa, ponieważmy_var
nie jest to układ zmienna, podczas gdy możemy zrobićset@@big_tables=1
,set@@session.big_tables=1
iset session big_tables=1
dlategobig_tables
jest zmienna systemowa.var2
jest zmienną bez@
przedrostka, ale nie jest zmienną systemową: jest zmienną proceduralną. Jest to dozwolone, ponieważ jest to procedura składowana (inaczej program przechowywany). Poza procedurami składowanymi zmienna bez@
jest zmienną systemową.MSSQL wymaga, aby zmienne w ramach procedur były ZADEKLAROWANE, a ludzie używali składni @Variable (DECLARE @TEXT VARCHAR (25) = 'text'). Ponadto MS pozwala na deklarowanie w dowolnym bloku procedury, w przeciwieństwie do mySQL, który wymaga wszystkich DEKLARACJI na górze.
Chociaż dobrze w wierszu poleceń, uważam, że użycie „set = @variable” w ramach procedur przechowywanych w mySQL jest ryzykowne. Nie ma zasięgu, a zmienne działają ponad granicami zakresu. Jest to podobne do deklarowanych zmiennych w JavaScript bez prefiksu „var”, które są wówczas globalną przestrzenią nazw i tworzą nieoczekiwane kolizje i nadpisania.
Mam nadzieję, że dobrzy ludzie na mySQL pozwolą DECLARE @ Zmienna na różnych poziomach bloków w ramach procedury przechowywanej. Zwróć uwagę na @ (przy znaku). Prefiks @ pomaga oddzielić nazwy zmiennych od nazw kolumn tabeli - ponieważ często są one takie same. Oczywiście zawsze można dodać przedrostek „v” lub „l_”, ale znak @ jest przydatnym i zwięzłym sposobem, aby nazwa zmiennej pasowała do kolumny, z której można wyodrębnić dane bez blokowania jej.
MySQL jest nowy w procedurach przechowywanych i wykonał dobrą robotę dla swojej pierwszej wersji. Przyjemnością będzie zobaczenie, jak się tutaj przyjmują i obserwowanie dojrzałych aspektów serwera po stronie serwera.
źródło
Zasadniczo używam UserDefinedVariables (poprzedzone @) w ramach procedur przechowywanych. Ułatwia to życie, szczególnie gdy potrzebuję tych zmiennych w dwóch lub więcej procedur przechowywanych. Właśnie wtedy, gdy potrzebuję zmiennej tylko w JEDNEJ Procedurze Przechowywanej, używam Zmiennej Systemowej (bez poprzedzającego @).
@Xybo: Nie rozumiem, dlaczego używanie @variables w StoredProcedures powinno być ryzykowne. Czy mógłbyś wyjaśnić nieco „zakres” i „granice” (dla mnie jako nowicjusza)?
źródło
@@GLOBAL
zmienne są jeszcze bardziej „globalne” i podstępne. Przechodzą przez sesje!@variables
mają „zakres sesji”, więc przynajmniej pozostają w ten sposób ograniczone. Jednak w każdym normalnym języku, który określa się mianem zakresu „globalnego” (gdy przekraczają funkcje itp.). Pojęcie „globalne” w MySQL należy chyba nazwać „uniwersalnym”, ponieważ wykracza ono poza granice procesu, w którym jest uruchomiony. „Globalny” zwykle nie może tego zrobić w standardowym języku, ponieważ procesy nie współużytkują przestrzeni pamięci. Wynika to z trwałej (niestabilnej) tendencji SQL.