go backarticles

Articles of SQLschool.gr Team

The GOTO statement in SQL Server

Antonios Chatzipavlis

Overview

Το να γράψω το συγκεκριμένο άρθρο ήταν μια προσωπική πρόκληση. Είμαι σίγουρος ότι θα υπάρξουν αντιδράσεις μιας και το GOTO statement έχει εξοβελιστεί στο πυρ το εξώτερον. Όμως δεν έχω καμία διάθεση ή πρόθεση να μπω σε αυτές.

Προσωπικά δεν θεωρώ το GOTO statement κακή πρακτική στο να χρησιμοποιηθεί, αρκεί αυτή να είναι σωστή.

Σαν προγραμματιστής δεν θεωρώ κακό κανένα statement αλλά διαφωνώ στην μη σωστή χρήση του.

Δεν θα κάνω ιστορική αναδρομή ούτε θα τονίσω το πόσο κακό μπορεί να κάνει η λανθασμένη χρήση του GOTO γιατί αυτά είναι γνωστά και μπορεί εύκολα ο καθένας να τα βρει στην εποχή του internet.

Σε αυτό το άρθρο θέλω να δείξω το πως μπορεί το GOTO να χρησιμοποιηθεί σωστά στο T-SQL code που γράφουμε ώστε να επιτύχουμε την "καθαρότητα" του κώδικα μας στην εκτέλεση και κυρίως στην ανάγνωση του.

Επίσης να επισημάνω ότι μιλάω μόνο για T-SQL code και σε καμία περίπτωση δεν κάνω αναγωγή σε γλώσσες προγραμματισμού καθώς εκεί έχουμε αρκετές δυνατότητες που δεν υπάρχουν στην SQL language για την αποφυγή της χρήσης του. Τέλος να αναφέρω ότι σε καμία περίπτωση δεν εγκρίνω την χρήση του που οδηγεί σε spaghetti code.

Existing usage in system stored procedures

Αν κοιτάξουμε με το παρακάτω query στα system object θα βρούμε πάνω από 250 stored procedures που περιέχουν GOTO και αν με την sp_helptext δούμε το κώδικα κάποιων από αυτές θα βρούμε αρκετά patterns που δείχνουν την χρήση του.

SQL Script

select object_schema_name(object_id) as [schema_name], object_name(object_id) as [object_name]
from sys.system_sql_modules 
where definition like '%goto%'

Τα περισσότερα από αυτά έχουν να κάνουν με error trapping και transactions. Για να προλάβω αντιδράσεις να πω ότι αρκετές από αυτές είναι γραμμένες πριν την υποστήριξη του begin try/catch στο SQL Server.

Possible use cases

Γενικότερα θα δείτε και άλλα patterns που είναι χρήσιμα όμως θα εστιάσω σε δύο από αυτά καθώς κάνουν την ζωή μας ευκολότερη τόσο στην ανάγνωση όσο και στην συντήρηση του κώδικα που γράφουμε σε stored procedures, trigger κ.λ.π.

Avoid code repeat

Μια χρήση είναι για την αποφυγή επανάληψης του ίδιου κώδικα όπως στο παράδειγμα.

SQL Script

create procedure pname @p1 int
as
begin

    ... -- a lot of code lines 

    if ( @p1 = x )
    begin
        goto samecode;
    end

    if ( @p1 = y )
    begin
        goto samecode;
    end

    goto exitsp

    samecode:
    ... -- code

    exitsp:
    ... -- safe exit
    return
end
go

Για να προλάβω πάλι τις αντιδράσεις που λένε να βάλω αυτό σε κάποιο άλλο function ή stored procedure και να το καλώ όπου χρειάζεται να πω ότι ναι είναι μια λύση αλλά αυξάνει τα dependencies και σε αρκετές περιπτώσεις το performance καθώς μιλάμε για executions plans από διαφορετικά objects που πρέπει να συνεργαστούν.

Ιδανικά θα ήθελα να έχω μια λογική gosub/return αλλά δεν την έχουμε διαθέσιμη στην T-SQL και ναι μεν μπορείς να το κάνεις με flags αλλά δεν μου αρέσει και τόσο γιατί πάμε στη λογική του μακαρονιού.

