Χρήση δρομέων και βρόχων στο Transact-SQL. Δρομείς σε αποθηκευμένες διαδικασίες MySQL Δρομείς σε διακομιστή sql

Η εντολή DECLARE CURSOR σας επιτρέπει να ανακτήσετε εγγραφές από έναν πίνακα σειρά προς σειρά για χειρισμό. Αυτό επιτρέπει την επεξεργασία σειρά προς σειρά αντί για την παραδοσιακή επεξεργασία δεδομένων που κάνει η SQL.

Ως πρώτη προσέγγιση, τα ακόλουθα βήματα χρησιμοποιούνται κατά την εργασία με τον κέρσορα.

Ο κέρσορας δημιουργείται με την εντολή DECLARE. Ο κέρσορας ανοίγει με την εντολή OPEN.

Οι λειτουργίες με τον κέρσορα εκτελούνται χρησιμοποιώντας την εντολή FETCH. Ο κέρσορας κλείνει με την εντολή ΚΛΕΙΣΙΜΟ.

Η εντολή DECLARE CURSOR καθορίζει μια πρόταση SELECT. Κάθε σειρά που επιστρέφεται από την πρόταση SELECT μπορεί να ανακτηθεί και να υποβληθεί σε επεξεργασία ξεχωριστά. Το ακόλουθο παράδειγμα Oracle δηλώνει έναν δρομέα σε ένα μπλοκ δήλωσης μαζί με πολλές άλλες μεταβλητές. Μετά από αυτό, στο επόμενο μπλοκ BEGIN...END, ανοίγει ο δρομέας, γίνεται επιλογή από αυτόν και ο δρομέας κλείνει.

CURSOR title_price_cursor ΕΙΝΑΙ ΕΠΙΛΟΓΟΣ τίτλος, τιμή ΑΠΟ τίτλους

ΟΠΟΥ η τιμή ΔΕΝ ΕΙΝΑΙ ΜΗΧΑΝΗ. title_price_val title_price_cursor ROWTYPE; new_price NUMBER(10,2);

OPEN title_price_Cursor;

FETCH title_price_cur-sor INTO title_price_val.

new_price:= "title_price_val.price" * 1.25 INSERT INTO new_title_price VALUES

(title_price_val.title, new_price) CLOSE title_price_cursor; ΤΕΛΟΣ;

Επειδή αυτό το παράδειγμα χρησιμοποιεί PL/SQL, δεν θα εξηγήσουμε μεγάλο μέρος του κώδικα σε αυτό το βιβλίο. Ωστόσο, το μπλοκ DECLARE εμφανίζει καθαρά τη δήλωση του δρομέα. Σε ένα εκτελέσιμο μπλοκ PL/SQL, ο κέρσορας αρχικοποιείται με την εντολή OPEN, οι τιμές ανακτώνται με την εντολή FETCH και τέλος ο δρομέας κλείνει με την εντολή CLOSE.

Η δήλωση SELECT είναι η βάση του δρομέα, επομένως είναι καλή πρακτική να τη δοκιμάσετε διεξοδικά πριν τη συμπεριλάβετε στη δήλωση DECLARE CURSOR. Η δήλωση SELECT μπορεί να λειτουργήσει στον υποκείμενο πίνακα ή την προβολή. Επομένως, οι δρομείς μόνο για ανάγνωση μπορούν να λειτουργούν με προβολές που δεν μπορούν να ενημερώσουν. Μια πρόταση SELECT μπορεί να περιέχει ρήτρες όπως ORDER BY, GROUP BY και HAVING εφόσον αυτοί οι όροι δεν ενημερώνουν τον πίνακα προέλευσης. Εάν ο κέρσορας ορίζεται ως ΓΙΑ ΕΝΗΜΕΡΩΣΗ, τότε συνιστάται να αφαιρέσετε τέτοιες ρήτρες από την πρόταση SELECT.

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

Στο ακόλουθο απλό παράδειγμα DB2, θα δηλώσουμε έναν δρομέα που αναζητά αριθμούς τμημάτων, ονόματα τμημάτων και αριθμούς διαχειριστών στην ομάδα_διαχειριστή "XO1".

DECLARE dept_cursor CURSOR

ΓΙΑ SELECT dept_nbr, dept_name, mgr_nbr

WHERE admin_group="X01"

ΠΑΡΑΓΓΕΛΙΑ ΑΠΟ d"ept_name ASC, dept_nbr DESC, mgr_nbr DESC;

Το ακόλουθο παράδειγμα του Microsoft SQL Server δηλώνει και ανοίγει έναν δρομέα για τον πίνακα εκδοτών. Ο δρομέας επιλέγει την πρώτη εγγραφή που ταιριάζει με τη δήλωση SELECT από τον πίνακα εκδοτών και την εισάγει σε έναν άλλο πίνακα. Στη συνέχεια, προχωρά στην επόμενη εγγραφή, μετά στην επόμενη, έως ότου υποβληθούν σε επεξεργασία όλες οι εγγραφές. Τέλος, ο κέρσορας κλείνει και η μνήμη ελευθερώνεται (η εντολή DEALLOCATE χρησιμοποιείται μόνο στον Microsoft SQL Server).

ΔΗΛΩΣΤΕ @publisher_name VARCHAR(20)

ΔΗΛΩΣΤΕ pub_cursor CURSOR FOR SELECT pub_name ΑΠΟ εκδότες WHERE χώρα "ΗΠΑ"

ΑΝΑΓΚΗ ΤΗΣ ΕΠΟΜΕΝΗΣ ΑΠΟ PUB_cursor ΣΤΟ όνομα_εκδότη

WHILE @s>FETCH_STATUS=0

INSERT INTO Foreign_publishers VALUES("j>όνομα_εκδότη)

ΚΛΕΙΣΙΜΟ pub_cursor ΑΠΟΣΤΟΛΗ pub_cursor

Σε αυτό το παράδειγμα, μπορείτε να δείτε τον κέρσορα να κινείται μέσα από ένα σύνολο εγγραφών. (Αυτό το παράδειγμα προορίζεται μόνο για να καταδείξει την ιδέα, αφού στην πραγματικότητα υπάρχει Ο καλύτερος τρόποςλύση σε αυτό το πρόβλημα, δηλαδή την εντολή INSERT, SELECT.)

ΙΣΧΥΕΙ ΓΙΑ: SQL Server (από το 2008) Βάση Δεδομένα SQL Azure SQL Data Warehouse Parallel Data Warehouse

Καθορίζει χαρακτηριστικά ενός δρομέα διακομιστή Transact-SQL, όπως ιδιότητες προβολής και το ερώτημα που χρησιμοποιείται για τη δημιουργία του συνόλου αποτελεσμάτων στο οποίο λειτουργεί ο δρομέας. Η δήλωση DECLARE CURSOR υποστηρίζει τόσο την τυπική σύνταξη ISO όσο και τη σύνταξη που χρησιμοποιεί το σύνολο επεκτάσεων γλώσσας Transact-SQL.

Σύνταξη ISO ΔΗΛΩΣΤΕ το όνομα_δρομέα [ ΑΝΕΥΑΙΣΘΗΤΟ ] [ ΚΥΛΙΣΗ ] ΔΡΟΜΕΑ ΓΙΑ select_statement [ ΓΙΑ ( ΜΟΝΟ ΔΙΑΒΑΣΗ | ΕΝΗΜΕΡΩΣΗ [ OF column_name [ ,...n ] ] ) ] [;] Transact-SQL Extended Syntax ΔΗΛΩΣΗ δρομέα_όνομα ΔΡΟΜΕΑ [ ΤΟΠΙΚΟ | ΠΑΓΚΟΣΜΙΑ ] [ FORWARD_ONLY | ΚΥΛΙΣΗ ] [ ΣΤΑΤΙΚΟ | ΣΕΤ ΠΛΗΚΤΡΟ | ΔΥΝΑΜΙΚΟ | FAST_FORWARD ] [ READ_ONLY | SCROLL_LOCKS | ΑΙΣΙΟΔΟΞΗ ] [ TYPE_WARNING ] FOR select_statement [ ΓΙΑ ΕΝΗΜΕΡΩΣΗ [ OF column_name [ ,...n ] ] ] [;]

όνομα_δρομέα
όνομα_δρομέα

ΑΝΑΙΣΘΗΤΟΣ
tempdb; Επομένως, οι αλλαγές στους υποκείμενους πίνακες δεν αντικατοπτρίζονται στα δεδομένα που επιστρέφονται από τις επιλογές αυτού του δρομέα και αυτός ο κέρσορας δεν μπορεί να αλλάξει. Κατά τη χρήση της σύνταξης ISO, εκτός και αν έχει καθοριστεί η επιλογή ΑΣΑΘΙΣΤΟΣ, οι δεσμευμένες ενημερώσεις και οι διαγραφές που έγιναν στους βασικούς πίνακες εμφανίζονται στις επόμενες επιλογές.

ΠΑΠΥΡΟΣ
Υποδεικνύει ότι όλες οι επιλογές δειγματοληψίας είναι διαθέσιμες (ΠΡΩΤΟ, ΤΕΛΕΥΤΑΙΟ, ΠΡΟΗΓΟΥΜΕΝΟ, ΕΠΟΜΕΝΟ, ΣΧΕΤΙΚΟ, ΑΠΟΛΥΤΟ). Εάν η δήλωση ISO DECLARE CURSOR δεν καθορίζει μια επιλογή SCROLL, υποστηρίζεται μόνο η επιλογή NEXT fetch. Η επιλογή SCROLL δεν μπορεί να καθοριστεί με την επιλογή FAST_FORWARD.

select_statement
Μια τυπική δήλωση SELECT που καθορίζει το σύνολο αποτελεσμάτων ενός δρομέα. Δεν επιτρέπονται οι λέξεις-κλειδιά FOR Browse και INTO select_statementδήλωση δρομέα.

select_statementδιένεξη με δρομέα του ζητούμενου τύπου.

ΜΟΝΟ ΓΙΑ ΑΝΑΓΝΩΣΗ

Ενημέρωση ]
στήλη_όνομα [, .. .n] καθορίζεται, μόνο οι στήλες που αναφέρονται επιτρέπουν αλλαγές. Εάν η δήλωση UPDATE χρησιμοποιείται χωρίς λίστα στηλών, τότε η ενημέρωση είναι δυνατή για όλες τις στήλες.

όνομα_δρομέα
Το όνομα Transact-SQL του συγκεκριμένου δρομέα διακομιστή. όνομα_δρομέαπρέπει να ακολουθεί τους κανόνες για τα αναγνωριστικά.

ΤΟΠΙΚΟΣ
Υποδεικνύει ότι ο κέρσορας είναι τοπικός στο πακέτο, την αποθηκευμένη διαδικασία ή την ενεργοποίηση στην οποία δημιουργήθηκε. Το όνομα του δρομέα είναι έγκυρο μόνο σε αυτήν την περιοχή. Ένας δρομέας μπορεί να αναφέρεται από τοπικές μεταβλητές πακέτου, αποθηκευμένες διαδικασίες, ενεργοποιητές ή την παράμετρο εξόδου μιας αποθηκευμένης διαδικασίας. Η παράμετρος OUTPUT χρησιμοποιείται για τη μετάδοση ενός τοπικού δρομέα στο καλούν πακέτο, την αποθηκευμένη διαδικασία ή την ενεργοποίηση, η οποία μπορεί στη συνέχεια να εκχωρήσει την παράμετρο σε μια μεταβλητή δρομέα για μετέπειτα πρόσβαση στον κέρσορα μετά την ολοκλήρωση της αποθηκευμένης διαδικασίας. Ο κέρσορας απελευθερώνεται σιωπηρά όταν η δέσμη, η αποθηκευμένη διαδικασία ή η ενεργοποίηση ολοκληρώσει την εκτέλεση, εκτός εάν ο δρομέας μεταβιβάστηκε στην παράμετρο OUTPUT. Εάν ο δρομέας μεταβιβάστηκε στην παράμετρο OUTPUT, ο κέρσορας απελευθερώνεται όταν ελευθερωθούν όλες οι μεταβλητές που τον αναφέρουν ή όταν τερματιστεί το εύρος.

