Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια
σε

 

Αρχική σελίδα Ιστολόγια Συζητήσεις Εκθέσεις Φωτογραφιών Αρχειοθήκες

Λαμβάνοντας την τιμή @@identity.

Îåêßíçóå áðü ôï ìÝëïò infoCENTER. Τελευταία δημοσίευση από το μέλος KelMan στις 25-01-2006, 02:53. Υπάρχουν 12 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  21-01-2006, 18:58 8856

    Λαμβάνοντας την τιμή @@identity.

    Σαν βάση χρησιμοποιώ SQL Server 2005 Express.

    Έχω ένα SQLCommand όπου χρησιμοποιώντας το UI του Visual Studio έχω φτιάξει το CommandText του SQLCommand. Θέλω όμως σαν τιμή επιστροφής μετά το INSERT που θα εκτελεί ο SQLCommand να λαμβάνω την IDENTITY τιμή που έχει δώαει ο SQL Server στην εγγραφή που μόλις έχει εισαχθεί.

    Μπορεί κάποιος να μου δώσει τα φώτα του, γιατί ότι και αν έχω δοκιμάσει δεν βγαίνει.

     

  •  21-01-2006, 21:12 8858 σε απάντηση της 8856

    Απ: Λαμβάνοντας την τιμή @@identity.

    Για να κάνεις κάτι τέτοιο, θα πρέπει εκεί που γράφεις το query, να πατήσεις από κάτω το κουμπί που λέει “Advanced Options” και κατόπιν, να βάλεις check στην επιλογή “Refresh the data table”. Έτσι, όταν θα καθορίσει τα Insert και Update statements που αντιστοιχούν στο InsertCommand και UpdateCommand, θα τους κάνει append ένα select ώστε να πάρεις πίσω όλα τα πεδία και να διαβάσεις τις τιμές που έχουν προέλθει από identity columns και default values. Δηλαδή αν το query σου είναι

    SELECT     CustomerID, Company, Email, Phone
    FROM         Customers

    αν ενεργοποιήσεις το Refresh the data table, αυτός θα παράγει τα εξής Insert και Update:

    INSERT INTO [Customers] ([Company], [Email], [Phone]) VALUES (@Company, @Email, @Phone);
    SELECT CustomerID, Company, Email, Phone FROM Customers WHERE (CustomerID = SCOPE_IDENTITY())

    και

    UPDATE [Customers] SET [Company] = @Company, [Email] = @Email, [Phone] = @Phone WHERE (([CustomerID] = @Original_CustomerID));
    SELECT CustomerID, Company, Email, Phone FROM Customers WHERE (CustomerID = @CustomerID)

    Μάλιστα, εδώ υπάρχει και μια βελτίωση στο ADO.NET 2.0. Στην προγούμενη έκδοση, ο generated κώδικας αντί για το SCOPE_IDENTITY() χρησιμοποιούσε το @@IDENTITY το οποίο δίνει λάθος τιμή σε περίπτωση που υπάρχει trigger που κάνει insert σε πίνακα με identity column. Το guideline ήταν λοιπόν, πάντοτε να αλλάζουμε κατόπιν τον κώδικα χειροκίνητα για να αποφύγουμε την περίπτωση που κάποιος θα πάει να βάλει ένα trigger στον πίνακά μας χωρίς να το ξέρουμε.


    Vir prudens non contra ventum mingit
  •  22-01-2006, 04:09 8861 σε απάντηση της 8858

    Απ: Λαμβάνοντας την τιμή @@identity.

    Το παράδειγμα που αναφέρεις ισχύει στην περίπτωση όπου υπάρχει SQLDataAdapter και με βάση αυτό πάω να φτιάξω με τη βοήθεια του wizard του την παραμετροποίησή του.

    Στην περίπτωση όμως που έχεις ένα σκέτο SQLCommand τότε στον wizard του για να δημιουργήσεις το CommandText δεν έχει τις επιλογές που αναφέρεις. Π.χ "Advanced Options". Τι μένει λοιπόν; Να το γράψεις εσύ μόνος σου τον παραπάνω κώδικα... Αμ δε όμως...

    Δεν ξέρω έχω ψάξει αρκετά για αυτό αλλά δεν βρήκα κάτι. Ευχαριστώ πάντως για τον χρόνο σου.
  •  22-01-2006, 10:12 8862 σε απάντηση της 8861

    Απ: Λαμβάνοντας την τιμή @@identity.

    Ναί όντως, αν δεν υπάρχει DataAdapter δεν σου δίνει αυτή τη δυνατότητα διότι δεν υπάρχει λόγος να στη δώσει. Δηλαδή όταν απλά κάνεις ExecuteΧ ένα Command, τα data, στην καλύτερη περίπτωση, σου έρχονται ως stream από τον DataReader. Δεν υπάρχει ένα Object για να γίνουν persist και να κρατήσει παλιές/νέες τιμές όπως γίνεται στην περίπτωση του DataAdapter που καταλήγουν σε ένα DataTable.

    Τώρα που το σκέφτομαι, γιατί δεν βάζεις το Insert σε ένα Stored Procedure που να περιέχει την ίδια την εντολή και κατόπιν ένα SET με το οποίο θα περνάς την τιμή του SCOPE_IDENTITY() σε μια output παράμετρο; Με αυτόν τον τρόπο θα έχεις τη δυνατότητα να διαβάσεις πίσω την τιμή της παραμέτρου.


    Vir prudens non contra ventum mingit
  •  22-01-2006, 16:42 8863 σε απάντηση της 8862

    Απ: Λαμβάνοντας την τιμή @@identity.

    Μέχρι τώρα Stored Procedures χρησιμοποιούσα. Είπα για πρώτη φορά να κάνω κάτι άλλο, και έπεσα πάνω σε αυτό. Τι να κάνουμε δεν μπορούμε να τα έχουμε όλα.
  •  24-01-2006, 13:39 8889 σε απάντηση της 8856

    Απ: Λαμβάνοντας την τιμή @@identity.

    Αφού τρέξει το Insert δοκίμασε το παρακάτω

    Dim newId As Int32

    Dim idCMD As SqlClient.SqlCommand

    'Conn το Connection που έχεις στην εφαρμογήσ σου

    conn.Open()

    ' Me.DataMember είναι το όνομα του πίνακα

    idCMD = New SqlClient.SqlCommand("SELECT IDENT_CURRENT('" & Me.DataMember & "')", conn)

    ' Retrieve the identity value

    newId = CType(idCMD.ExecuteScalar(), Int32)

     


    Ιωάννης Μανουσάκης
  •  24-01-2006, 14:42 8893 σε απάντηση της 8889

    Απ: Λαμβάνοντας την τιμή @@identity.

    Όχι, αυτός ο τρόπος δεν είναι καλός, εκτός αν φτιάχνεις μια εφαρμογή single-user και δεν υπάρχει πιθανότητα να πειραχθεί η βάση σου (πχ κάποιος να κάνει attach ένα trigger στον πίνακά σου).

    Το IDENT_CURRENT, όπως λέει και στα BOL, επιστρέφει το τελευταίο identity value από οποιοδήποτε session και οποιοδήποτε scope, που σημαίνει ότι θα σου φέρει λάθος τιμή σε διάφορες περιπτώσεις. Για παράδειγμα, στην περιπτώση που το insert σου προκάλεσε κάποιον trigger ο οποίος με τη σειρά του έκανε insert σε άλλον πίνακα με identity column ή στην περίπτωση που από τη στιγμή που έγινε το insert μέχρι να τρέξει αυτό το select, κάποιος άλλος χρήστης κάνει insert σε οποιονδήποτε πίνακα με identity column. Το πρώτο σενάριο μπορεί να συμβεί εκ των ουκ ανευ. Το δεύτερο σενάριο μπορεί να συμβεί εύκολα σε ένα OLTP σύστημα με αρκετά transactions.


    Vir prudens non contra ventum mingit
  •  24-01-2006, 16:43 8899 σε απάντηση της 8856

    Απ: Λαμβάνοντας την τιμή @@identity.

    To OUTPUT INSERTED statement πιστεύω είναι το κατάλληλο εργαλείο για αυτή τη δουλειά
    Μην αφήνετε τα media να σας "ταΐζουν"!
  •  24-01-2006, 17:38 8901 σε απάντηση της 8899

    Απ: Λαμβάνοντας την τιμή @@identity.

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

    Στην πρώτη περίπτωση, MAX(indentity_column)+1 είναι αρκετό να "μαντέψουμε" την επόμενη τιμή, του indentity. Αν κάνουμε ένα συνδιασμό του SET IDENTITY_INSERT ON με το INSERT SQL που θέλουμε να εκτελέσουμε, μπορούμε να εισάγουμε από το client την τιμή του identity και να την ξέρουμε εκ των προτέρων. Αντίστοιχα μπορούμε να πράξουμε και σε ένα πιο πολύπλοκα σε υπολογισμό identity.

     

    George J.


    George J. Capnias: Χειροπρακτικός Υπολογιστών, Ύψιστος Γκουράρχης της Κουμπουτερολογίας
    w: capnias.org, t: @gcapnias, l: gr.linkedin.com/in/gcapnias
    dotNETZone.gr News
  •  24-01-2006, 17:55 8902 σε απάντηση της 8901

    Απ: Λαμβάνοντας την τιμή @@identity.

    Θα γίνω (πάλι) δικηγόρος του Devil [6]

    Μην ξεχνάτε ότι παίζουμε(;) σε ένα OLTP σύστημα, που σημαίνει ότι θα πρέπει να κλειδώσουμε τον πίνακα από την στιγμή που διαβάζουμε το MAX(ident_col) μέχρι να κάνουμε το INSERT έτσι ώστε να υπάρχει concistency και να μην πάει κάποιος άλλος να κάνει INSERT, κάτι που θα σημαίνει ότι το identity value που θα πάμε να βάλουμε θα είναι ίδιο με του άλλου.

    Γι αυτόν το λόγο στα RDBMS παρέχεται ο μηχανισμός αυτός και οι περιπτώσεις που χρειάζεται να κάνουμε implement δική μας τέτοια μέθοδο είναι όταν πρέπει ο αριθμός σειράς να είναι απόλυτος και να μην έχει gaps (πχ. παραστατικά). Και πάλι ο κώδικας που θα παράγει τα sequential numbers θα πρέπει να είναι bullet-proof και είναι ένας μικρός πονοκέφαλος (συνήθως χρησιμοποιείται ένας extra πίνακας ο οποίος κρατάει το τελευταίο νούμερο και χρησιμοποιείται μέσα σε ένα transaction ώστε να είμαστε οι μοναδικοί που θα το γράφουμε/διαβάζουμε σε κάθε δεδομένη στιγμή).

    Πάντως, για το πρόβλημα του φίλου infoCENTER η πιο απλή μέθοδος είναι να χρησιμοποιηθεί stored procedure που θα επιστρέφει αυτό το νούμερο. Οποιοδήποτε άλλο implementation είτε είναι πολυπλοκότερο, είτε έχει μεγαλύτερο overhead από άποψη resources.


    Vir prudens non contra ventum mingit
  •  25-01-2006, 00:44 8922 σε απάντηση της 8902

    Απ: Λαμβάνοντας την τιμή @@identity.

    Παιδιά σας ευχαριστώ για το χρόνο σας.

    Η ιδέα να χρησιμοποιήσω δεύτερο SQLCommand δουλεύει, απλά ήθελα να δω αν μπορούσε να γίνει μόνο με μία SQLCommand. Δεν έχω δοκιμάσει ακόμα το OUTPUT INSERTED για να δω τι γίνεται και απο εκεί.

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

    Όσο για @@IDENTITY ή SCOPE_IDENTITY θα προτιμήσω από εδώ και μπρος το δεύτερο μιας και είναι διαθέσιμη ρουτίνα στον SQL Server 2005.

    Ευχαριστώ και πάλι για τον χρόνο σας.
  •  25-01-2006, 01:00 8923 σε απάντηση της 8856

    Απ: Λαμβάνοντας την τιμή @@identity.

    Ρίξε μια ματιά εδώ για το output inserted: http://msdn2.microsoft.com/ms177564.aspx .
    Μην αφήνετε τα media να σας "ταΐζουν"!
  •  25-01-2006, 02:53 8924 σε απάντηση της 8923

    Απ: Λαμβάνοντας την τιμή @@identity.

    Όπως κι εδώ http://www.dotnetzone.gr/cs/blogs/mkelaiditis/archive/2005/11/17/7129.aspx Smile [:)]


    Vir prudens non contra ventum mingit
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems