W innym pytaniu, które napisałem, ktoś powiedział mi, że istnieje różnica między:
@variable
i:
variable
w MySQL. Wspomniał także o tym, jak MSSQL ma zakres wsadowy, a MySQL ma zakres sesji. Czy ktoś może mi to rozwinąć?
W innym pytaniu, które napisałem, ktoś powiedział mi, że istnieje różnica między:
@variable
i:
variable
w MySQL. Wspomniał także o tym, jak MSSQL ma zakres wsadowy, a MySQL ma zakres sesji. Czy ktoś może mi to rozwinąć?
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:
SET @var = 1
SELECT @var2 := 2
Po opracowaniu procedury składowanej w MySQL
można przekazać parametry wejściowe i zadeklarować zmienne lokalne:
DELIMITER //
CREATE PROCEDURE prc_test (var INT)
BEGIN
DECLARE var2 INT;
SET var2 = 1;
SELECT var2;
END;
//
DELIMITER ;
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:
CREATE PROCEDURE prc_test ()
BEGIN
DECLARE var2 INT DEFAULT 1;
SET var2 = var2 + 1;
SET @var2 = @var2 + 1;
SELECT var2, @var2;
END;
SET @var2 = 1;
CALL prc_test();
var2 @var2
--- ---
2 2
CALL prc_test();
var2 @var2
--- ---
2 3
CALL prc_test();
var2 @var2
--- ---
2 4
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).
SELECT @@version;
na przykład. Jest to również powód, dla którego używanie DELIMITER @@
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 w SET
instrukcjach 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.
W MySQL @variable
wskazuje zmienną zdefiniowaną przez użytkownika . Możesz zdefiniować własne.
SET @a = 'test';
SELECT @a;
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.
SET @@a = 'test';
, por. dev.mysql.com/doc/refman/5.1/en/set-statement.html
@@
. Na przykład set@@my_var=1
, set@@session.my_var=1
i set 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
i set session big_tables=1
dlatego big_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.
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)?
@@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.