Multiple IF/ELSE cases

Μία χρήση που την χρησιμοποιώ αρκετά καθώς με βοηθάει στο να έχω καθαρό κώδικα και να μην χάνομαι μέσα σε αυτό είναι όταν έχω cases.

Δυστυχώς στην T-SQL δεν υπάρχει η λογική της switch όπως πχ σε C#. Ναι ξέρω θα μου πείτε για την CASE αλλά η CASE παίζει μόνο συνδυαστικά με κάποιο άλλο statement. Οπότε αναγκαστικά παίζεις με IF… ELSE και εκεί αν έχεις πολλά χάνεται το μάτι και ο έλεγχος ιδιαίτερα όταν στο κάθε IF υπάρχουν αρκετές γραμμές κώδικα, μάλιστα ούτε η χρήση tabs (indention) στο κώδικα δεν σε σώζει.

Δείτε το παρακάτω παράδειγμα και σκεφτείτε να υπάρχει αρκετός κώδικας μέσα σε κάθε IF...ELSE

SQL Script

create procedure pname @p1 int
as
begin

    if ( @p1 = x )
    begin
        ...
    end

    else if ( @p1 = y )
    begin
        ....
    end

    else if ( @p1 = z )
    begin
        ....
    end
    
    else
    begin
        ...
    end

    return
end
go

Θα μπορούσε να γίνει όπως παρακάτω και αυτό βοηθάει αρκετά στην συντήρηση και ανάγνωση του κώδικα.

SQL Script

create procedure pname @p1 int
as
begin

    
    if ( @p1 = x ) goto caseX
    if ( @p1 = y ) goto caseY
    if ( @p1 = z ) goto caseZ
    else goto caseother
    return

    caseX:
        ....
        return

    caseY:
        ....
        return

    caseZ:
        ....
        return

    caseother:
        ....
        return

end
go

Summary

Για ακόμα μια φορά θα πω ότι η χρήση της θέλει προγραμματιστική εμπειρία από αυτόν που γράφει τον κώδικα καθώς την ώρα που γράφει πρέπει να είναι σε θέση να αναγνωρίζει το πότε την χρησιμοποιεί σωστά και πότε ξεφεύγει η κατάσταση.

Τέλος να πω ότι τα παραδείγματα που παρατέθηκαν στον άρθρο αυτό επιδέχονται αλλαγών αλλά τα κράτησα απλά ώστε να γίνει κατανοητό το νόημα.


Antonios Chatzipavlis

Antonios Chatzipavlis

Antonios is a Data Solutions Consultant and Trainer. He has been working in IT since 1988. In his career, he has worked as senior developer, IT Manager, Solutions Architect and IT Consultant. Since 1995 he has been devoted on new technologies and software development tools, mainly by Microsoft, either by training company staff and colleagues or assisting them in design, development and implementation as a consultant or chief developer. He has focused in Databases and Data Science since 1995. He specialized in Microsoft SQL Server since version 6.0 in areas like SQL Server Internals, Database Design and Development, Business Intelligence and in 2010 he has started working with Azure Data Platform, NoSQL databases, Big Data Technologies and Machine Learning. He is an active member of many IT communities in Greece, answering colleagues' questions and writing articles in his web site. He is the owner of SQLschool.gr which is a community portal with a lot of information about Microsoft SQL Server. He has been a Microsoft Certified Trainer (MCT) since 2000. Microsoft honored him as MVP on Data Platform due to his activities in SQL Server since 2010. He holds a large number of Microsoft Certifications and Microsoft SQL Server Certifications since version 6.5.



Leave your comment

COMMENT

FULL NAME

EMAIL ADDRESS

We use Gravatar

WEB SITE



captcha


 

Newsletter

If you want to receive updates from us subscribe below with your email.
Follow us in

About us   Contact us   Terms of Use   Privacy   Register
sql school greece logo
© 2010-2021 All rights reserved

This site uses cookies for operational and analytics purposes only.
By continuing to browse this site, you agree to their use.