MySQL: @variable vs. variabel. Apa bedanya?

501

Dalam pertanyaan lain saya memposting seseorang mengatakan kepada saya bahwa ada perbedaan antara:

@variable

dan:

variable

di MySQL. Dia juga menyebutkan bagaimana MSSQL memiliki lingkup batch dan MySQL memiliki ruang lingkup sesi. Bisakah seseorang menjelaskan hal ini untuk saya?

aarona
sumber
1
Saya kenal dengan MSSQL dan karena itu tidak pernah terpikir oleh saya untuk mengajukan pertanyaan seperti itu. Jawaban yang diberikan di sini memberi saya petunjuk tentang sesuatu yang tidak saya miliki tentang IDE !! Terima kasih ..
Ken

Jawaban:

624

MySQLmemiliki konsep variabel yang ditentukan pengguna .

Mereka adalah variabel yang diketik secara longgar yang dapat diinisialisasi di suatu tempat dalam suatu sesi dan mempertahankan nilainya sampai sesi berakhir.

Mereka diawali dengan @tanda, seperti ini:@var

Anda dapat menginisialisasi variabel ini dengan SETpernyataan atau di dalam kueri:

SET @var = 1

SELECT @var2 := 2

Saat Anda mengembangkan prosedur tersimpan MySQL, Anda dapat meneruskan parameter input dan mendeklarasikan variabel lokal:

DELIMITER //

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

DELIMITER ;

Variabel-variabel ini tidak diawali dengan awalan.

Perbedaan antara variabel prosedur dan variabel yang ditentukan pengguna khusus sesi adalah variabel prosedur diinisialisasi ulang untuk NULLsetiap kali prosedur dipanggil, sedangkan variabel khusus sesi tidak:

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

Seperti yang Anda lihat, var2(variabel prosedur) diinisialisasi ulang setiap kali prosedur dipanggil, sementara@var2 (variabel khusus sesi) tidak.

(Selain variabel yang ditentukan pengguna, MySQL juga memiliki beberapa "variabel sistem" yang telah ditentukan, yang mungkin "variabel global" seperti @@global.portatau "variabel sesi" seperti @@session.sql_mode; "variabel sesi" ini tidak terkait dengan sesi yang ditentukan pengguna yang ditentukan pengguna variabel.)

Quassnoi
sumber
43
Perhatikan juga, bahwa ada variabel global yang tersedia: Lihat SELECT @@version;misalnya. Ini juga alasan, mengapa menggunakan DELIMITER @@bukanlah ide yang bagus.
Mchl
13
itu membuat pertanyaan baru untuk pendapatan ... apakah ada perbedaan antara "var = var" dan "var: = var" seperti dalam contoh Anda?
confiq
13
@confiq: tidak ada.
Quassnoi
10
Pertanyaan lain untuk pendatang baru. Kapan disarankan untuk menggunakan @vs tidak?
pixelfreak
73
@confiq, @Quassnoi: ada satu perbedaan signifikan antara :=dan =, dan itu :=berfungsi sebagai operator penugasan variabel di mana saja, sementara =hanya bekerja seperti itu dalam SETpernyataan, dan merupakan operator perbandingan di mana pun. Jadi SELECT @var = 1 + 1;akan meninggalkan @var tidak berubah dan mengembalikan boolean (1 atau 0 tergantung pada nilai saat ini dari @var), sementara SELECT @var := 1 + 1;akan mengubah @var ke 2, dan mengembalikan 2.
Dewi Morgan
71

Di MySQL, @variablemenunjukkan variabel yang ditentukan pengguna . Anda bisa menentukan sendiri.

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

Di luar program yang disimpan, a variable, tanpa @, adalah variabel sistem , yang tidak dapat Anda tentukan sendiri.

Cakupan variabel ini adalah seluruh sesi. Itu berarti bahwa sementara koneksi Anda dengan database ada, variabel masih dapat digunakan.

Ini berbeda dengan MSSQL, di mana variabel hanya akan tersedia dalam kumpulan kueri saat ini (prosedur tersimpan, skrip, atau sebaliknya). Itu tidak akan tersedia dalam batch yang berbeda di sesi yang sama.

Molf
sumber
2
Jangan bingung dengan variabel sesi, yang memiliki singkatan SET @@a = 'test';, lih. dev.mysql.com/doc/refman/5.1/en/set-statement.html
RobM
@ RhM, Mereka disebut variabel sistem , bukan variabel sesi.
Pacerier
1
@Pacerier: Apakah saya salah membaca dokumen? "" "Untuk menunjukkan secara eksplisit bahwa suatu variabel adalah variabel sesi, mendahului namanya dengan SESSION, @@ session., Atau @@." ""
RobM
5
@RobM, Anda salah membaca. Bacalah seluruh paragraf, bukan hanya paragraf di dalam poin. Sederhananya, ada dua jenis variabel sesi: 1) variabel sesi yang ditentukan pengguna, dan 2)  variabel sesi yang ditentukan sistem . Anda tidak dapat mengatur variabel sesi yang ditentukan pengguna dengan menggunakan @@. Sebagai contoh, set@@my_var=1, set@@session.my_var=1, dan set session my_var=1tidak akan bekerja karena my_varbukan sistem variabel, sedangkan kita bisa melakukan set@@big_tables=1, set@@session.big_tables=1dan set session big_tables=1karena big_tablesmerupakan variabel sistem.
Pacerier
1
@GovindRai: Dalam jawaban Quassnoi, var2adalah variabel tanpa @awalan, tetapi itu bukan variabel sistem: itu adalah variabel prosedur. Ini diperbolehkan karena itu dalam prosedur tersimpan (alias program tersimpan). Di luar prosedur tersimpan, variabel tanpa @adalah variabel sistem.
LarsH
10