ΠΑΓΚΟΣΜΙΑ
Υποδεικνύει ότι ο κέρσορας είναι καθολικός στη σύνδεση. Το όνομα του δρομέα μπορεί να χρησιμοποιηθεί από οποιαδήποτε αποθηκευμένη διαδικασία ή πακέτο που εκτελείται στη σύνδεση. Ο κέρσορας απελευθερώνεται σιωπηρά μόνο εάν διακοπεί η σύνδεση.

FORWARD_ONLY
Καθορίζει ότι ο κέρσορας μπορεί να προβληθεί μόνο από την πρώτη γραμμή μέχρι την τελευταία. Υποστηρίζεται μόνο η επιλογή FETCH NEXT fetch. Εάν έχει καθοριστεί FORWARD_ONLY χωρίς τις λέξεις-κλειδιά STATIC, KEYSET ή DYNAMIC, ο δρομέας συμπεριφέρεται ως ΔΥΝΑΜΙΚΟΣ δρομέας. Εάν δεν έχει καθοριστεί ούτε το όρισμα FORWARD_ONLY ούτε το όρισμα SCROLL, η προεπιλογή είναι το όρισμα FORWARD_ONLY εκτός εάν υπάρχουν οι λέξεις-κλειδιά STATIC, KEYSET ή DYNAMIC. Οι δρομείς STATIC, KEYSET και DYNAMIC έχουν προεπιλεγμένη τιμή SCROLL. Σε αντίθεση με τα API βάσης δεδομένων όπως το ODBC και το ADO, η λειτουργία FORWARD_ONLY υποστηρίζεται από τους ακόλουθους δρομείς Transact-SQL: STATIC, KEYSET και DYNAMIC.

ΣΤΑΤΙΚΟΣ
Ορίζει έναν δρομέα που δημιουργεί ένα προσωρινό αντίγραφο δεδομένων για χρήση από τον κέρσορα. Όλα τα ερωτήματα στον κέρσορα έχουν πρόσβαση στον καθορισμένο προσωρινό πίνακα tempdb; Επομένως, οι αλλαγές στους υποκείμενους πίνακες δεν αντικατοπτρίζονται στα δεδομένα που επιστρέφονται από τις επιλογές αυτού του δρομέα και αυτός ο κέρσορας δεν μπορεί να αλλάξει.

ΣΕΤ ΠΛΗΚΤΡΟ
Υποδεικνύει ότι η ιδιότητα μέλους ή η σειρά των σειρών στον κέρσορα παραμένει αμετάβλητη όταν ανοίγει. Ένα σύνολο πλήκτρων που προσδιορίζουν μοναδικά τις σειρές είναι ενσωματωμένο στον πίνακα tempdbπου ονομάζεται κλειδιά.

Οι αλλαγές σε τιμές χωρίς κλειδί σε βασικούς πίνακες που έγιναν από τον κάτοχο του δρομέα ή πραγματοποιήθηκαν από άλλους χρήστες εμφανίζονται όταν ο κάτοχος του δρομέα το δει. Οι αλλαγές που έγιναν από άλλους χρήστες δεν αντικατοπτρίζονται (οι αλλαγές δεν μπορούν να γίνουν χρησιμοποιώντας τον δρομέα διακομιστή Transact-SQL). Εάν μια σειρά διαγραφεί, η προσπάθεια ανάκτησης σειρών επιστρέφει @@FETCH_STATUS -2. Οι ενημερώσεις σε τιμές κλειδιών από τα όρια του δρομέα είναι παρόμοιες με τη διαγραφή μιας παλιάς σειράς και στη συνέχεια την εισαγωγή μιας νέας σειράς. Η σειρά με τις νέες τιμές δεν είναι ορατή και προσπαθεί να ανακτήσει τη σειρά με τις παλιές τιμές επιστρέφει @@FETCH_STATUS -2. Οι ενημερώσεις είναι ορατές αμέσως εάν γίνονται μέσω του δρομέα χρησιμοποιώντας την πρόταση WHERE CURRENT OF.

ΔΥΝΑΜΙΚΟΣ
Καθορίζει έναν δρομέα που εμφανίζει όλες τις αλλαγές δεδομένων που έγιναν σε σειρές στο σύνολο αποτελεσμάτων κατά την προβολή αυτού του δρομέα. Οι τιμές δεδομένων, η σειρά και η ιδιότητα μέλους σειρών σε κάθε επιλογή ενδέχεται να διαφέρουν. Η επιλογή ΑΠΟΛΥΤΗ επιλογή δεν υποστηρίζεται από δυναμικούς δρομείς.

ΓΡΗΓΟΡΗ ΠΡΟΩΘΗΣΗ
Υποδεικνύει έναν δρομέα FORWARD_ONLY, READ_ONLY που έχει ενεργοποιημένη τη βελτιστοποίηση απόδοσης. Η επιλογή FAST_FORWARD δεν μπορεί να καθοριστεί με τις επιλογές SCROLL ή FOR_UPDATE.

ΜΟΝΟ ΓΙΑ ΑΝΑΓΝΩΣΗ
Αποτρέπει τις αλλαγές που γίνονται μέσω αυτού του δρομέα. Η πρόταση WHERE CURRENT OF δεν μπορεί να αναφέρει έναν δρομέα σε μια πρόταση ΕΝΗΜΕΡΩΣΗ ή ΔΙΑΓΡΑΦΗ. Αυτή η επιλογή έχει προτεραιότητα έναντι της προεπιλεγμένης δυνατότητας ανανέωσης του δρομέα.

SCROLL_LOCKS
Υποδεικνύει ότι οι τοποθετημένες ενημερώσεις ή διαγραφές που πραγματοποιούνται με χρήση του δρομέα είναι εγγυημένα επιτυχείς. Ο SQL Server κλειδώνει τις σειρές καθώς διαβάζονται στον κέρσορα για να διασφαλίσει ότι αυτές οι σειρές είναι διαθέσιμες για επόμενες αλλαγές. Η επιλογή SCROLL_LOCKS δεν μπορεί να καθοριστεί με την επιλογή FAST_FORWARD ή STATIC.

ΑΙΣΙΟΔΟΞΟΣ
Καθορίζει ότι οι τοποθετημένες ενημερώσεις ή διαγραφές που γίνονται με χρήση του δρομέα θα αποτύχουν εάν η σειρά έχει ενημερωθεί από τότε που διαβάστηκε στον κέρσορα. Ο SQL Server δεν κλειδώνει τις σειρές καθώς διαβάζονται στον κέρσορα. Αντ' αυτού χρησιμοποιούνται συγκρίσεις χρονική σφραγίδατιμές στήλης ή αθροίσματα ελέγχου, αν όχι στον πίνακα χρονική σφραγίδαστήλη για να προσδιορίσετε εάν η σειρά έχει αλλάξει από τότε που διαβάστηκε στον κέρσορα. Εάν η σειρά έχει τροποποιηθεί, τότε οι προσπάθειες για ενημέρωση ή διαγραφή θέσης θα αποτύχουν. Η επιλογή OPTIMISTIC δεν μπορεί να καθοριστεί με την επιλογή FAST_FORWARD.

TYPE_WARNING
Καθορίζει ότι μια προειδοποίηση θα σταλεί στον πελάτη εάν ο δρομέας μετατραπεί σιωπηρά από έναν τύπο που ζητήθηκε σε έναν άλλο.

select_statement
Μια τυπική δήλωση SELECT που καθορίζει το σύνολο αποτελεσμάτων ενός δρομέα. Οι λέξεις-κλειδιά COMPUTE, COMPUTE BY, FOR Browse και INTO δεν επιτρέπονται στο select_statementδήλωση δρομέα.

Ο SQL Server μετατρέπει σιωπηρά τον κέρσορα σε άλλο τύπο, εάν υπάρχουν οι όροι select_statementδιένεξη με δρομέα του ζητούμενου τύπου. Για περισσότερες πληροφορίες, δείτε τις σιωπηρές μετατροπές δρομέα.

ΓΙΑ ΕΝΗΜΕΡΩΣΗ]
Καθορίζει τις στήλες στον κέρσορα που θα ενημερωθούν. Αν ΟΦ στήλη_όνομα [, ... n] παρέχεται, μόνο οι στήλες που αναφέρονται επιτρέπουν αλλαγές. Εάν η δήλωση UPDATE χρησιμοποιείται χωρίς λίστα στηλών, τότε η ενημέρωση είναι δυνατή για όλες τις στήλες, εκτός εάν έχει καθοριστεί η επιλογή ταυτόχρονης READ_ONLY.

Η δήλωση DECLARE CURSOR ορίζει χαρακτηριστικά ενός δρομέα διακομιστή Transact-SQL, όπως ιδιότητες προβολής και το ερώτημα που χρησιμοποιείται για τη δημιουργία του συνόλου αποτελεσμάτων στο οποίο λειτουργεί ο δρομέας. Η δήλωση OPEN συμπληρώνει το σύνολο αποτελεσμάτων και η πρόταση FETCH επιστρέφει μια σειρά από αυτό. Η δήλωση CLOSE διαγράφει το τρέχον σύνολο αποτελεσμάτων που σχετίζεται με τον κέρσορα. Η δήλωση DEALLOCATE απελευθερώνει πόρους που χρησιμοποιούνται από τον δρομέα.

Η πρώτη μορφή της δήλωσης DECLARE CURSOR χρησιμοποιεί σύνταξη ISO για να καθορίσει τις παραμέτρους του δρομέα. Η δεύτερη μορφή της πρότασης DECLARE CURSOR χρησιμοποιεί επεκτάσεις στη γλώσσα Transact-SQL που σας επιτρέπουν να ορίζετε δρομείς χρησιμοποιώντας τους ίδιους τύπους με αυτούς που χρησιμοποιούνται στις συναρτήσεις δρομέα των API βάσης δεδομένων όπως το ODBC και το ADO.

Αυτές οι δύο μορφές δεν μπορούν να αναμειχθούν. Εάν καθορίσετε SCROLL ή παραλείπετε λέξεις-κλειδιά πριν από τη λέξη-κλειδί CURSOR, δεν μπορείτε να χρησιμοποιήσετε λέξεις-κλειδιά μεταξύ του CURSOR και επίσης για select_statementλέξεις-κλειδιά. Κατά τον καθορισμό λέξεων-κλειδιών μεταξύ του CURSOR, καθώς και για select_statementλέξεις-κλειδιά, δεν μπορείτε να καθορίσετε SCROLL ή INSENSITIVE πριν από τη λέξη-κλειδί CURSOR.

Εάν χρησιμοποιείτε τη σύνταξη Transact-SQL για τη δήλωση DECLARE CURSOR και δεν προσδιορίζετε τις επιλογές READ_ONLY, OPTIMISTIC ή SCROLL_LOCKS, η ακόλουθη προεπιλεγμένη τιμή θεωρείται ότι.

    Εάν η δήλωση SELECT δεν υποστηρίζει ενημερώσεις (ή έχει ανεπαρκή δικαιώματα ή έχει πρόσβαση σε απομακρυσμένους πίνακες που δεν υποστηρίζουν ενημερώσεις κ.λπ.), ο δρομέας ορίζεται σε READ_ONLY.

    Οι δρομείς STATIC και FAST_FORWARD από προεπιλογή είναι READ_ONLY.

    Οι δρομείς DYNAMIC και KEYSET από προεπιλογή είναι OPTIMISTIC.

Οι δρομείς μπορούν να αναφέρονται μόνο από άλλες δηλώσεις Transact-SQL. Οι συναρτήσεις API βάσης δεδομένων δεν μπορούν να αναφέρουν δρομείς. Για παράδειγμα, μόλις δηλωθεί ένας δρομέας, οι συναρτήσεις και οι μέθοδοι OLE DB, ODBC ή ADO δεν μπορούν να αναφέρονται στο όνομά του. Οι σειρές του δρομέα δεν μπορούν να επιλεγούν χρησιμοποιώντας τις αντίστοιχες λειτουργίες και μεθόδους API. Για το σκοπό αυτό, πρέπει να χρησιμοποιήσετε δηλώσεις Transact-SQL FETCH.

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

Οι μεταβλητές μπορούν να χρησιμοποιηθούν ως μέρος select_statement, στο οποίο δηλώνεται ο κέρσορας. Οι τιμές των μεταβλητών του δρομέα δεν αλλάζουν μετά τη δήλωση.

Από προεπιλογή, τα δικαιώματα DECLARE CURSOR χορηγούνται σε όλους τους χρήστες που έχουν δικαίωμα SELECT στις προβολές, τους πίνακες και τις στήλες που χρησιμοποιούνται από τον δρομέα.

Δεν μπορείτε να χρησιμοποιήσετε δρομείς ή κανόνες ετικέτας σε έναν πίνακα με ευρετήριο αποθήκευσης στηλών συμπλέγματος. Αυτός ο περιορισμός δεν ισχύει για μη ομαδοποιημένα ευρετήρια. Μπορείτε να χρησιμοποιήσετε δρομείς και κανόνες ετικέτας σε έναν πίνακα με ευρετήριο αποθήκευσης στηλών χωρίς συμπλέγματα.

Α. Χρήση απλού δρομέα και σύνταξης

Το σύνολο αποτελεσμάτων που δημιουργήθηκε όταν ανοίγετε αυτόν τον δρομέα περιλαμβάνει όλες τις γραμμές και τις στήλες του πίνακα. Αυτός ο δρομέας μπορεί να ενημερωθεί, όλες οι ενημερώσεις και οι διαγραφές αντιπροσωπεύονται στην επιλογή αυτού του δρομέα. FETCH``NEXT λαμβάνεται μόνο επειδή η παράμετρος SCROLL δεν έχει καθοριστεί.

ΔΗΛΩΣΗ vend_cursor CURSOR FOR SELECT * FROM Purchasing.Vendor OPEN vend_cursor FETCH NEXT FROM vend_cursor;

B. Χρήση ένθετων δρομέων για την εμφάνιση μιας αναφοράς

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

ΡΥΘΜΙΣΗ ΕΝΕΡΓΟΠΟΙΗΣΗΣ NO COUNT ; ΔΗΛΩΣΤΕ @vendor_id int , @vendor_name nvarchar ( 50 ), @message varchar ( 80 ), @product nvarchar ( 50 );ΤΥΠΩΝΩ" -------- Αναφορά προϊόντων προμηθευτή --------"; ΔΗΛΩΣΤΕ vendor_cursor ΔΙΑΜΟΡΦΩΣΗ ΓΙΑ ΕΠΙΛΕΓΜΕΝΟ Αναγνωριστικό Προμηθευτή, Όνομα ΑΠΟ Αγορά. OPEN vendor_cursor FETCH ΕΠΟΜΕΝΟ ΑΠΟ vendor_cursor INTO @vendor_id, @vendor_name ΕΝΩ @@FETCH_STATUS = 0 BEGIN PRINT " " SELECT @message = "----- Προϊόντα από τον προμηθευτή: "+ @vendor_name PRINT @message -- Δηλώστε έναν εσωτερικό δρομέα που βασίζεται -- στο vendor_id από τον εξωτερικό δρομέα. DECLARE product_cursor CURSOR FOR SELECT v.Name FROM Purchasing.ProductVendor pv, Production.Product v WHERE pv.ProductID = v.ProductID ΚΑΙ pv.VendorID = @vendor_id -- Μεταβλητή τιμή από τον εξωτερικό δρομέα OPEN product_cursor FETCH NEXT FROM product_cursor INTO @product IF @@FETCH_STATUS<>0 ΕΚΤΥΠΩΣΗ "<>" WHILE @@FETCH_STATUS = 0 BEGIN ΕΠΙΛΟΓΗ @message = " " + @product PRINT @message ΑΝΑΓΚΗ ΕΠΟΜΕΝΟΥ ΑΠΟ product_cursor ΣΤΟ @product ΤΕΛΟΣ ΚΛΕΙΣΙΜΟ product_cursor DEALLOCATE product_cursor -- Λάβετε τον επόμενο προμηθευτή. FETCH TO NEXT FROM vendor vendor @vendor_ ΤΕΛΟΣ ΚΛΕΙΣΙΜΟ vendor_cursor; DEALLOCATE vendor_cursor;


Ο δρομέας είναι ένας σύνδεσμος προς την περιοχή της μνήμης με βάση τα συμφραζόμενα. Σε ορισμένες υλοποιήσεις της γλώσσας προγραμματισμού SQL (Oracle, Microsoft SQL Server) - το σύνολο αποτελεσμάτων που λαμβάνεται κατά την εκτέλεση ενός ερωτήματος και ο δείκτης τρέχουσας εγγραφής που σχετίζεται με αυτό. Θα έλεγα ότι ένας δρομέας είναι ένας εικονικός πίνακας που αντιπροσωπεύει μια εναλλακτική αποθήκευση δεδομένων. Σε αυτήν την περίπτωση, ο δρομέας σάς επιτρέπει να έχετε πρόσβαση στα δεδομένα του σαν να ήταν τα δεδομένα ενός κανονικού πίνακα.
Οι δρομείς χρησιμοποιούνται σε αποθηκευμένες διαδικασίες. Αρκετή θεωρία, ας δούμε ένα παράδειγμα:
Έχουμε μια βάση δεδομένων (η βάση δεδομένων δεν είναι λίγο καλή, αυτή είναι μια από τις δικές μου εργαστηριακές εργασίες, αλλά ο δάσκαλος της βάσης δεδομένων μας επέμενε σε μια τέτοια δομή)
/*πληροφορίες Τράπεζας*/
ΔΗΜΙΟΥΡΓΙΑ ΠΙΝΑΚΑ "τράπεζα" (

`BankName` VARCHAR (50) COLLATE utf8_bin NOT NULL DEFAULT "" ,


ΚΥΡΙΟ ΚΛΕΙΔΙ ("BankId")

)ENGINE=InnoDB
ΣΕΤ ΧΑΡΑΚΤΗΡΩΝ "utf8" ΣΥΓΚΕΝΤΡΩΣΗ "utf8_bin" ;
/*στοιχεία καταθέσεων */
ΔΗΜΙΟΥΡΓΙΑ ΠΙΝΑΚΑ "διανομή τράπεζας" (
«BankId» ΑΚΕΡΑΙΟΣ (11) ΟΧΙ NULL,
"Persent" INTEGER (11) DEFAULT NULL ,
`ContributeAmount` ΔΕΚΑΔΙΚΟ (10,0) ΟΧΙ ΜΗΧΑΝΟ,
«ClientId» INTEGER (11) ΟΧΙ NULL,
ΚΥΡΙΟ ΚΛΕΙΔΙ (`BankId`, `ClientId`),
KEY `BankId` (`BankId`),
KEY `ClientId` (`ClientId`),
ΠΕΡΙΟΡΙΣΜΟΣ `bankdistribution_fk` ΞΕΝΟ ΚΛΕΙΔΙ (`BankId`) ΑΝΑΦΟΡΕΣ `bank` (`BankId`),
ΠΕΡΙΟΡΙΣΜΟΣ `bankdistribution_fk1` ΞΕΝΟ ΚΛΕΙΔΙ (`ClientId`) ΑΝΑΦΟΡΕΣ `client` (`ClientId`)
)ENGINE=InnoDB
/*στοιχεία για επενδυτές*/
ΔΗΜΙΟΥΡΓΙΑ ΠΙΝΑΚΑ "πελάτη" (
`ClientId` ΑΚΕΡΑΙΟΣ (3) ΟΧΙ NULL AUTO_INCREMENT,
`CreditCardId` BIGINT(10) NOT NULL,
`Επώνυμο` VARCHAR (50) COLLATE utf8_bin NOT NULL DEFAULT "" ,
`Όνομα` VARCHAR (50) COLLATE utf8_bin NOT NULL DEFAULT "" ,
`FirstName` VARCHAR (50) COLLATE utf8_bin NOT NULL DEFAULT "" ,
`Τηλέφωνο` VARCHAR (50) COLLATE utf8_bin NOT NULL DEFAULT "" ,
`Διεύθυνση` VARCHAR (50) COLLATE utf8_bin NOT NULL DEFAULT "" ,
«SafeId» INTEGER (5) ΟΧΙ NULL,
ΚΥΡΙΟ ΚΛΕΙΔΙ (`ClientId`, `CreditCardId`),
KEY `ClientId` (`ClientId`)

)ENGINE=InnoDB
AUTO_INCREMENT=11 ΣΕΤ ΧΑΡΑΚΤΗΡΩΝ "utf8" ΣΥΓΚΡΟΤΗΜΑ "utf8_bin"

Ας υποθέσουμε ότι πρέπει να λάβουμε κάθε τράπεζα με τη σειρά και να εκτελέσουμε ορισμένες ενέργειες μαζί της, το ακόλουθο ερώτημα θα μπορούσε να μας βοηθήσει σε αυτό

Επιλέξτε «τράπεζα».* ΑΠΟ ΟΡΙΟ ΑΡΙΘΜΟ «ΤΡΑΠΕΖΑ» ΤΩΝ_ΑΡΧΕΙΩΝ_ΧΡΕΙΑΖΟΜΑΣΤΕ,1
. Έτσι, χρησιμοποιώντας το LIMIT WE NEED_RECORD NUMBER, 1, εξάγουμε κάθε εγγραφή σε βρόχο από τον πίνακα τράπεζας και εκτελούμε τις ενέργειες που χρειαζόμαστε με αυτό, αυξάνοντας παράλληλα την τιμή του WE NEED_RECORD NUMBER κατά 1. Τώρα θα κάνουμε το ίδιο, αλλά χρησιμοποιώντας ένα δρομέας
Αρχίζουν
/* μεταβλητές όπου εξάγουμε δεδομένα */
Δήλωση ακέραιου αριθμού vBankId ;
Δήλωση vBankName VARCHAR(50);
Δήλωση vAddress VARCHAR(50);
Δήλωση vPhone VARCHAR (50);
/* μεταβλητή hadler - a*/
Δηλώστε ολοκληρωμένο ακέραιο προεπιλεγμένο 0.
/*Δήλωση δρομέα*/
Δήλωση δρομέα BankCursor για Επιλογή `bank`.`BankId`,`bank`.`BankName`,`bank`.`Address`,`bank`.
/*Σκοπός HANDLER, ο οποίος θα εξηγηθεί παρακάτω*/
ΔΗΛΩΣΤΕ ΣΥΝΕΧΕΙΑ ΧΕΙΡΙΣΤΗΡΙΟΥ ΓΙΑ ΣΕΤ "02000" SQLSTATE done=1;
/* άνοιγμα κέρσορα */
Άνοιγμα BankCursor.
/*ανάκτηση δεδομένων*/
ΕΝΩ ολοκληρώθηκε = 0 DO

κάνουμε τις ενέργειες που χρειαζόμαστε
ΤΕΛΟΣ ΕΝΩ ;
/*κλείσιμο του δρομέα*/
Κλείσιμο BankCursor.
ΤΕΛΟΣ ;

* Αυτός ο πηγαίος κώδικας επισημάνθηκε με το εργαλείο επισήμανσης πηγαίου κώδικα.

Σφάλμα: 1329 SQLSTATE: 02000 (ER_SP_FETCH_NO_DATA)

Μήνυμα: Δεν υπάρχουν δεδομένα - μηδέν σειρές ανακτήθηκαν, επιλέχθηκαν ή υποβλήθηκαν σε επεξεργασία

SQLSTATE: Το 02000 ενεργοποιείται όταν φτάσει στο τέλος του δρομέα ή όταν η επιλογή ή η ενημέρωση επιστρέφει μια κενή συμβολοσειρά.

Στην επόμενη γραμμή δηλώσαμε τον κέρσορα DECLARE cursor_name CURSOR FOR select_statement.
Άνοιγμα του δρομέα Άνοιγμα cursor_name.
Στη συνέχεια, μέχρι να φτάσουμε στο τέλος του δρομέα (WHILE done = 0 DO), εξάγουμε τα δεδομένα και τα επεξεργαζόμαστε.
Πρέπει να κλείσετε τον κέρσορα πριν βγείτε από την αποθηκευμένη διαδικασία. Κλείσιμο cursor_name;

Δεν φαίνεται περίπλοκο. Υπάρχουν όμως πολλές παγίδες που σχετίζονται με το SQLSTATE "02000".

ΕΝΩ ολοκληρώθηκε = 0 DO
ΑΝΑΚΤΗΣΗ BankCursor INTO vBankId,vBankName,vAddress,vPhone.

Επιλέξτε (ContributeAmount) INTO vContributeAmountSUM FROM bankdistribute όπου BankId = vBankId όριο 1.
κάνουμε κάποιες ενέργειες
ΤΕΛΟΣ ΕΝΩ ;

* Αυτός ο πηγαίος κώδικας επισημάνθηκε με το εργαλείο επισήμανσης πηγαίου κώδικα.


Όλα είναι καλά και σωστά από συντακτική άποψη. Αλλά από λογικής άποψης, όχι. Μπορεί οι καταθέτες να μην έχουν ανοίξει λογαριασμούς σε κάποια τράπεζα, στη συνέχεια για Select (ContributeAmount) INTO vContributeAmountSUM FROM διανομή τράπεζας όπου BankId = vBankId όριο 1. SQLSTATE: Το 02000 θα ενεργοποιηθεί, η μεταβλητή done θα οριστεί σε 1 και ο βρόχος while θα τελειώσει νωρίτερα από ό,τι περιμέναμε. Αυτό μπορεί να αποφευχθεί κάνοντας τα εξής
ΕΝΩ ολοκληρώθηκε = 0 DO
ΑΝΑΚΤΗΣΗ BankCursor INTO vBankId,vBankName,vAddress,vPhone.
/* αποσπά για την τράπεζα το ποσό οποιασδήποτε από τις καταθέσεις της */


εάν (vContributeAmountSUM > 0) τότε
/* αποσπά για την τράπεζα το ποσό οποιασδήποτε από τις καταθέσεις της */

τέλος εαν ;
κάνουμε κάποιες ενέργειες
ΤΕΛΟΣ ΕΝΩ ;

* Αυτός ο πηγαίος κώδικας επισημάνθηκε με το εργαλείο επισήμανσης πηγαίου κώδικα.


Με το πρώτο αίτημα, ελέγξαμε αν υπάρχουν συνεισφορές (αν δεν υπάρχουν, τότε vContributeAmountSUM == 0) και μόνο αν υπάρχουν, ανακτούμε τα δεδομένα.

Τώρα ας υποθέσουμε ότι πρέπει να αφαιρέσουμε το συνολικό ποσό σε λογαριασμούς σε διαφορετικές τράπεζες για κάθε πελάτη
Δηλώστε το ClientSummCursor Cursor για Select sum

Δήλωση του δρομέα ClientSummCursor για Select sum (`bankdistribution`.`ContributeAmount`), `bankdistribution`.`ClientId` FROM `bankdistribution` Inner Join πελάτη στο (client.ClientId = bankdistribution.`ClientId`) όπου 1 ομάδα διανομής κατά ``kdistribution`. `ClientId`;

Άνοιγμα ClientSummCursor.
ΕΝΩ ολοκληρώθηκε = 0 DO
ΑΝΑΚΤΗΣΗ BankCursor INTO vBankId,vBankName,vAddress,vPhone.
/* αποσπά για την τράπεζα το ποσό οποιασδήποτε από τις καταθέσεις της */
Επιλέξτε Count(ContributeAmount) INTO vContributeAmountSUM FROM bankdistribution όπου BankId = όριο vBankId 1.
/* ελέγξτε αν υπάρχουν όντως καταθέσεις σε αυτήν την τράπεζα */
εάν (vContributeAmountSUM > 0) τότε
/* αποσπά για την τράπεζα το ποσό οποιασδήποτε από τις καταθέσεις της */
Επιλέξτε ContributeAmount INTO vContributeAmountSUM FROM bankdistribution όπου BankId = vBankId όριο 1.
τέλος εαν ;


κάνουμε κάποιες ενέργειες.
ΤΕΛΟΣ ΕΝΩ ;

* Αυτός ο πηγαίος κώδικας επισημάνθηκε με το εργαλείο επισήμανσης πηγαίου κώδικα.

Η ίδια κατάσταση μπορεί να προκύψει όταν τα δεδομένα στον δρομέα ClientSummCursor τελειώνουν νωρίτερα από τα δεδομένα στον BankCursor, ενεργοποιείται το SQLSTATE: 02000, η ​​μεταβλητή done ορίζεται σε 1 και ο βρόχος while τελειώνει νωρίτερα από ό,τι περιμέναμε. Αυτό μπορεί να αποφευχθεί κάνοντας τα εξής

Άνοιγμα ClientSummCursor.
ΕΝΩ ολοκληρώθηκε = 0 DO
ΑΝΑΚΤΗΣΗ BankCursor INTO vBankId,vBankName,vAddress,vPhone.
/* αποσπά για την τράπεζα το ποσό οποιασδήποτε από τις καταθέσεις της */
Επιλέξτε Count(ContributeAmount) INTO vContributeAmountSUM FROM bankdistribution όπου BankId = όριο vBankId 1.
/* ελέγξτε αν υπάρχουν όντως καταθέσεις σε αυτήν την τράπεζα */
εάν (vContributeAmountSUM > 0) τότε
/* αποσπά για την τράπεζα το ποσό οποιασδήποτε από τις καταθέσεις της */
Επιλέξτε ContributeAmount INTO vContributeAmountSUM FROM bankdistribution όπου BankId = vBankId όριο 1.
τέλος εαν ;
/* πριν εξαγάγετε δεδομένα από τον δεύτερο δρομέα, θυμηθείτε την κατάσταση sqlstate */
SET old_status = ολοκληρωμένο.
/* εξάγουμε τα δεδομένα που χρειαζόμαστε */
FETCH ClientSummCursor INTO vSum,vClientId;
/* ελέγξτε εάν τα δεδομένα ανακτήθηκαν και αν το sqlstate 0200 απέτυχε */
αν (ολοκληρώθηκε = 0) τότε
κάνουμε κάποιες ενέργειες.
τέλος εαν ;
/* πριν από το τέλος του while, επαναφέρετε την τιμή της μεταβλητής done */
set done = old_status;
ΤΕΛΟΣ ΕΝΩ ;

* Αυτός ο πηγαίος κώδικας επισημάνθηκε με το εργαλείο επισήμανσης πηγαίου κώδικα.

Ευχαριστώ όλους όσους διάβασαν μέχρι εδώ, ελπίζω ότι αυτό θα είναι χρήσιμο σε κάποιον.

Η υλοποίηση ενός δρομέα σε μια βάση δεδομένων μοιάζει με μια κλάση Java που έχει ένα σύνολο δεδομένων και μεθόδων για την επεξεργασία του. Εν δρομέας sqlχρησιμοποιεί τα δεδομένα ως κανονικό πίνακα. Οι δρομείς μπορούν να χρησιμοποιηθούν σε ενεργοποιητές, αποθηκευμένες διαδικασίες και λειτουργίες.

Σύμφωνα με το πρότυπο SQL, όταν εργάζεστε με δρομείς, εκτελούνται οι ακόλουθες βασικές ενέργειες:

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

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

Σε ορισμένες περιπτώσεις, δεν μπορείτε να κάνετε χωρίς τη χρήση δρομέα. Ωστόσο, εάν είναι δυνατόν, θα πρέπει να αποφύγετε τη χρήση δρομέα και να εργαστείτε με τυπικές εντολές επεξεργασίας δεδομένων: ΕΠΙΛΟΓΗ, ΕΝΗΜΕΡΩΣΗ, ΕΝΙΣΧΥΣΗ, ΔΙΑΓΡΑΦΗ. Αυτό οφείλεται στο γεγονός ότι οι δρομείς δεν επιτρέπουν λειτουργίες τροποποίησης σε ολόκληρο τον όγκο δεδομένων και η ταχύτητα εκτέλεσης εργασιών επεξεργασίας δεδομένων με χρήση δρομέα είναι αισθητά χαμηλότερη από αυτή του τυπικά μέσα SQL.

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

Δήλωση δρομέα

Οι δρομείς πρέπει να δηλωθούν για να μπορέσουν να χρησιμοποιηθούν. Το πρότυπο SQL χρησιμοποιεί την ακόλουθη σύνταξη για να δημιουργήσει έναν δρομέα:

Δήλωση cursor_name cursor για select_statement ])]

Αυτή η έκφραση δηλώνει δρομέα δήλωση κέρσοραμε το όνομα "cursor_name".

ΑΝΑΙΣΘΗΤΟΣδημιουργείται ένας στατικός κέρσορας που δεν επιτρέπει την πραγματοποίηση αλλαγών. Επιπλέον, οι αλλαγές που έγιναν από άλλους χρήστες δεν εμφανίζονται. Εάν λείπει η λέξη-κλειδί ΑΣΑΘΙΣΤΗ, δημιουργείται ένας δυναμικός δρομέας.

Όταν χρησιμοποιείτε μια λέξη-κλειδί ΠΑΠΥΡΟΣο δημιουργημένος δρομέας μπορεί να μετακινηθεί προς οποιαδήποτε κατεύθυνση, επιτρέποντάς σας να εφαρμόσετε οποιεσδήποτε εντολές επιλογής. Εάν αυτό το όρισμα παραλειφθεί, τότε ο δρομέας θα είναι διαδοχικός, δηλ. η προβολή του θα είναι δυνατή μόνο προς μία κατεύθυνση - από την αρχή μέχρι το τέλος.

Εκφραση select_statementυποδεικνύει μια δομή για την ανάγνωση πληροφοριών όπως επιλογή ... από ... . Δεν πρέπει να περιέχει τον χειριστή σε, αφού ο κέρσορας έχει τον δικό του τελεστή φέρωγια να γεμίσετε μεταβλητές με δεδομένα δρομέα.

Όταν προσδιορίζετε ένα όρισμα ΜΟΝΟ ΓΙΑ ΔΙΑΒΑΣΗθα δημιουργηθεί ένας δρομέας μόνο για ανάγνωση και δεν θα επιτρέπονται τροποποιήσεις στα δεδομένα. Ένας δυναμικός δρομέας μπορεί να δηλωθεί ως δρομέας μόνο για ανάγνωση, επιτρέποντας την εμφάνιση αλλαγών που έγιναν από άλλο χρήστη.

Δημιουργία δρομέα με όρισμα ΓΙΑ ΕΝΗΜΕΡΩΣΗσας επιτρέπει να κάνετε αλλαγές σε δεδομένα στον κέρσορα είτε σε καθορισμένες στήλες είτε, ελλείψει ορίσματος Όνομα_στήλης, σε όλες τις στήλες.

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

Δρομέας ανοιχτός

Η SQL ορίζει την ακόλουθη σύνταξη για το άνοιγμα ενός δρομέα "ανοιχτός δρομέας":

Άνοιγμα cursor_name;

Λήψη δεδομένων από δρομέα, ανάκτηση δρομέα

Η σύνταξη για την ανάγνωση δεδομένων από έναν δρομέα σε ορισμένες μεταβλητές είναι η εξής:

Ανάκτηση cursor_name στο var_name [, var_name] ...;

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

Κλείσιμο του δρομέα

Χειριστής Κλείσεκλείνει τον κέρσορα. Εάν ο χειριστής δεν καθορίζεται ρητά, ο κέρσορας κλείνει αυτόματα όταν κλείσει το αντίστοιχο μπλοκ προγράμματος.

Κλείσιμο cursor_name;

Μετά το κλείσιμο, ο κέρσορας γίνεται απρόσιτος. Κατά το κλείσιμο, απελευθερώνονται όλες οι κλειδαριές που έχουν εγκατασταθεί ενώ ο κέρσορας ήταν σε λειτουργία. Μόνο ανοιχτοί δρομείς μπορούν να κλείσουν. Ένας κλειστός αλλά όχι απελευθερωμένος δρομέας μπορεί να ανοίξει ξανά. Δεν επιτρέπεται το κλείσιμο ενός δρομέα που δεν έχει ανοίξει.

Κάθε DBMS έχει τις δικές του ιδιαιτερότητες στη χρήση δρομέα.

Δυνατότητες χρήσης δρομέων στο Oracle

Υπάρχουν τέσσερα χαρακτηριστικά δρομέα στο PL/SQL %ΒΡΕΘΗΚΑΝ, %ΔΕΝ ΒΡΕΘΗΚΕ, %ΕΙΝΑΙ ΑΝΟΙΧΤΟΚαι %ROWCOUNT. Τα χαρακτηριστικά του δρομέα δηλώνονται όπως οι τελεστές %TYPE και %ROWTYPE, στα δεξιά του ονόματος του δρομέα.

% FOUND χαρακτηριστικό

%NOTFOUND χαρακτηριστικό

Το χαρακτηριστικό %NOTFOUND είναι ακριβώς το αντίθετο του %FOUND.

Χαρακτηριστικό %ISOPEN

Το χαρακτηριστικό %ISOPEN υποδεικνύει μόνο εάν ο δρομέας είναι ανοιχτός ή όχι.

%ROWCOUNT χαρακτηριστικό

Χαρακτηριστικό %ROWCOUNTείναι ένα αριθμητικό χαρακτηριστικό που επιστρέφει τον αριθμό των σειρών που διαβάζονται από τον δρομέα σε μια συγκεκριμένη χρονική στιγμή.

Παράδειγμα δρομέα SQL σε ένα Oracle DBMS

Δήλωση v_id managers.id %TYPE; v_name managers.name%TYPE; v_comm managers.comm%TYPE; δρομέας crs για επιλογή αναγνωριστικού, όνομα, άθροισμα(comm) ως comm από διαχειριστές όπου τα δεδομένα μεταξύ "2014-11-01" και "2014-11-30" ομαδοποιούνται ανά αναγνωριστικό, όνομα. ξεκινήστε να ανοίγετε το crs. βρόχος ΕΞΟΔΟΣ ΟΤΑΝ crs%ΔΕΝ ΒΡΕΘΗΚΕ. FETCH crs σε v_id, v_name, v_comm; εισαγάγετε τις τιμές bonus(id, name, comm) (crs.id, crs.name, crs.comm); βρόχος τέλος? διαπράττω; Κλείσιμο crs? τέλος;

Δυνατότητες χρήσης δρομέων σε διακομιστή SQL

Οι δρομείς που χρησιμοποιούνται στο MSSQL μπορούν να είναι διαδοχικοί ή με δυνατότητα κύλισης. Το Sequential σάς επιτρέπει να επιλέξετε δεδομένα μόνο προς μία κατεύθυνση - από την αρχή μέχρι το τέλος. Οι δρομείς με δυνατότητα κύλισης επιτρέπουν την κίνηση και προς τις δύο κατευθύνσεις και σας επιτρέπουν να μεταβείτε σε μια αυθαίρετη σειρά στο σύνολο αποτελεσμάτων του δρομέα.

Ο SQL Server υποστηρίζει δρομείς στατικούς, δυναμικούς, διαδοχικούς και βασισμένους σε keyset.

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

Ένας δυναμικός δρομέας απαιτεί πρόσθετους πόρους δικτύου και λογισμικού. Όταν χρησιμοποιείτε δυναμικούς δρομείς, δεν δημιουργείται πλήρες αντίγραφο των δεδομένων, αλλά οι επιλογές από τους πίνακες προέλευσης εκτελούνται μόνο όταν ο χρήστης έχει πρόσβαση σε συγκεκριμένα δεδομένα. Κατά τη διάρκεια της ανάκτησης, ο διακομιστής κλειδώνει τις σειρές και τυχόν αλλαγές που κάνει ο χρήστης στο πλήρες σύνολο αποτελεσμάτων του δρομέα θα είναι ορατές στον κέρσορα. Ωστόσο, από τη στιγμή που ο δρομέας έχει ανακτήσει δεδομένα, οι αλλαγές που έγιναν από άλλο χρήστη δεν θα αντικατοπτρίζονται πλέον στον κέρσορα.

Ένας δρομέας που ελέγχεται από ένα σύνολο πλήκτρων έχει ιδιότητες μεταξύ στατικής και δυναμικής. Τα αρχεία προσδιορίζονται τη στιγμή της δειγματοληψίας και έτσι οι αλλαγές παρακολουθούνται. Αυτός ο τύπος δρομέα είναι χρήσιμος κατά την εφαρμογή κύλισης προς τα πίσω. Σε αυτήν την περίπτωση, οι προσθήκες και οι διαγραφές δεδομένων δεν είναι ορατές μέχρι να ενημερωθούν οι πληροφορίες και να επιλέξει ο κέρσορας νέα έκδοσηκαταγράφει εάν έχουν γίνει αλλαγές σε αυτά.

Οι στατικοί δρομείς χρησιμοποιούνται καλύτερα για συστήματα επεξεργασίας πληροφοριών, π.χ. για συστήματα αναφοράς ή για στατιστικούς και αναλυτικούς σκοπούς. Ένας στατικός δρομέας είναι καλύτερος στην ανάκτηση μεγάλων ποσοτήτων δεδομένων. Σε συστήματα ηλεκτρονικών αγορών ή κρατήσεων αντικειμένων (θέσεις, εισιτήρια), είναι απαραίτητο να γίνεται δυναμική αντίληψη των ενημερωμένων πληροφοριών καθώς γίνονται αλλαγές. Σε τέτοιες περιπτώσεις, χρησιμοποιείται ένας δυναμικός δρομέας. Σε αυτές τις εφαρμογές, ο όγκος των δεδομένων που μεταφέρονται είναι συνήθως μικρός και έχει πρόσβαση σε ατομικό επίπεδο εγγραφής.

Οι διαδοχικοί δρομείς δεν επιτρέπουν την ανάκτηση δεδομένων προς την αντίστροφη κατεύθυνση, μόνο από την αρχή έως το τέλος του δρομέα. Ένας διαδοχικός δρομέας δεν αποθηκεύει ένα σύνολο από όλες τις σειρές δεδομένων. Διαβάζονται από τη βάση δεδομένων αμέσως μόλις γίνει μια επιλογή στον κέρσορα, η οποία επιτρέπει τη δυναμική απεικόνιση όλων των αλλαγών που έγιναν από τους χρήστες στη βάση δεδομένων χρησιμοποιώντας τις εντολές INSERT, UPDATE, DELETE. Ο κέρσορας διαβάζει την πιο πρόσφατη κατάσταση δεδομένων.

Δήλωση δρομέα

Δήλωση cursor_name cursor για SELECT_statement ]]

Όταν χρησιμοποιείτε μια λέξη-κλειδί ΤΟΠΙΚΟΣΘα δημιουργηθεί ένας τοπικός δρομέας που είναι ορατός μόνο εντός του μπλοκ, της ενεργοποίησης, της αποθηκευμένης διαδικασίας ή της συνάρτησης που ορίζει ο χρήστης. Λέξη-κλειδί ΠΑΓΚΟΣΜΙΑ, ορίζει έναν καθολικό δρομέα που υπάρχει μέχρι να κλείσει η τρέχουσα σύνδεση.

Χειριστής FORWARD_ONLYορίζει έναν διαδοχικό δρομέα που επιτρέπει την ανάκτηση δεδομένων μόνο προς την κατεύθυνση από την πρώτη γραμμή προς την τελευταία. Όταν χρησιμοποιείτε τον χειριστή ΠΑΠΥΡΟΣδημιουργείται ένας δρομέας με δυνατότητα κύλισης που επιτρέπει την πρόσβαση στα δεδομένα με οποιαδήποτε σειρά και προς οποιαδήποτε κατεύθυνση.

Ο τύπος του δρομέα καθορίζεται από τους τελεστές:

  • STATIC - δημιουργία στατικού δρομέα.
  • DYNAMIC - δημιουργία δυναμικού δρομέα.
  • KEYSET - δημιουργία δρομέα κλειδιού.

Αν για δρομέα ΜΟΝΟ ΓΙΑ ΑΝΑΓΝΩΣΗπροσδιορίστε το όρισμα ΓΡΗΓΟΡΗ ΠΡΟΩΘΗΣΗ, τότε ο δρομέας που δημιουργήθηκε θα βελτιστοποιηθεί για γρήγορη πρόσβασηστα δεδομένα. Αυτό το όρισμα δεν μπορεί να χρησιμοποιηθεί σε συνδυασμό με ορίσματα FORWARD_ONLYΚαι ΑΙΣΙΟΔΟΞΟΣ.

Εάν ο κέρσορας έχει δημιουργηθεί με τον τελεστή ΑΙΣΙΟΔΟΞΟΣ, τότε απαγορεύεται η αλλαγή ή η διαγραφή σειρών που άλλαξαν μετά το άνοιγμα του δρομέα.

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

Ανάκτηση δεδομένων από δρομέα, ανάκτηση

Αμέσως μετά το άνοιγμα του δρομέα, μπορείτε να λάβετε τα περιεχόμενά του χρησιμοποιώντας την ακόλουθη εντολή:

Όταν χρησιμοποιείτε τον χειριστή ΠΡΩΤΑθα επιστραφεί η πρώτη σειρά του συνόλου αποτελεσμάτων του δρομέα, η οποία γίνεται η τρέχουσα σειρά. Όταν καθορίζεται ΤΕΛΕΥΤΑΙΟΣθα επιστραφεί η τελευταία γραμμή του δρομέα. Γίνεται και η τρέχουσα γραμμή.

Κατά τον καθορισμό ενός χειριστή ΕΠΟΜΕΝΟθα επιστραφεί η σειρά αμέσως μετά την τρέχουσα στο σύνολο αποτελεσμάτων. Αυτή η γραμμή γίνεται η τρέχουσα γραμμή. Προεπιλεγμένη εντολή ΦΕΡΩχρησιμοποιεί ακριβώς αυτή τη μέθοδο ανάκτησης σειρών.

Κατά τον καθορισμό ενός χειριστή ΠΡΙΝθα επιστραφεί η γραμμή πριν από την τρέχουσα. Αυτή η γραμμή γίνεται η τρέχουσα γραμμή.

Χειριστής ΑΠΟΛΥΤΟ (αριθμός_γραμμής | @line_number_variable)επιστρέφει μια γραμμή με τον απόλυτο τακτικό της αριθμό στο πλήρες σύνολο αποτελεσμάτων του δρομέα. Ο αριθμός γραμμής μπορεί να καθοριστεί χρησιμοποιώντας μια σταθερά ή ως όνομα μιας μεταβλητής στην οποία είναι αποθηκευμένος ο αριθμός γραμμής. Η μεταβλητή πρέπει να είναι ακέραιος τύπος δεδομένων. Υποδεικνύονται τόσο οι θετικές όσο και οι αρνητικές τιμές. Κατά τον καθορισμό μιας θετικής τιμής, η συμβολοσειρά μετράται από την αρχή του συνόλου, ενώ μια αρνητική τιμή μετράται από το τέλος. Η επιλεγμένη γραμμή γίνεται η τρέχουσα γραμμή. Εάν οριστεί μηδενική τιμή, δεν επιστρέφεται καμία σειρά.

Διαφωνία ΣΧΕΤΙΚΟ (αριθμός σειρών | @variable αριθμός σειρών)επιστρέφει τη μετατόπιση γραμμής τον καθορισμένο αριθμό γραμμών μετά την τρέχουσα. Εάν καθορίσετε έναν αρνητικό αριθμό σειρών, θα επιστραφεί η σειρά που είναι ο καθορισμένος αριθμός σειρών πριν από την τρέχουσα. Ο καθορισμός μιας μηδενικής τιμής θα επιστρέψει την τρέχουσα σειρά. Η σειρά που επιστρέφεται γίνεται η τρέχουσα σειρά.

Για να ανοίξετε έναν καθολικό δρομέα, πρέπει να καθορίσετε μια λέξη-κλειδί πριν από το όνομά του ΠΑΓΚΟΣΜΙΑ. Το όνομα του δρομέα μπορεί επίσης να καθοριστεί χρησιμοποιώντας μια μεταβλητή.

Στην έκφραση INTO @variable_name [,...n]ορίζεται μια λίστα μεταβλητών στην οποία θα αποθηκευτούν οι αντίστοιχες τιμές στηλών της επιστρεφόμενης σειράς. Η σειρά των μεταβλητών πρέπει να ταιριάζει με τη σειρά των στηλών στον κέρσορα και ο τύπος δεδομένων της μεταβλητής πρέπει να ταιριάζει με τον τύπο δεδομένων στη στήλη του δρομέα.

Αλλαγή και διαγραφή δεδομένων με χρήση δρομέα

Για να αλλάξετε δεδομένα χρησιμοποιώντας δρομέα, πρέπει να εκδώσετε μια εντολή UPDATE στην ακόλουθη μορφή:

Σε μία λειτουργία, οι τιμές πολλών στηλών της τρέχουσας σειράς του δρομέα μπορούν να αλλάξουν, αλλά όλες πρέπει να ανήκουν στον ίδιο πίνακα.

Για να διαγράψετε δεδομένα χρησιμοποιώντας δρομέα, χρησιμοποιήστε την εντολή DELETE στην ακόλουθη μορφή:

Ως αποτέλεσμα, η τρέχουσα γραμμή στον κέρσορα θα διαγραφεί.

Απελευθέρωση μνήμης, κατανομή

Για να αφαιρέσετε έναν δρομέα από τη μνήμη, χρησιμοποιήστε την εντολή

Κατανομή ονόματος_δρομέα.

Χαρακτηριστικό @@FETCH_STATUS

Για να προσδιορίσετε την παρουσία σειρών στον κέρσορα, θα πρέπει να χρησιμοποιήσετε μια καθολική μεταβλητή @@FETCH_STATUS, η οποία παίρνει μια μη μηδενική τιμή εάν δεν υπάρχουν άλλες σειρές στον κέρσορα. Εάν το σύνολο των σειρών δεν έχει ακόμη εξαντληθεί, τότε το @@FETCH_STATUS είναι ίσο με μηδέν.

Παράδειγμα δρομέα σε διακομιστή SQL

Δηλώστε @company varchar(50), @manager varchar(50), @message varchar(256); δήλωση crs_clients δρομέα τοπικό για επιλεγμένη εταιρεία, διαχειριστής από πελάτες όπου πόλη = "Μόσχα" παραγγελία ανά εταιρεία, διαχειριστή. εκτύπωση "Λίστα πελατών"? άνοιγμα crs_clients; ανάκτηση του επόμενου από crs_clients σε @company, @manager; ενώ @@FETCH_STATUS = 0 start επιλέξτε @message = "Εταιρεία " + @company + " manager " + @manager; εκτύπωση @message; -- μεταβείτε στην επόμενη ανάκτηση εγγραφής από το crs_clients στο @company, @manager. τέλος; κλείσιμο crs_clients? deallocate crs_clients;

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

Έννοια του δρομέα

Ένα ερώτημα σε σχέση με μια σχεσιακή βάση δεδομένων επιστρέφει συνήθως πολλές σειρές (εγγραφές) δεδομένων, αλλά η εφαρμογή επεξεργάζεται μόνο μία εγγραφή κάθε φορά. Ακόμα κι αν ασχολείται με πολλές σειρές ταυτόχρονα (για παράδειγμα, εμφανίζει δεδομένα με τη μορφή υπολογιστικών φύλλων), ο αριθμός τους εξακολουθεί να είναι περιορισμένος. Επιπλέον, κατά την τροποποίηση, τη διαγραφή ή την προσθήκη δεδομένων, η μονάδα εργασίας είναι η σειρά. Σε αυτήν την περίπτωση, η έννοια του δρομέα έρχεται στο προσκήνιο και σε αυτό το πλαίσιο, ο κέρσορας είναι ένας δείκτης σε μια σειρά.

Ένας δρομέας στο SQL είναι μια περιοχή στη μνήμη της βάσης δεδομένων που έχει σχεδιαστεί για να διατηρεί την τελευταία πρόταση SQL. Εάν η τρέχουσα δήλωση είναι ένα ερώτημα βάσης δεδομένων, μια σειρά δεδομένων ερωτήματος που ονομάζεται τρέχουσα τιμή ή τρέχουσα γραμμή δρομέα, αποθηκεύεται επίσης στη μνήμη. Η καθορισμένη περιοχή στη μνήμη ονομάζεται και είναι προσβάσιμη σε προγράμματα εφαρμογών.

Συνήθως, οι δρομείς χρησιμοποιούνται για να επιλέξουν από μια βάση δεδομένων ένα υποσύνολο των πληροφοριών που είναι αποθηκευμένες σε αυτήν. Ανά πάσα στιγμή, μια γραμμή δρομέα μπορεί να ελεγχθεί από το πρόγραμμα εφαρμογής. Οι δρομείς χρησιμοποιούνται συχνά σε Δηλώσεις SQL, ενσωματωμένο σε προγράμματα εφαρμογών γραμμένα σε διαδικαστικές γλώσσες. Μερικά από αυτά δημιουργούνται έμμεσα από τον διακομιστή της βάσης δεδομένων, ενώ άλλα ορίζονται από προγραμματιστές.

Σύμφωνα με το πρότυπο SQL, όταν εργάζεστε με δρομείς, μπορούν να διακριθούν οι ακόλουθες κύριες ενέργειες:

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

Ο ορισμός του δρομέα μπορεί να διαφέρει ελαφρώς μεταξύ των υλοποιήσεων. Για παράδειγμα, μερικές φορές ένας προγραμματιστής πρέπει να ελευθερώσει ρητά τη μνήμη που έχει εκχωρηθεί για έναν δρομέα. Μετά απελευθερώστε τον κέρσοραΗ σχετική μνήμη ελευθερώνεται επίσης. Αυτό καθιστά δυνατή την επαναχρησιμοποίηση του ονόματός του. Σε άλλες υλοποιήσεις όταν κλείνοντας τον κέρσοραΗ απελευθέρωση μνήμης συμβαίνει σιωπηρά. Αμέσως μετά την ανάκτηση, γίνεται διαθέσιμο για άλλες επεμβάσεις: ανοίγοντας άλλον δρομέακαι τα λοιπά.

Σε ορισμένες περιπτώσεις, η χρήση δρομέα είναι αναπόφευκτη. Ωστόσο, εάν είναι δυνατόν, αυτό θα πρέπει να αποφεύγεται και να λειτουργεί με τυπικές εντολές επεξεργασίας δεδομένων: SELECT, UPDATE, INSERT, DELETE. Εκτός από το γεγονός ότι οι δρομείς δεν επιτρέπουν λειτουργίες τροποποίησης σε ολόκληρο τον όγκο δεδομένων, η ταχύτητα εκτέλεσης εργασιών επεξεργασίας δεδομένων με χρήση δρομέα είναι αισθητά χαμηλότερη από αυτή των τυπικών εργαλείων SQL.

Υλοποίηση δρομέων σε περιβάλλον MS SQL Server

Ο SQL Server υποστηρίζει τρεις τύπους δρομέων:

  • Οι δρομείς SQL χρησιμοποιούνται κυρίως σε ενεργοποιητές, αποθηκευμένες διαδικασίες και σενάρια.
  • Οι δρομείς διακομιστή λειτουργούν στον διακομιστή και υλοποιούν τη διεπαφή προγραμματισμού εφαρμογών για ODBC, OLE DB, DB_Library.
  • Οι δρομείς πελάτη εφαρμόζονται στον ίδιο τον πελάτη. Λαμβάνουν ολόκληρο το σύνολο αποτελεσμάτων των σειρών από τον διακομιστή και το αποθηκεύουν τοπικά, γεγονός που επιταχύνει την επεξεργασία δεδομένων μειώνοντας τον χαμένο χρόνο που δαπανάται σε λειτουργίες δικτύου.

Διαφορετικοί τύποι εφαρμογών πολλών χρηστών απαιτούν διαφορετικούς τύπους παράλληλης πρόσβασης στα δεδομένα. Ορισμένες εφαρμογές απαιτούν άμεση πρόσβαση σε πληροφορίες σχετικά με αλλαγές στη βάση δεδομένων. Αυτό είναι χαρακτηριστικό για τα συστήματα κρατήσεων εισιτηρίων. Σε άλλες περιπτώσεις, όπως τα συστήματα στατιστικής αναφοράς, η σταθερότητα των δεδομένων είναι σημαντική γιατί εάν τροποποιείται συνεχώς, τα προγράμματα δεν θα είναι σε θέση να εμφανίζουν πληροφορίες αποτελεσματικά. Διαφορετικές εφαρμογές χρειάζονται διαφορετικές υλοποιήσεις δρομέων.

Στον SQL Server, οι τύποι δρομέα διαφέρουν ως προς τις δυνατότητες που παρέχουν. Ο τύπος του δρομέα καθορίζεται στο στάδιο της δημιουργίας του και δεν μπορεί να αλλάξει. Ορισμένοι τύποι δρομέων μπορούν να ανιχνεύσουν αλλαγές που έγιναν από άλλους χρήστες σε σειρές που περιλαμβάνονται στο σύνολο αποτελεσμάτων. Ωστόσο, ο SQL Server παρακολουθεί τις αλλαγές σε τέτοιες σειρές μόνο κατά την πρόσβαση στη σειρά και δεν επιτρέπει την τροποποίηση των αλλαγών αφού έχει ήδη διαβαστεί η σειρά.

Οι δρομείς χωρίζονται σε δύο κατηγορίες: ακολουθητικόςκαι κυλιόμενο. Συνεχήςσας επιτρέπουν να επιλέξετε δεδομένα μόνο προς μία κατεύθυνση - από την αρχή μέχρι το τέλος. Δρομείς με δυνατότητα κύλισηςπαρέχουν μεγαλύτερη ελευθερία δράσης - είναι δυνατό να μετακινηθείτε και προς τις δύο κατευθύνσεις και να μεταβείτε σε μια αυθαίρετη σειρά του συνόλου αποτελεσμάτων του δρομέα. Εάν το πρόγραμμα μπορεί να τροποποιήσει τα δεδομένα στα οποία δείχνει ο κέρσορας, ονομάζεται κύλιση και τροποποιήσιμο. Μιλώντας για δρομείς, δεν πρέπει να ξεχνάμε την απομόνωση συναλλαγών. Όταν ένας χρήστης τροποποιεί μια εγγραφή, ένας άλλος τη διαβάζει χρησιμοποιώντας το δικό του δρομέα και επιπλέον, μπορεί να τροποποιήσει την ίδια εγγραφή, γεγονός που καθιστά απαραίτητη τη διατήρηση της ακεραιότητας των δεδομένων.

Ο SQL Server υποστηρίζει στατικά, δυναμικά, ακολουθητικόςκαι ελέγχεται από ένα σύνολο πλήκτρων.

Στο σχήμα με στατικό δρομέαΟι πληροφορίες διαβάζονται από τη βάση δεδομένων μία φορά και αποθηκεύονται ως στιγμιότυπο (κάποια χρονική στιγμή), επομένως οι αλλαγές που έγιναν στη βάση δεδομένων από άλλο χρήστη δεν είναι ορατές. Για λίγο ανοίγοντας τον κέρσοραο διακομιστής θέτει ένα κλείδωμα σε όλες τις σειρές που περιλαμβάνονται στο πλήρες σύνολο αποτελεσμάτων του. Στατικός κέρσοραςδεν αλλάζει μετά τη δημιουργία και εμφανίζει πάντα το σύνολο δεδομένων που υπήρχε κατά το άνοιγμά του.

Εάν άλλοι χρήστες αλλάξουν τα δεδομένα που περιλαμβάνονται στον δρομέα στον πίνακα προέλευσης, αυτό δεν θα επηρεάσει το στατικό δρομέα.

ΣΕ στατικό δρομέαΔεν είναι δυνατή η πραγματοποίηση αλλαγών, επομένως ανοίγει πάντα σε λειτουργία μόνο για ανάγνωση.

Δυναμικός κέρσοραςδιατηρεί τα δεδομένα σε «ζωντανή» κατάσταση, αλλά αυτό απαιτεί πόρους δικτύου και λογισμικού. Χρησιμοποιώντας δυναμικούς δρομείςδεν δημιουργείται πλήρες αντίγραφο των δεδομένων προέλευσης, αλλά εκτελείται μια δυναμική επιλογή από τους πίνακες προέλευσης μόνο όταν ο χρήστης έχει πρόσβαση σε συγκεκριμένα δεδομένα. Κατά τη διάρκεια της ανάκτησης, ο διακομιστής κλειδώνει τις σειρές και τυχόν αλλαγές που κάνει ο χρήστης στο πλήρες σύνολο αποτελεσμάτων του δρομέα θα είναι ορατές στον κέρσορα. Ωστόσο, εάν κάποιος άλλος χρήστης έχει κάνει αλλαγές μετά την ανάκτηση των δεδομένων από τον κέρσορα, αυτές δεν θα αντικατοπτρίζονται στον κέρσορα.

Δρομέας που ελέγχεται από ένα σύνολο πλήκτρων, βρίσκεται στη μέση μεταξύ αυτών των άκρων. Τα αρχεία προσδιορίζονται τη στιγμή της δειγματοληψίας και έτσι οι αλλαγές παρακολουθούνται. Αυτός ο τύπος δρομέα είναι χρήσιμος κατά την εφαρμογή κύλισης προς τα πίσω - τότε οι προσθήκες και οι διαγραφές σειρών δεν είναι ορατές μέχρι να ενημερωθούν οι πληροφορίες και το πρόγραμμα οδήγησης επιλέγει μια νέα έκδοση της εγγραφής εάν έχουν γίνει αλλαγές σε αυτήν.

Διαδοχικοί δρομείςδεν επιτρέπεται η ανάκτηση δεδομένων προς την αντίστροφη κατεύθυνση. Ο χρήστης μπορεί να επιλέξει μόνο σειρές από την αρχή έως το τέλος του δρομέα. Σειριακός δρομέαςδεν αποθηκεύει ένα σύνολο από όλες τις σειρές. Διαβάζονται από τη βάση δεδομένων αμέσως μόλις επιλεγούν στον κέρσορα, ο οποίος επιτρέπει σε όλες τις αλλαγές που γίνονται από τους χρήστες στη βάση δεδομένων να αντικατοπτρίζονται δυναμικά χρησιμοποιώντας εντολές INSERT, UPDATE, DELETE. Ο κέρσορας δείχνει την πιο πρόσφατη κατάσταση των δεδομένων.

Στατικοί δρομείςπαρέχει μια σταθερή προβολή των δεδομένων. Είναι καλές για συστήματα "αποθήκευσης" πληροφοριών: εφαρμογές για συστήματα αναφοράς ή για στατιστικούς και αναλυτικούς σκοπούς. Εκτός, στατικό δρομέααντιμετωπίζει καλύτερα από άλλους με τη δειγματοληψία μεγάλων ποσοτήτων δεδομένων. Αντίθετα, τα ηλεκτρονικά συστήματα αγορών ή κρατήσεων εισιτηρίων απαιτούν δυναμική αντίληψη των ενημερωμένων πληροφοριών καθώς γίνονται αλλαγές. Σε τέτοιες περιπτώσεις χρησιμοποιείται δυναμικός κέρσορας. Σε αυτές τις εφαρμογές, ο όγκος των δεδομένων που μεταφέρονται είναι συνήθως μικρός και έχει πρόσβαση σε επίπεδο σειράς (ατομική εγγραφή). Η ομαδική πρόσβαση είναι πολύ σπάνια.

Διαχείριση δρομέα σε περιβάλλον MS SQL Server

Έλεγχος δρομέαυλοποιείται εκτελώντας τις ακόλουθες εντολές:

  • ΔΗΛΩΣΤΕ - δημιουργία ή δήλωση δρομέα;
  • ΑΝΟΙΞΕ - άνοιγμα κέρσορα, δηλ. συμπληρώνοντάς το με δεδομένα.
  • ΦΕΡΩ επιλογή από τον κέρσορακαι αλλαγή σειρών δεδομένων χρησιμοποιώντας τον κέρσορα.
  • ΚΛΕΙΣΕ - κλείνοντας τον κέρσορα;
  • ΑΝΑΘΕΣΗ - ελευθερώνοντας τον κέρσορα, δηλ. διαγραφή του δρομέα ως αντικείμενο.

Δήλωση δρομέα

Το πρότυπο SQL παρέχει την ακόλουθη εντολή για τη δημιουργία ενός δρομέα:

Η χρήση της λέξης-κλειδιού ΑΣΑΘΗΣ θα δημιουργήσει στατικό δρομέα. Αλλαγές δεδομένωνδεν επιτρέπονται, επιπλέον δεν εμφανίζονται αλλαγές που έγιναν από άλλους χρήστες. Εάν λείπει η λέξη-κλειδί ΑΝΕΥΑΙΣΘΗΤΟ, α δυναμικός κέρσορας.

Όταν καθορίζετε τη λέξη-κλειδί SCROLL, ο δρομέας που δημιουργήθηκε μπορεί να μετακινηθεί προς οποιαδήποτε κατεύθυνση, επιτρέποντάς σας να χρησιμοποιήσετε οποιεσδήποτε εντολές επιλογής. Εάν αυτό το όρισμα παραλειφθεί, ο δρομέας θα είναι σταθερός, δηλ. η προβολή του θα είναι δυνατή μόνο προς μία κατεύθυνση - από την αρχή μέχρι το τέλος.

Η δήλωση SELECT καθορίζει το σώμα του αιτήματος SELECT, το οποίο καθορίζει το σύνολο γραμμών που προκύπτει για τον κέρσορα.

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

Η δημιουργία ενός δρομέα με ένα όρισμα ΓΙΑ ΕΝΗΜΕΡΩΣΗ σάς επιτρέπει να εκτελέσετε στον κέρσορα αλλαγή δεδομένωνείτε στις καθορισμένες στήλες είτε, ελλείψει του ορίσματος OF στήλη_όνομα, σε όλες τις στήλες.

Στο περιβάλλον του MS SQL Server, η ακόλουθη σύνταξη για την εντολή δημιουργίας δρομέα είναι αποδεκτή:

<создание_курсора>::= ΔΗΛΩΣΗ δρομέα_όνομα ΔΡΟΜΕΤΗ ΓΙΑ SELECT_statement ]]

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

Εάν έχει καθοριστεί η λέξη-κλειδί GLOBAL, δημιουργείται ένας καθολικός δρομέας. υπάρχει μέχρι να κλείσει η τρέχουσα σύνδεση.

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

Ο καθορισμός του SCROLL δημιουργεί με δυνατότητα κύλισης; Τα δεδομένα είναι προσβάσιμα με οποιαδήποτε σειρά και προς οποιαδήποτε κατεύθυνση.

Ο καθορισμός STATIC δημιουργεί στατικό δρομέα.

Ο καθορισμός του KEYSET δημιουργεί έναν δρομέα κλειδιού.

Ο καθορισμός του DYNAMIC δημιουργεί δυναμικός κέρσορας.

Εάν καθορίσετε το όρισμα FAST_FORWARD για έναν δρομέα READ_ONLY, ο δρομέας που δημιουργήθηκε θα βελτιστοποιηθεί για γρήγορη πρόσβαση στα δεδομένα. Αυτό το όρισμα δεν μπορεί να χρησιμοποιηθεί σε συνδυασμό με τα ορίσματα FORWARD_ONLY ή OPTIMISTIC.

Ένας δρομέας που δημιουργήθηκε με το όρισμα OPTIMISTIC εμποδίζει την τροποποίηση ή τη διαγραφή σειρών που τροποποιήθηκαν μετά ανοίγοντας τον κέρσορα.

Καθορίζοντας το όρισμα TYPE_WARNING, ο διακομιστής θα ενημερώσει τον χρήστη για μια σιωπηρή αλλαγή στον τύπο του δρομέα, εάν δεν είναι συμβατή με το ερώτημα SELECT.

Άνοιγμα του κέρσορα

Για ανοίγοντας τον κέρσορακαι συμπληρώνοντάς το με δεδομένα από το ερώτημα SELECT που καθορίστηκε κατά τη δημιουργία του δρομέα, χρησιμοποιήστε την ακόλουθη εντολή:

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

Ανάκτηση δεδομένων από δρομέα

Αμέσως μετά ανοίγοντας τον κέρσοραμπορείτε να επιλέξετε τα περιεχόμενά του (το αποτέλεσμα της εκτέλεσης του αντίστοιχου ερωτήματος) χρησιμοποιώντας την ακόλουθη εντολή:

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

Ο καθορισμός LAST επιστρέφει την πιο πρόσφατη σειρά του δρομέα. Γίνεται και η τρέχουσα γραμμή.

Ο καθορισμός NEXT επιστρέφει τη σειρά αμέσως μετά την τρέχουσα στο πλήρες σύνολο αποτελεσμάτων. Τώρα γίνεται επίκαιρο. Από προεπιλογή, η εντολή FETCH χρησιμοποιεί αυτήν τη μέθοδο για την ανάκτηση σειρών.

Η λέξη-κλειδί PRIOR επιστρέφει τη σειρά πριν από την τρέχουσα. Γίνεται επίκαιρο.

Διαφωνία ΑΠΟΛΥΤΟ (αριθμός_γραμμής | @line_number_variable)επιστρέφει μια γραμμή με τον απόλυτο τακτικό της αριθμό στο πλήρες σύνολο αποτελεσμάτων του δρομέα. Ο αριθμός γραμμής μπορεί να καθοριστεί χρησιμοποιώντας μια σταθερά ή ως όνομα μιας μεταβλητής στην οποία είναι αποθηκευμένος ο αριθμός γραμμής. Η μεταβλητή πρέπει να είναι ακέραιος τύπος δεδομένων. Υποδεικνύονται τόσο οι θετικές όσο και οι αρνητικές τιμές. Κατά τον καθορισμό μιας θετικής τιμής, η συμβολοσειρά μετράται από την αρχή του συνόλου, ενώ μια αρνητική τιμή μετράται από το τέλος. Η επιλεγμένη γραμμή γίνεται η τρέχουσα γραμμή. Εάν οριστεί μηδενική τιμή, δεν επιστρέφεται καμία σειρά.

Διαφωνία ΣΧΕΤΙΚΟ (αριθμός σειρών | @variable αριθμός σειρών)επιστρέφει τη γραμμή που είναι ο καθορισμένος αριθμός γραμμών μετά την τρέχουσα. Εάν καθορίσετε έναν αρνητικό αριθμό σειρών, θα επιστραφεί η σειρά που είναι ο καθορισμένος αριθμός σειρών πριν από την τρέχουσα. Ο καθορισμός μιας μηδενικής τιμής θα επιστρέψει την τρέχουσα σειρά. Η σειρά που επιστρέφεται γίνεται η τρέχουσα σειρά.

Προς την ανοίξτε τον καθολικό δρομέα, πρέπει να καθορίσετε τη λέξη-κλειδί GLOBAL πριν από το όνομά της. Το όνομα του δρομέα μπορεί επίσης να καθοριστεί χρησιμοποιώντας μια μεταβλητή.

Στο σχέδιο INTO @variable_name [,...n]καθορίζεται μια λίστα μεταβλητών στην οποία θα αποθηκευτούν οι αντίστοιχες τιμές στηλών της επιστρεφόμενης σειράς. Η σειρά καθορισμού των μεταβλητών πρέπει να ταιριάζει με τη σειρά των στηλών στον κέρσορα και ο τύπος δεδομένων της μεταβλητής πρέπει να ταιριάζει με τον τύπο δεδομένων στη στήλη του δρομέα. Εάν η κατασκευή INTO δεν έχει καθοριστεί, τότε η συμπεριφορά της εντολής FETCH θα μοιάζει με τη συμπεριφορά της εντολής SELECT - τα δεδομένα εμφανίζονται στην οθόνη.

Αλλαγή και διαγραφή δεδομένων

Για να κάνετε αλλαγές χρησιμοποιώντας έναν δρομέα, πρέπει να εκδώσετε μια εντολή UPDATE στην ακόλουθη μορφή:

Πολλές στήλες της τρέχουσας σειράς του δρομέα μπορούν να αλλάξουν σε μία λειτουργία, αλλά όλες πρέπει να ανήκουν στον ίδιο πίνακα.

Για να διαγράψετε δεδομένα χρησιμοποιώντας δρομέα, χρησιμοποιήστε την εντολή DELETE στην ακόλουθη μορφή:

Ως αποτέλεσμα, το ρεύμα που έχει οριστεί γραμμή στον κέρσορα θα διαγραφεί.

Κλείσιμο του δρομέα

Μετά το κλείσιμο, ο κέρσορας γίνεται απρόσιτος στους χρήστες του προγράμματος. Κατά το κλείσιμο αφαιρούνται όλες οι κλειδαριές που έχουν εγκατασταθεί κατά τη λειτουργία του. Το κλείσιμο μπορεί να εφαρμοστεί μόνο σε ανοιχτούς δρομείς. Κλειστό αλλά όχι ελευθερωμένος κέρσοραςμπορεί να ξανανοίξει. Δεν επιτρέπεται το κλείσιμο ενός δρομέα που δεν έχει ανοίξει.

Αφήστε τον κέρσορα

Κλείσιμο του δρομέαδεν απελευθερώνει απαραίτητα τη μνήμη που σχετίζεται με αυτό. Ορισμένες υλοποιήσεις πρέπει να το αναθέσουν ρητά χρησιμοποιώντας την πρόταση DEALLOCATE. Μετά απελευθερώστε τον κέρσοραΗ μνήμη ελευθερώνεται επίσης, καθιστώντας δυνατή την επαναχρησιμοποίηση του ονόματος του δρομέα.

Για να ελέγξετε εάν έχει φτάσει το τέλος του δρομέα, συνιστάται να χρησιμοποιήσετε τη συνάρτηση: @@FETCH_STATUS

Η συνάρτηση @@FETCH_STATUS επιστρέφει:

0 εάν η ανάκτηση ήταν επιτυχής.

1 εάν η ανάκτηση απέτυχε λόγω προσπάθειας ανάκτησης μιας γραμμής έξω από τον κέρσορα.

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

DECLARE @id_kl INT, @firm VARCHAR(50), @fam VARCHAR(50), @message VARCHAR(80), @nam VARCHAR(50), @d DATETIME, @p INT, @s INT SET @s=0 PRINT "Λίστα αγορών" ΔΗΛΩΣΤΕ klient_cursor CURSOR LOCAL FOR SELECT Client Code, Company, Last Name FROM Client WHERE City="Moscow" ORDER BY Company, Last Name OPEN klient_cursor FETCH NEXT FROM klient_cursor INTO @id_kl, @STALE, @USFETCH_Fam =0 BEGIN SELECT @message="Πελάτης "+@fam+ "Company "+ @firm PRINT @message SELECT @message="Όνομα προϊόντος Ημερομηνία αγοράς Κόστος" PRINT @message ΔΗΛΩΣΗ tovar_cursor CURSOR FOR SELECT Product.Όνομα, Συναλλαγή.Ημερομηνία, Προϊόν .Τιμή* Συναλλαγή.Ποσότητα ΩΣ Κόστος ΑΠΟ Προϊόν ΕΣΩΤΕΡΙΚΗ ΣΥΝΔΕΣΗ Συναλλαγή ΣΤΟ Προϊόν. Κωδικός προϊόντος=Transaction.Κωδικός προϊόντος WHERE Συναλλαγή.Κωδικός πελάτη=@id_kl OPEN tovar_cursor FETCH NEXT FROM tovar_cursor INTO @nam, @d, @p IF @@FETCH_STATUS<>0 PRINT "No shoppings" WHILE @@FETCH_STATUS=0 BEGIN SELECT @message=" "+@nam+" "+ CAST(@d AS CHAR(12))+" "+ CAST(@p AS CHAR(6)) PRINT @message SET @s=@s+@p FETCH NEXT FROM tovar_cursor INTO @nam, @d, @p END CLOSE tovar_cursor DEALLOCATE tovar_cursor SELECT @message="Συνολικό κόστος "+ CAST(@s AS CHAR(6)) PRINT @message -- μετακίνηση στον επόμενο πελάτη-- FETCH NEXT FROM klient_cursor INTO @id_kl, @firm, @fam END CLOSE klient_cursor DEALLOCATE klient_cursor Παράδειγμα 13.6. Δρομέας για την εμφάνιση μιας λίστας αγαθών που αγοράστηκαν από πελάτες από τη Μόσχα και το συνολικό κόστος τους.

Παράδειγμα 13.7.Αναπτύξτε έναν κυλιόμενο δρομέα για πελάτες από τη Μόσχα. Εάν ο αριθμός τηλεφώνου ξεκινά με 1, διαγράψτε τον πελάτη με αυτόν τον αριθμό και στην πρώτη καταχώρηση δρομέα αντικαταστήστε το πρώτο ψηφίο του αριθμού τηλεφώνου με 4.

ΔΗΛΩΣΤΕ @firm VARCHAR(50), @fam VARCHAR(50), @tel VARCHAR(8), @message VARCHAR(80) ΕΚΤΥΠΩΣΗ "Λίστα πελατών" ΔΗΛΩΣΤΕ klient_cursor CURSOR GLOBAL SCROLL KEYSET FOR SELECT Firm, Last name, Phone FROM WHERE City ="Moscow" ΠΑΡΑΓΓΕΛΙΑ ΑΠΟ Εταιρεία, Επώνυμο ΓΙΑ ΕΝΗΜΕΡΩΣΗ OPEN klient_cursor FETCH NEXT FROM klient_cursor INTO @firm, @fam, @tel WHILE @@FETCH_STATUS=0 BEGIN SELECT @message="Client "+@fam+ " Company "+ @firm " Τηλέφωνο "+ @tel PRINT @message -- εάν ο αριθμός τηλεφώνου ξεκινά με 1, -- διαγράψτε τον πελάτη με αυτόν τον αριθμό ΑΝ @tel LIKE '1%' DELETE Client WHERE CURRENT OF klient_cursor ALSE -- μεταβείτε στο επόμενο client FETCH NEXT FROM klient_cursor INTO @firm, @fam, @tel END FETCH ABSOLUTE 1 FROM klient_cursor INTO @firm, @fam, @tel -- στην πρώτη καταχώριση, αντικαταστήστε το πρώτο ψηφίο στον αριθμό τηλεφώνου με 4 ΕΝΗΜΕΡΩΣΗ ΣΕΤ πελάτη ='4' + RIGHT(@ tel,LEN(@tel)-1)) WHERE CURRENT OF klient_cursor SELECT @message="Client "+@fam+" Firm "+ @firm "Phone "+ @tel PRINT @message CLOSE klient_cursor DEALLOCATE klient_cursor Παράδειγμα 13.7. Με δυνατότητα κύλισης για πελάτες από τη Μόσχα.

Παράδειγμα 13.8.Χρήση δρομέα ως παράμετρος εξόδου της διαδικασίας. Η διαδικασία επιστρέφει ένα σύνολο δεδομένων - μια λίστα προϊόντων.

Η κλήση της διαδικασίας και η εκτύπωση δεδομένων από τον κέρσορα εξόδου εκτελούνται ως εξής:

ΔΗΛΩΣΤΕ @my_cur CURSOR ΔΗΛΩΣΤΕ @n VARCHAR(20) EXEC my_proc @cur=@my_cur ΑΝΑΓΚΗ ΕΞΟΔΟΥ ΕΠΟΜΕΝΟ ΑΠΟ @my_cur ΣΕ @n ΕΠΙΛΟΓΗ @n ΕΝΩ (@@FETCH_STATUS=0) ΑΡΧΙΣΤΕ ΛΗΨΗ ΕΠΟΜΕΝΟ ΑΠΟ @_n ΤΕΛΟΣ ΚΛΕΙΣΙΜΟ @my_cur ΑΝΑΘΕΣΗ @my_cur




Μπλουζα