MySQL: @variable vs. variabile. Qual è la differenza?


501

In un'altra domanda che ho pubblicato qualcuno mi ha detto che c'è una differenza tra:

@variable

e:

variable

in MySQL. Ha anche menzionato come MSSQL abbia un ambito batch e MySQL abbia un ambito sessione. Qualcuno può approfondire questo per me?


1
Conosco MsSQL e quindi il pensiero non mi è mai venuto in mente di porre una domanda del genere. Le risposte fornite qui mi hanno dato un'idea di qualcosa di cui non avevo IDEA !! Grazie ..
Ken

Risposte:


624

MySQLha il concetto di variabili definite dall'utente .

Sono variabili tipicamente vaghe che possono essere inizializzate da qualche parte in una sessione e mantengono il loro valore fino al termine della sessione.

Sono preceduti da un @segno, come questo:@var

È possibile inizializzare questa variabile con SETun'istruzione o all'interno di una query:

SET @var = 1

SELECT @var2 := 2

Quando si sviluppa una stored procedure in MySQL, è possibile passare i parametri di input e dichiarare le variabili locali:

DELIMITER //

CREATE PROCEDURE prc_test (var INT)
BEGIN
    DECLARE  var2 INT;
    SET var2 = 1;
    SELECT  var2;
END;
//

DELIMITER ;

Queste variabili non sono anteposte a nessun prefisso.

La differenza tra una variabile di procedura e una variabile definita dall'utente specifica della sessione è che la variabile della procedura viene reinizializzata NULLogni volta che viene chiamata la procedura, mentre la variabile specifica della sessione non è:

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

Come puoi vedere, var2(variabile di procedura) viene reinizializzata ogni volta che viene chiamata la procedura, mentre @var2(variabile specifica della sessione) non lo è.

(Oltre alle variabili definite dall'utente, MySQL ha anche alcune "variabili di sistema" predefinite, che possono essere "variabili globali" come @@global.porto "variabili di sessione" come @@session.sql_mode; queste "variabili di sessione" non sono correlate a determinate dall'utente definite dalla sessione variabili.)


43
Si noti inoltre che sono disponibili variabili globali: vedere SELECT @@version;ad esempio. Questo è anche un motivo, perché l'utilizzo DELIMITER @@non è davvero una buona idea.
Mchl

13
fa nuove domande per i nuovi risultati ... c'è qualche differenza tra "var = var" e "var: = var" come nel tuo esempio?
confiq

13
@confiq: non ce n'è.
Quassnoi,

10
Un'altra domanda per un nuovo arrivato. Quando si consiglia di utilizzare @vs no?
pixelfreak,

73
@confiq, @Quassnoi: esiste una differenza significativa tra :=e =, ed è che :=funziona da operatore di assegnazione di variabili ovunque, mentre =funziona solo in questo modo nelle SETdichiarazioni, ed è un operatore di confronto ovunque. Quindi SELECT @var = 1 + 1;lascerà invariato @var e restituirà un valore booleano (1 o 0 a seconda del valore corrente di @var), mentre SELECT @var := 1 + 1;cambierà @var in 2 e restituirà 2.
Dewi Morgan

71

In MySQL, @variableindica una variabile definita dall'utente . Puoi definire il tuo.

SET @a = 'test';
SELECT @a;

Al di fuori dei programmi memorizzati, a variable, senza @, è una variabile di sistema , che non è possibile definire.

Lo scopo di questa variabile è l'intera sessione. Ciò significa che mentre esiste la connessione con il database, la variabile può ancora essere utilizzata.

Ciò è in contrasto con MSSQL, in cui la variabile sarà disponibile solo nel batch corrente di query (stored procedure, script o altro). Non sarà disponibile in un batch diverso nella stessa sessione.


2
Non essere confuso con le variabili di sessione, che hanno la scorciatoia SET @@a = 'test';, cfr. dev.mysql.com/doc/refman/5.1/en/set-statement.html
RobM

@RobM, sono chiamati variabili di sistema , non variabili di sessione.
Pacerier,

1
@Pacerier: sto leggendo i documenti sbagliati? "" "Per indicare esplicitamente che una variabile è una variabile di sessione, precede il nome con SESSION, @@ session. O @@." ""
RobM

5
@RobM, lo stai leggendo in modo errato. Leggi l'intero paragrafo, non solo il paragrafo all'interno del punto elenco. In poche parole, ci sono due tipi di variabili di sessione: 1) Variabili di sessione definite dall'utente e 2) Variabili di sessione definite dal sistema  . Non è possibile impostare una variabile di sessione definita dall'utente utilizzando @@. Ad esempio, set@@my_var=1, set@@session.my_var=1, e set session my_var=1non avrebbe funzionato perché my_varnon è un sistema di variabili, mentre noi possiamo fare set@@big_tables=1, set@@session.big_tables=1e set session big_tables=1perché big_tablesè una variabile di sistema.
Pacerier,