MSSQL mensyaratkan bahwa variabel dalam prosedur menjadi DECLAREd dan orang-orang menggunakan sintaks @Variable (DECLARE @TEXT VARCHAR (25) = 'teks'). Juga, MS memungkinkan untuk mendeklarasikan dalam blok apa pun dalam prosedur, tidak seperti mySQL yang membutuhkan semua DECLARE di bagian atas.

Meskipun bagus di baris perintah, saya merasa menggunakan "set = @variable" di dalam prosedur tersimpan di mySQL berisiko. Tidak ada ruang lingkup dan variabel hidup melintasi batas ruang lingkup. Ini mirip dengan variabel dalam JavaScript yang dideklarasikan tanpa awalan "var", yang kemudian menjadi namespace global dan membuat tabrakan dan menimpa yang tidak terduga.

Saya berharap orang-orang baik di mySQL akan memungkinkan DECLARE @Variable di berbagai level blok dalam prosedur tersimpan. Perhatikan @ (pada tanda). Awalan tanda @ membantu memisahkan nama variabel dari nama kolom tabel - karena sering sama. Tentu saja, seseorang selalu dapat menambahkan awalan "v" atau "l_", tetapi tanda @ adalah cara yang praktis dan ringkas untuk memiliki nama variabel yang cocok dengan kolom tempat Anda mengekstraksi data dari tanpa mengkliknya.

MySQL baru untuk prosedur tersimpan dan mereka telah melakukan pekerjaan dengan baik untuk versi pertama mereka. Akan menyenangkan untuk melihat di mana mereka mengambilnya di sini dan untuk menonton aspek sisi server dari bahasa matang.

Xybo
sumber
3

Pada prinsipnya, saya menggunakan UserDefinedVariables (diawali dengan @) dalam Stored Procedures. Ini membuat hidup lebih mudah, terutama ketika saya membutuhkan variabel-variabel ini dalam dua atau lebih Prosedur Tersimpan. Hanya ketika saya membutuhkan variabel hanya dalam SATU Prosedur Tersimpan, daripada saya menggunakan System Variable (tanpa prepended @).

@Xybo: Saya tidak mengerti mengapa menggunakan @variables di StoredProcedures harus berisiko. Bisakah Anda jelaskan "ruang lingkup" dan "batas" sedikit lebih mudah (bagi saya sebagai newbe)?

Peter
sumber
3
Ini melanggar prinsip-prinsip rekayasa perangkat lunak dasar. Tolong jangan menulis baris anther kode sampai Anda tahu persis apa ruang lingkup, dan mengapa menggunakan variabel global umumnya adalah ide yang mengerikan. Ketika saya mengambil 101 kelas pemrograman, karena saya ingat menggunakan global untuk hampir semua hal akan menghasilkan "F" otomatis. Ada pengecualian khusus, tetapi sebagai aturan umum - jangan lakukan itu!
BuvinJ
Mengapa? --Variabel benar-benar umum di setiap Buku-MySQL.
Peter
Tentu, dalam skrip "datar" tanpa pemanggilan fungsi, prosedur, pemicu, dll. Dan jika Anda hanya akan mengeksekusi skrip sederhana itu, atau serangkaian perintah terbatas dan kemudian mengakhiri sesi (dengan demikian menghancurkan global Anda). Jika demikian, silakan dan gunakan jika Anda mau. Tapi JANGAN menggunakannya di dalam fungsi! Jika Anda hanya Google variabel global atau ruang lingkup Anda akan langsung menemukan dukungan luas untuk gagasan bahwa mereka disukai secara universal. Inilah titik awalnya: wiki.c2.com/?GlobalVariablesAreBad atau untuk penjelasan yang lebih umum: en.wikipedia.org/wiki/Global_variable
BuvinJ
2
Di MySQL, @variables bersifat global. Ini mudah dikonfirmasi. Tetapkan satu di luar fungsi dan kemudian evaluasilah di dalamnya. Sebaliknya, atur satu di dalam fungsi dan evaluasilah di luarnya. Anda akan melihat fungsi tersebut tidak melindungi ruang lingkup tersebut. Mereka saling menginjak kaki.
BuvinJ
1
Menggunakan terminologi MySQL, @@GLOBALvariabel bahkan lebih "global" dan berbahaya. Mereka melewati sesi! @variablesmemiliki "ruang lingkup sesi", jadi setidaknya mereka tetap terkurung dengan cara itu. Namun, dalam bahasa normal apa pun yang Anda sebut ruang lingkup "global" (ketika fungsi tersebut melintas dll). Konsep MySQL "global" mungkin harus disebut "universal", karena ia melampaui batas proses yang menjalankannya. "Global" biasanya tidak bisa melakukan itu dalam bahasa standar, karena proses tidak berbagi ruang memori. Ini berasal dari kecenderungan SQL yang persisten (volatile).
BuvinJ