xarda Δημοσ. 4 Μαρτίου 2012 Δημοσ. 4 Μαρτίου 2012 Πως θα μπορεσω να τσεκάρω αν μια εγγραφή υπαρχει στην βάση; Χρησιμοποιω ADOQuery για τα ερωτηματα: Ακολουθεί παραδειγματακι χρησης του ADOQuery... >ADOQuery1->Close(); ADOQuery1->SQL->Clear(); ADOQuery1->SQL->Add("SELECT EmpNo, LastName, FirstName, HireDate"); ADOQuery1->SQL->Add("FROM Employee"); ADOQuery1->Open();
Directx Δημοσ. 4 Μαρτίου 2012 Δημοσ. 4 Μαρτίου 2012 (επεξεργασμένο) Αν και δεν ασχολούμαι με τα DB εργαλεία του C++ Builder (προφανώς αυτόν χρησιμοποιείς), παρόλα αυτά θα μπορούσες να το κάνεις ως εξής: > try { ADOQuery1->SQL->Clear(); ADOQuery1->SQL->Add("SELECT * FROM Employee");// WHERE EmpNo=\"1\""); ADOQuery1->Open(); ShowMessage(ADOQuery1->RecordCount != -1 ? ADOQuery1->RecordCount ? "RECORD FOUND": "RECORD NOT FOUND" : "ADO ERROR"); while(!ADOQuery1->Eof) { ShowMessage(ADOQuery1->FieldByName("EmpNo")->AsString); ADOQuery1->Next(); } } __finally { ADOQuery1->Close(); } Αν το κριτήριο αναζήτησης σου είναι για παράδειγμα το EmpNo (το οποίο υποθέτω ότι είναι ένα String) τότε μέσο της συνθήκης WHERE EmpNo=\"1\" ζητάς από το ADOQuery να επιστρέψει όλες τις εγγραφές όπου το EmpNo είναι "1". Για να μάθεις τον αριθμό των εγγραφών αρκεί να τσεκάρεις μετά το ADOQuery->Open() το ADOQuery->RecordCount που επιστρέφει τον αριθμό των ευρεθέντων εγγραφών. --EDIT: Το RecordCount σε περίπτωση αποτυχίας του ADO επιστρέφει -1. Όλα αυτά με την επιφύλαξη ότι μπορεί να υπάρχει και κάποιος άλλος τρόπος (πχ μέσο ορισμού ->Locate). Τέλος, για να διαβάσεις τις εγγραφές που επιστρέφει η ADOQuery->Open / SELECT, ώστε να εφαρμόσεις ενδεχομένως κριτήρια που μπορεί να υπερβαίνουν την SQL, μπορείς να δοκιμάσεις το παρακάτω: > while(!ADOQuery1->Eof) { ShowMessage(ADOQuery1->FieldByName("EmpNo")->AsString); ADOQuery1->Next(); } Το ->Eof είναι διάφορο του false για όσο διάστημα υπάρχουν εγγραφές στο ADOQuery, το ->Next() μας μεταφέρει στην επόμενη εγγραφή (αποτέλεσμα) του ADOQuery->SQL μας. Τέλος μπορούμε να αποκτήσουμε πρόσβαση στα πεδία της τρέχουσας εγγραφής στην οποία βρίσκεται το ADOQuery μας, μέσο του ->FieldByName(όνομα πεδίου) και την αίτηση μας να επιστραφεί σε μορφή κειμένου -AsString, θεωρώ όπως προείπα ότι το EmpNo έχει ορισθεί ως κείμενο στην ΒΔ. Καλή συνέχεια. Επεξ/σία 4 Μαρτίου 2012 από Directx
xarda Δημοσ. 4 Μαρτίου 2012 Μέλος Δημοσ. 4 Μαρτίου 2012 Thanks για την απαντηση αλλα συνεχως μου εμφανιζει "Record Found"..... Δεν "πιανει" το recordcount....
Directx Δημοσ. 4 Μαρτίου 2012 Δημοσ. 4 Μαρτίου 2012 Thanks για την απαντηση αλλα συνεχως μου εμφανιζει "Record Found"..... Δεν "πιανει" το recordcount.... Αυτό συμβαίνει διότι το RecordCount != 0 (υπόψη, η περίπτωση -1 είναι ειδική και αναφέρετε παρακάτω) άρα το ADOQuery σου, επιστρέφει αποτέλεσμα για το SQL Statement σου συνεπώς θα πρέπει να αναθεωρήσεις τις παραμέτρους του "WHERE" σου. Υπόψη, σύμφωνα με την τεκμηρίωση σε περίπτωση σφάλματος το RecordCount επιστρέφει -1 άρα θα πρέπει να ελέγξεις και για αυτή την πιθανότητα -συμβαίνει αν το ADO δεν ανοίξει σωστά (υποθέτω στον έλεγχο που έχω δώσει, ότι η εκτέλεση του ερωτήματος είναι πάντα επιτυχής από το ADO -αυτό το άλλαξα πλέον). -- Στην θέση σου θα μελετούσα, τον αριθμό του RecordCount (αν είναι -1 τότε υπάρχει κάποιο σφάλμα με το ADO), το WHERE μου και τις εγγραφές που επέστρεψε το ADOQuery ως αποτέλεσμα της SQL εντολής μου.
xarda Δημοσ. 5 Μαρτίου 2012 Μέλος Δημοσ. 5 Μαρτίου 2012 Ok το καταφεραμε κ αυτο. Μια απορια αν ξερει καποιος και μπορει να απαντησει.Βλεπω πως πρεπει να χρησιμοποιουμε διαφορα exception. Για παραδειγμα στο δικο μου προγραμματακι δεν εκτελειται ποτε το catch της εξαιρεσης αλλα συνατησεις του embarcadero....Ποιος ο λογος να χρησιμοποιουμε exception en olighs???
computeras13 Δημοσ. 5 Μαρτίου 2012 Δημοσ. 5 Μαρτίου 2012 Μια παρατήρηση θα κάνω μόνο στον κώδικα SQL σου. Ειναι καλύτερο πάντα όταν θέλεις απλά να δεις αν κάτι υπάρχει και να μετρήσεις πχ σε πόσες σειρές υπάρχει να χρησιμοποιείς >SELECT 1 FROM ... και >SELECT COUNT(1) FROM ... αντί για >SELECT * FROM ... Έτσι έχεις πολύ καλύτερες ταχύτητες. Απλά να το έχεις στο μυαλό σου.
Directx Δημοσ. 5 Μαρτίου 2012 Δημοσ. 5 Μαρτίου 2012 (επεξεργασμένο) Μια παρατήρηση θα κάνω μόνο στον κώδικα SQL σου. Ειναι καλύτερο πάντα όταν θέλεις απλά να δεις αν κάτι υπάρχει και να μετρήσεις πχ σε πόσες σειρές υπάρχει να χρησιμοποιείς >SELECT 1 FROM ... και >SELECT COUNT(1) FROM ... αντί για >SELECT * FROM ... Έτσι έχεις πολύ καλύτερες ταχύτητες. Απλά να το έχεις στο μυαλό σου. Σε αυτή την περίπτωση ο έλεγχος αποτελέσματος του TADOQuery αλλάζει σε: > try { ADOQuery1->SQL->Clear(); ADOQuery1->SQL->Add("SELECT COUNT(*) FROM Employee WHERE EmpNo=\"1\""); ADOQuery1->Open(); ShowMessage(ADOQuery1->Fields->Count && !ADOQuery1->Fields->Fields[0]->IsNull ? ADOQuery1->Fields->Fields[0]->AsInteger ? "RECORD FOUND": "RECORD NOT FOUND": "ADO ERROR"); } __finally { ADOQuery1->Close(); } Όπου το αποτέλεσμα της COUNT καταχωρείται ως πρώτο στον πίνακα TADOQuery->Fields->Fields[] (αυτός είναι ο τρόπος ελέγχου του αποτελέσματος σε C++ Builder, σε Delphi διαφέρει ελαφρά). @xarda: Οι εξαιρέσεις βοηθούν στην ανάπτυξη ευανάγνωστου κώδικα αφαιρώντας την ανάγκη για εισαγωγή συνεχόμενων ελέγχων επιτυχίας μέσο εντολών if ύστερα από την κλήση κάποιας ρουτίνας. Σε τεχνικό επίπεδο, επιτρέπουν αρκετά ασφαλή διαχείριση σφαλμάτων ακόμα και για περιπτώσεις που υπό συνθήκες θα οδηγούσαν την εκτέλεση του προγράμματος σε βίαιη διακοπή. Στην VCL (C++ Builder) είναι ο βασικός τρόπος ελέγχου μεταξύ επιτυχίας ή αποτυχίας για σχεδόν το σύνολο των προσφερόμενων υπηρεσιών της βιβλιοθήκης και συνεπώς θα πρέπει να αρχίσεις να τις λαμβάνεις υπόψη σου (το ίδιο ισχύει και για το __finally). Αν δεν το κάνεις αυτό, τότε όλες οι εξαιρέσεις καταλήγουν σε ένα αυτόματο catch που προσφέρει το TApplication (ας πούμε η VCL..) πράγμα που δεν είναι συνήθως επιθυμητό. Επεξ/σία 5 Μαρτίου 2012 από Directx
xarda Δημοσ. 5 Μαρτίου 2012 Μέλος Δημοσ. 5 Μαρτίου 2012 Μααα ακομα και το πιο απλο try catch να φτιαξω τοτε φαινεται πως δεν εκτελειται ο κώδικας της catch αλλα οι exceptions του builder!!! για παραδειγμα: > try{ this->ADOConnection1->Connected = false; if( this->ADOConnection1->Connected != true ) { throw 10; } } catch (int e){ MessageDlg("Error while connecting", mtError,TMsgDlgButtons() << mbOK, 0); } Μου εμφανιζει το μηνυμα του builder: >....raised exception class int with message 'Exception Object Address: 0X8A3292'. αντι για: > MessageDlg("Error while connecting", mtError,TMsgDlgButtons() << mbOK, 0); Γιατι;;; ΑΚΥΡΟ ΠΑΙΔΙΑ...Run without debugging η λύση!!!
xarda Δημοσ. 6 Μαρτίου 2012 Μέλος Δημοσ. 6 Μαρτίου 2012 Χρειαζομαι βοηθεια. Θα με τρελανει αυτο το messagebox τι να πω δλδ τοσος χαμενος χρονος για μια ΒΛΑΚΕΕΕΕΕΙΙΙΙΙΙΙΙΙΑΑΑΑΑΑΑΑΑΑΑΑΑ τελος παντων > try{ if(1<2){ throw "kodikos sfalmatos:198"; } } catch(String msg){ MessageBox(NULL, msg , "<Message title here>", MB_ICONSTOP|MB_SETFOREGROUND); } Ο παραπανω κωδικας δεν εκτελειται και αυτο που θελω να κάνω ειναι με καποιο τροπο να εμφανιζεται στο messagebox to " kodikos sfalmatos 198 ".... Πως ;
Directx Δημοσ. 6 Μαρτίου 2012 Δημοσ. 6 Μαρτίου 2012 Χρειαζομαι βοηθεια. Θα με τρελανει αυτο το messagebox τι να πω δλδ τοσος χαμενος χρονος για μια ΒΛΑΚΕΕΕΕΕΙΙΙΙΙΙΙΙΙΑΑΑΑΑΑΑΑΑΑΑΑΑ τελος παντων > try{ if(1<2){ throw "kodikos sfalmatos:198"; } } catch(String msg){ MessageBox(NULL, msg , "<Message title here>", MB_ICONSTOP|MB_SETFOREGROUND); } Ο παραπανω κωδικας δεν εκτελειται και αυτο που θελω να κάνω ειναι με καποιο τροπο να εμφανιζεται στο messagebox to " kodikos sfalmatos 198 ".... Πως ; Το πρόβλημα σου προέρχεται από δυο λόγους, ο πρώτος είναι ότι ορίζεις την εξαίρεση σου ως "throw "kodikos sfalmatos:198";" αντί του ορθού "throw (String)"kodikos sfalmatos:198";" καθώς το catch που ακολουθεί ανιχνεύει μόνο εξαιρέσεις τύπου String (catch(String msg)). Το δεύτερο πρόβλημα είναι ότι χρησιμοποιείς την ρουτίνα MessageBox του Windows API το οποίο όμως δεν δέχεται άμεσα τύπους String αλλά char*, συνεπώς αρκεί ένα msg.c_str() για να λάβεις το String σε μορφή char*. Τέλος το MessageBox(NULL καλό είναι να γίνει Handle όπου πρόκειται για το HWND της φόρμας σου. Αν τώρα εργάζεσαι με κάποια νεότερη έκδοση του C++ Builder που δουλεύει με Unicode θα πρέπει να ορίσεις το "<Message title here>" ως L"<Message title here>" και ίσως αξίζει να προτιμήσεις το MessageBoxW αντί του MessageBox και σε αυτή την περίπτωση το .w_str() αντί του .c_str() (αλλά τώρα μάλλον σε πάω μακριά). Με αυτό υπόψη ο κώδικας μπορεί να δηλωθεί ως: > try{ if(1<2) throw (String)"kodikos sfalmatos:198"; } catch(String msg){ MessageBoxW(Handle, msg.c_str(), "<Message title here>", MB_ICONSTOP); } Και η ανάλογη έκδοση για C++ Builder που υποστηρίζει Unicode: > try{ if(1<2) throw (String)"kodikos sfalmatos:198"; } catch(String msg){ MessageBoxW(Handle, msg.c_str(), L"<Message title here>", MB_ICONSTOP); } --Επίσης αντί του MessageBox μπορεί να δεις και το TApplication->MessageBox (για να γλιτώσεις το HWND/NULL) ή κάτι σε ποίο VCL (MessageDlg -με ορισμένους όμως μικρούς περιορισμούς) [δες την τεκμηρίωση του C++ Builder ]. Και μια πιο VCL-friendly εκδοχή (μπορεί να γίνει ακόμα πιο ευέλικτα αλλά δεν θέλω να σε μπερδέψω): > try{ if(1<2) throw Exception("kodikos sfalmatos:198"); } catch(Exception &msg){ Application->ShowException(&msg); } Τέλος μια συμβουλή για τον προγραμματισμό σε VCL, απέφυγε την χρήση του τύπου String (ναι ξέρω ότι τον προτείνουν και μερικά βιβλία) καθώς θα σε βάλει σε μπελάδες αφού στις παλιές εκδόσεις ταυτίζεται με το AnsiString ενώ στις νέες αυτόματα με το UnicodeString και τελικά μπορεί να σπάσει την συμβατότητα πολύ εύκολα με ήδη υπάρχον κώδικα και να δημιουργήσει ένα σωρό προβλήματα. Συνήθισε λοιπόν είτε να χρησιμοποιείς το AnsiString (αν δουλεύεις με παλιές εκδόσεις του C++ Builder 2007-2002-) ή την UnicodeString όταν δουλεύεις με καινούργιες (2009+).
xarda Δημοσ. 7 Μαρτίου 2012 Μέλος Δημοσ. 7 Μαρτίου 2012 Directx φαίνετε οτι γνωριζεις αρκετα πραγματα γι'αυτο θα ηθελα να μου πεις κατι ακομα... Χρησιμοποιω c++ στον embarcadero rad studio 2010 και θελω με κάποιο component οπως το DateTimePicker ή το MonthCalendar να χειριζομαι ημερομηνιες και ωρα...Τι προτείνεις και με ποια μορφη πρεπει να τα χειριστω;; Εννοειται πως θελω να αποθηκεύονται επιλεγμενες ημερομηνιες στον sql server 2005 να γίνονται συγκρισεις ημερομηνιων και ωρας κ.τ.λ...
Directx Δημοσ. 8 Μαρτίου 2012 Δημοσ. 8 Μαρτίου 2012 Directx φαίνετε οτι γνωριζεις αρκετα πραγματα γι'αυτο θα ηθελα να μου πεις κατι ακομα... Χρησιμοποιω c++ στον embarcadero rad studio 2010 και θελω με κάποιο component οπως το DateTimePicker ή το MonthCalendar να χειριζομαι ημερομηνιες και ωρα...Τι προτείνεις και με ποια μορφη πρεπει να τα χειριστω;; Εννοειται πως θελω να αποθηκεύονται επιλεγμενες ημερομηνιες στον sql server 2005 να γίνονται συγκρισεις ημερομηνιων και ωρας κ.τ.λ... Για διαχείριση χρόνου στον C++ Builder, θα πρέπει να δεις την TDateTime class (όπως και τις υποκατηγορίες της, TDate & TTime) η οποία προσφέρει ακρίβεια τάξης double και χρησιμοποιείται συνολικά από την VCL (όλα τα components που διαχειρίζονται Date/Time επιστρέφουν TDateTime). Όσον αφορά την περαιτέρω διαχείριση ωρών και ημερομηνιών θα πρέπει να δεις οπωσδήποτε τις ρουτίνες που προσφέρει το DateUtils.hpp (δρουν συμπληρωματικά προς την TDateTime) οι οποίες κυριολεκτικά θα σου λύσουν τα χέρια με τις δυνατότητες που σου προσφέρουν. Τώρα, για να πάρεις μια μικρή ιδέα για το πως δουλεύει η TDateTime class (και ορισμένες ρουτίνες του DateUtils.hpp) ρίξε μια μάτια εδώ και οπωσδήποτε άρχισε να μελετάς την τεκμηρίωση του C++ Builder (& μαζί με την τεκμηρίωση και της DateUtils.hpp), μόνο έτσι θα μπορέσεις να βρεις σίγουρη άκρη.
xarda Δημοσ. 8 Μαρτίου 2012 Μέλος Δημοσ. 8 Μαρτίου 2012 Μια πιο γενική ερώτηση...Κατα το ανοιγμα του προγραμματος εκτελουνται διαφορα sql queries για την εμφνανιση διαφορων εγγραφων απο την Db.Ανοιγωντας ενα child παραθυρο ας πουμε εκτελείτε ενα νέο ερώτημα,αν θελεις να βαλεις νέα εγγραφη παλι εκτελειται ενα sql query...Τι είναι καλύτερο;;Κατα την εκκινηση του προγραμματος να φορτώνονται τα δεδομενα της βασης σε vectors<> και να κλεινει η συνδεση ή κάθε φορα που εκτελεί κάτι να ανοιγοκλείνει τη συνδεση με την db ;;
Directx Δημοσ. 9 Μαρτίου 2012 Δημοσ. 9 Μαρτίου 2012 Μια πιο γενική ερώτηση...Κατα το ανοιγμα του προγραμματος εκτελουνται διαφορα sql queries για την εμφνανιση διαφορων εγγραφων απο την Db.Ανοιγωντας ενα child παραθυρο ας πουμε εκτελείτε ενα νέο ερώτημα,αν θελεις να βαλεις νέα εγγραφη παλι εκτελειται ενα sql query...Τι είναι καλύτερο;;Κατα την εκκινηση του προγραμματος να φορτώνονται τα δεδομενα της βασης σε vectors<> και να κλεινει η συνδεση ή κάθε φορα που εκτελεί κάτι να ανοιγοκλείνει τη συνδεση με την db ;; Καλύτερα άφησε την ΒΔ να διαχειριστεί τα δεδομένα σου όταν και όποτε χρειάζεται.
xarda Δημοσ. 16 Μαρτίου 2012 Μέλος Δημοσ. 16 Μαρτίου 2012 ΟΚ με τα παραπάνω! Τωρα αντιμετωπίζω ενα ΤΕΡΑΣΤΙΟ πρόβλημα! Στην db εχω δυο πίνακες εικόνα 1. Θέλω ενα sql query opoυ να μου εμφανίζει oλα τα αυτοκίνητα απο τον πίνακα car οπου είναι ελεύθερα ας πούμε στις ημερομηνιες που δίνω π.χ απο 3/13/2012 εως 3/19/2012 .... Πως στα κομματια ειναι αυτο το query???Εχω κάψει εγκέφαλο...
Προτεινόμενες αναρτήσεις
Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε
Πρέπει να είστε μέλος για να αφήσετε σχόλιο
Δημιουργία λογαριασμού
Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!
Δημιουργία νέου λογαριασμούΣύνδεση
Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.
Συνδεθείτε τώρα