1
@GovindRai: nella risposta di Quassnoi, var2è una variabile senza @prefisso, ma non è una variabile di sistema: è una variabile di procedura. Ciò è consentito perché si trova in una procedura memorizzata (ovvero programma memorizzato). Al di fuori delle stored procedure, una variabile senza @è una variabile di sistema.
LarsH,

10

MSSQL richiede che le variabili all'interno delle procedure siano DECLAREd e che la gente usi la sintassi @Variable (DECLARE @TEXT VARCHAR (25) = 'text'). Inoltre, MS consente di dichiarare all'interno di qualsiasi blocco della procedura, a differenza di mySQL che richiede tutti i DICHIARAZIONI in alto.

Benché buono sulla riga di comando, sento che usare "set = @variable" all'interno delle procedure memorizzate in mySQL è rischioso. Non esiste alcun ambito e le variabili vivono oltre i limiti dell'ambito. Ciò è simile alle variabili in JavaScript dichiarate senza il prefisso "var", che sono quindi lo spazio dei nomi globale e creano collisioni e sovrascritture impreviste.

Spero che le brave persone di mySQL consentiranno a DECLARE @Variable di vari livelli di blocco all'interno di una procedura memorizzata. Nota @ (al segno). Il prefisso @ sign aiuta a separare i nomi delle variabili dai nomi delle colonne della tabella, poiché spesso sono uguali. Ovviamente, si può sempre aggiungere un prefisso "v" o "l_", ma il segno @ è un modo pratico e conciso per far corrispondere il nome della variabile alla colonna dalla quale si potrebbero estrarre i dati senza bloccarlo.

MySQL è nuovo alle procedure memorizzate e hanno fatto un buon lavoro per la loro prima versione. Sarà un piacere vedere dove prendono forma qui e guardare maturare gli aspetti lato server della lingua.


3

In linea di principio, utilizzo UserDefinedVariables (anteposto a @) all'interno di Stored Procedures. Questo semplifica la vita, specialmente quando ho bisogno di queste variabili in due o più Stored procedure. Proprio quando ho bisogno di una variabile solo all'interno di UNA stored procedure, utilizzo una variabile di sistema (senza anteposta a @).

@Xybo: non capisco perché usare @variables in StoredProcedures dovrebbe essere rischioso. Potresti spiegare "scope" e "confini" un po 'più facilmente (per me come newbe)?


3
Ciò viola i principi di base dell'ingegneria del software. Si prega di non scrivere un'altra riga di codice fino a quando non si conosce esattamente quale sia l'ambito e perché l'utilizzo dell'utilizzo di variabili globali sia generalmente un'idea terribile. Quando ho preso 101 lezioni di programmazione, poiché ricordo che usare un globale praticamente per qualsiasi cosa si tradurrebbe in una "F" automatica. Ci sono eccezioni speciali, ma come regola generale - non farlo!
BuvinJ,

Perché? - Le variabili @ sono assolutamente comuni in ogni libro MySQL.
Peter,

Certo, in uno script "piatto" senza chiamate di funzione, procedure, trigger, ecc. E se hai intenzione di eseguire quel semplice script o un set limitato di comandi e quindi terminare la sessione (distruggendo così i tuoi globali). In tal caso, vai avanti e usali se vuoi. Ma NON usarli all'interno di una funzione! Se semplicemente variabili o ambito globali di Google troverai immediatamente un vasto supporto per l'idea che siano universalmente disapprovati. Ecco un punto di partenza: wiki.c2.com/?GlobalVariablesAreBad o per una spiegazione più generale: en.wikipedia.org/wiki/Global_variable
BuvinJ

2
In MySQL, @variables è globale. Questo è facilmente confermato. Impostare uno al di fuori di una funzione e quindi valutarlo all'interno di una. Al contrario, impostane uno all'interno di una funzione e valutalo al di fuori di essa. Vedrai che la funzione non protegge l'ambito di tale. Si calpestano l'un l'altro.
BuvinJ,

1
Utilizzando la terminologia MySQL, le @@GLOBALvariabili sono ancora più "globali" e insidiose. Incrociano le sessioni! @variableshanno "ambito di sessione", quindi almeno rimangono confinati in quel modo. In qualsiasi linguaggio normale è quello che tu chiami ambito "globale" (quando incrociano le funzioni, ecc.). Il concetto MySQL di "globale" dovrebbe forse essere chiamato "universale", in quanto si estende oltre i confini del processo che lo esegue. Un "globale" normalmente non può farlo in un linguaggio standard, poiché i processi non condividono lo spazio di memoria. Ciò deriva dalla tendenza persistente (vs volatile) di SQL.
BuvinJ,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.