SET vs SELECT when setting variables
Fivi Panopoulou - Sotiris Karras
Tuesday 20 September 2016
Στην T-SQL υπάρχουν δύο τρόποι με τους οποίους μπορεί κανείς να θέσει μια μεταβλητή. Ο πρώτος είναι με το SET και ο δεύτερος είναι με την χρήση του select statement. Και οι δύο τρόποι χρησιμοποιούνται ευρέως, σε ποια σημεία όμως διαφέρουν μεταξύ τους; Σε αυτό το post θα δούμε δύο σημαντικά σημεία στα οποία διαφοροποιούνται.
Η πρώτη διαφορά εντοπίζεται όταν θέλουμε να θέσουμε μια μεταβλητή με βάση το αποτέλεσμα ενός query το οποίο μπορεί να μας επιστρέψει περισσότερες από μια γραμμές. Για παράδειγμα στην Northwind το παρακάτω query μας επιστρέφει 8 διαφορετικά id.
SELECT ProductID
FROM Products
WHERE Discontinued = 1;
Αν εμείς θεωρήσουμε λανθασμένα ότι αυτό θα επέστρεφε μόνο ένα id και το χρησιμοποιήσουμε για να θέσουμε μια μεταβλητή ας δούμε τι θα γίνει για κάθε έναν από τους δύο τρόπους.
-- 1) setting the variable with SET
DECLARE @Pid INT;
SET @Pid = (SELECT ProductID
FROM Products
WHERE Discontinued = 1);
SELECT @Pid;
GO
----------------------------------------
-- 2) setting the variable with SELECT
DECLARE @Pid INT;
SELECT @Pid = ProductID
FROM Products
WHERE Discontinued = 1;
SELECT @Pid;
GO
Στην πρώτη περίπτωση ο SQL Server θα καταλάβει ότι έπρεπε το query να επιστρέφει μόνο ένα αποτέλεσμα και ότι υπάρχει λάθος, επιστρέφοντάς μας το κατάλληλο error:
"Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression."
Στην δεύτερη περίπτωση το query θα τρέξει χωρίς κανένα μήνυμα σφάλματος και η μεταβλητή @Pid θα λάβει την τελευταία τιμή του result set. Στην περίπτωσή μας επέστρεψε 53, αλλά θα πρέπει να τονιστεί ότι δεν υπάρχει καμία εγγύηση για το ποια θα είναι η τελευταία τιμή και άρα ποιο θα είναι τελικά η τιμή της μεταβλητής.
Η δεύτερη διαφορά εντοπίζεται όταν το query δεν επιστρέφει αποτελέσματα. Για παράδειγμα στην northwind το παρακάτω query μας επιστρέφει κενό result set.
SELECT ProductID
FROM Products
WHERE CategoryID = 9;
Ας πάμε λοιπόν να θέσουμε μια μεταβλητή @Pid με καθέναν από τους δύο τρόπους που αναφέρθηκαν, όπως φαίνεται παρακάτω.
-- 1) setting the variable with SET
DECLARE @Pid INT = 0;
SET @PID = (SELECT ProductID
FROM Products
WHERE CategoryID = 9);
SELECT @Pid;
GO
----------------------------------------
-- 2) setting the variable with SELECT
DECLARE @Pid INT = 0;
SELECT @Pid = ProductID
FROM Products
WHERE CategoryID = 9;
SELECT @Pid;
GO
Στην πρώτη περίπτωση το αποτέλεσμα θα είναι NULL, δείχνοντάς μας ότι δεν υπήρχε το id που θέλαμε. Στην δεύτερη περίπτωση δεν θα γίνει καμία ανάθεση και το @Pid θα συνεχίσει να έχει την τιμή που έχει πριν, δηλαδή 0.