sqlschool.gr logo


Articles of SQLschool.gr Team

Cosmos DB Server-side Operations

Antonios Chatzipavlis
Thursday 17 January 2019


Στην Cosmos DB υπάρχουν ,όπως και στις relational databases, διαδικασίες που τις θεωρούμε και είναι server side και δεν είναι άλλες από τα user defined functions, τις stored procedures και τους triggers και ως προς την λογική και την χρήση τους είναι όμοιες.

Η βασική διαφορά είναι ο κώδικας που γράφουμε σε αυτές στην Cosmos DB είναι σε JavaScript (ECMA-262) και μέσα σε αυτές κάνουμε κλήσεις στο Cosmos DB SQL API αντί να γράφουμε T-SQL.

Όλες αυτές οι διαδικασίες υλοποιούνται σαν αντικείμενα στο συγκεκριμένο collection και αυτό σημαίνει ότι δεν μπορώ να έχω τέτοια που να μοιράζονται σε πολλαπλά collections.

Όπως και στις relational databases έτσι και στην Cosmos DB τα πλεονεκτήματα των udfs, sp, triggers είναι γνωστά και αφορούν encapsulation, atomic transactions και performance.

Κάθε server side operation τρέχει σε ένα δικό του environment (sandbox) και όταν ολοκληρώσει οι πόροι που δαπανούσε επιστρέφονται για χρήση σε άλλα.

Αν θέλουμε να έχουμε state μεταξύ server side operation αυτό θα πρέπει να το κρατάμε στην database.


Σε κάθε stored procedure , trigger ο κώδικας που αυτές περιέχουν είναι ένα single logical transaction και όπως στις relational database έτσι και στην Cosmos DB υλοποιούνται τα ACID transactions properties.

Μάλιστα πρέπει να σημειωθεί ότι για να εξασφαλισθεί το consistency οι stored procedure / triggers εκτελούνται μόνο στην primary replica ενός Cosmos DB container.

Στην Cosmos DB οι stored procedures και οι triggers είναι ο μόνος τρόπος για να έχουμε multistatement transactions καθώς δεν υπάρχουν commands όπως BEGIN TRAN, COMMIT, ROLLBACK.

Όπως ανέφερα και παραπάνω κάθε stored procedure / trigger τρέχει στο δικό του sandbox με αυτό να σημαίνει ότι το κάθε transaction δεν μπορεί να έχει transaction scope εκτός από αυτό.

Με απλά λόγια αν έχω δύο triggers αυτοί δεν μπορούν να είναι στο ίδιο transaction.

Τα user defined functions δεν έχουν transactions καθώς εκτελούνται σαν μέρος ενός SELECT και σε αυτή την περίπτωση μπορώ να ορίσω μόνο το consistency level που επιθυμώ.

Πρέπει να τονισθεί ότι το κάθε transaction εφαρμόζεται σε ένα και μόνο ένα partition. Αυτό σημαίνει ότι αν έχω πολλαπλά partitions τότε θα πρέπει πχ στην εκτέλεση μιας stored procedure να έχω το partition key value για να μπορεί να ορισθεί το transaction scope.

JavaScript query API

Όπως αναφέρθηκε παραπάνω ο κώδικας που γράφω μέσα σε μια stored procedure / trigger / udf είναι javascript function.

Σε αυτή χρησιμοποιούμε το SQL API που μου παρέχει τα execution context, request, response και collection objects.

Η πρόσβαση σε αυτά γίνεται με buld-in objects/functions και είναι οι παρακάτω:

  • getContext() - δίνει το context object με το οποίο έχω πρόσβαση σε όλες τις λειτουργίες που μπορώ να κάνω μέσα σε Cosmos DB database.
  • getContext().getCollection() - επιστρέφει το collection στο οποίο δουλεύω
  • getConext().getResponse() - επιστρέφει το response object.
  • getConext().getRequest() - επιστρέφει το request object.

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

How to create a stored procedure / trigger / udf

Η δημιουργία sp / trigger / udf γίνεται είτε μέσα από το Azure Cosmos DB portal είτε χρησιμοποιώντας το αντίστοιχο object του .NET SDK

Image 1 - Create SP/Trigger/UDF from Azure Cosmos DB Portal
var Proc = new StoredProcedure
    Id = "procid",
    Body = @"function procfnct(c) {...}"

Uri collectionUri = UriFactory.CreateDocumentCollectionUri (_dbName, _collectionName);
StoredProcedure createdStoredProcedure = await client.CreateStoredProcedureAsync (collectionUri, Proc );

Πρέπει να επισημανθεί ότι η αναφορά στο κάθε ένα από αυτά κατά την χρήση του γίνεται με το Id που έχουμε δώσει και όχι με το όνομα της εκάστοτε function.

Stored Procedures

Τυπικά μια stored procedure μπορεί να έχει input parameters και εκτελεί μια διαδικασία. Μπορεί να επιστρέψει αποτέλεσμα και για να το κάνει αυτό θα πρέπει να χρησιμοποιηθεί η getContext().getReponse().setBody(…)

Ένας τυπικός τρόπος εκτέλεσης μια sp είναι με την χρήση της ExecuteStoredProcedureAsync.


Μοιάζουν με τις stored procedures αλλά δεν παίρνουν παραμέτρους ούτε επιστρέφουν κάτι.

Περιπτώσεις που χρησιμοποιούμε triggers είναι για data validation, transformation και auditing.

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

Υπάρχουν pre και post triggers είναι κατ' αντιστοιχία οι instead of και after triggers σε SQL Server.

Τα inserted , deleted virtual tables που έχουμε στον SQL Server εδώ τα έχουμε μέσω των getContext().getRequest().getOperationType() function - επιστρέφει το operation που έκανε τον trigger να εκτεστεί (insert,delete,replace), getContext().getRequest().getBody() function - επιστρέφει το document που επεξεργαζόμαστε.

Αν έχω pre-trigger χρησιμοποιώ την getContext().getResponset() να κάνω τις αλλαγές μου.

Ένα τυπικός τρόπος για την εκτέλεση ενός trigger γίνεται με την χρήση των PreTriggerInclude/PostTriggerInclude request options της CreateDocumentAsync. Αν δεν το κάνουμε αυτό τότε δεν θα εκτελεστεί κανένας καθώς στην Cosmos DB δεν έχουν την ίδια συμπεριφορά ως προς την εκτέλεση τους όπως στις relational databases.

User defined functions

Στην Cosmos DB μια udf είναι javascript function αλλά με μια σημαντική διαφορά, δεν έχουν access στο context object και χρησιμοποιούνται μόνο σε queries

Function VATPrice (Price) {
     return Price * 1.24;

SELECT o.Price, udf.VATPrice(o.Price) FROM Orders as o

Προσοχή στην εκτέλεση καθώς πρέπει να χρησιμοποιηθεί το udf prefix/collection


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.


What's New in SQL Server 2022 - Episodes

More Tips...

Become a member

If you want to receive updates from us become a member to our community.




sqlschool.gr © 2010-2024 All rights reserved

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