Office Forum
www.Office-Loesung.de
Access :: Excel :: Outlook :: PowerPoint :: Word :: Office :: Wieder Online ---> provisorisches Office Forum <-
Parametrisierte Abfragen in Controls
zurück: 2003->2007 übersichtsformular weiter: Problem mit Unterformular: 2455 Unbeantwortete Beiträge anzeigen
Neues Thema eröffnen   Neue Antwort erstellen     Status: Feedback Facebook-Likes Diese Seite Freunden empfehlen
Zu Browser-Favoriten hinzufügen
Autor Nachricht
Gärtner mit ä
Gast


Verfasst am:
27. Nov 2010, 15:30
Rufname:

Parametrisierte Abfragen in Controls - Parametrisierte Abfragen in Controls

Nach oben
       Version: Office 2003

Hallo Forum,

ich habe eine bestehende Access DB mit sehr vielen parametrisierten Abfragen. Wenn ich eine solche als RowSource in ein Control eintrage kommt die Abfrage nach dem Parameter der Abfrage. Kann ich vielleicht dafür sorgen das der Parameter von irgendwo anders herkommt? Oder wenn das nicht geht:
Kann ich die parametrisierte Abfrage einem Command Objekt mit den Param Objekten geben und dann das SQL Statement generieren, so dass ich dann das SQL Statement in die Rowsource Eigenschaft schreiben kann?

Vielen Dank

Peter
steffen0815
VBA-Programmierer


Verfasst am:
27. Nov 2010, 16:03
Rufname:


AW: Parametrisierte Abfragen in Controls - AW: Parametrisierte Abfragen in Controls

Nach oben
       Version: Office 2003

Hallo,
Zitat:
Command Objekt
Was soll das sein?

Wo konkret sollen die Parameter herkommen, wenn du sie nicht manuell eingeben willst?
Du kannst natürlich die RowSource direkt mit SQL "beschicken".

Btw:
Also ich habe bisher eigentlich noch nie Parameterabfragen eingesetzt und auch eine variable Recordsource ist eher selten.
Irgendetwas machst du anders als ich Wink.

_________________
Gruß Steffen
Gärtner mit ä
Gast


Verfasst am:
27. Nov 2010, 16:56
Rufname:

AW: Parametrisierte Abfragen in Controls - AW: Parametrisierte Abfragen in Controls

Nach oben
       Version: Office 2003

Der Parameter ergibt sich aus anderen Controls auf der Form.
Nehmen wir an wir haben eine DB Modellbau. Mit den Tabellen:
- Anleitung
- Komponente
- gehört_zu

Nun möchte man eine Form erstellen die diese Anleitung darstellt. Die RowSource der Form ist Anleitung. Auf der Form befindet sich eine Listbox wo die Komponenten der Anleitung rein sollen. Es gibt eine Abfrage mit einem Parameter AnleitungsID die Komponenten auflistet. Wie kann ich diese Abfrage verwenden? Ich möchte kein SQL in einen String schreiben, oder hinter eine Form. Der spätere Anwender kann kein VBA, er möchte jedoch ev die SQL verändern.

Ich habe mir jetzt so geholfen das im parametrisierten SQL der Param ersetzt wird:
Code:
    Me.lstKomponenten.RowSource _
                = Replace(CurrentDb.QueryDefs("KomponentenDerAnleitung").SQL _
                        , "[@AnleitungsID]", Me.txtID)
Der generische Weg geht jedoch über das ADODB.Command Objekt, weil hierfür die ADODB.Parameter Objekte entworfen wurden.
Oder aber ich kriege es hin das der Parameter von woanders her kommt. Ich weiß das ich es schonmal vor Jahren geschafft habe das die Parameterabfrage nicht aufgepoppt ist und der Wert von irgendwo her kam...
Bitsqueezer
Office-VBA-Programmierer


Verfasst am:
27. Nov 2010, 18:44
Rufname:

AW: Parametrisierte Abfragen in Controls - AW: Parametrisierte Abfragen in Controls

Nach oben
       Version: Office 2003

Hallo,

auch wenn ein Formular nur eine RecordSource hat und keine RowSource...Wink

RowSource in Controls und RecordSource in Formularen funktionieren nach dem gleichen Prinzip: Sie benötigen, wenn es sich um Abfragen handelt, einen SQL-Befehl, der in dem Moment ausgeführt wird, wenn das Formular geöffnet wird.
Daher müssen alle nötigen Parameter entweder innerhalb des SQL-Befehls enthalten sein (statischer SQL-Befehl mit festen Parameterwerten) oder sie müssen z.B. im Form Open Event zusammengesetzt und dann zugewiesen werden.

Wenn Du also kein direktes SQL hineinschreiben willst, ist die Lösung, die Du geschrieben hast, nämlich den SQL-Befehl direkt aus der QueryDef herauszulesen und dann den Parameter mit Replace zu ersetzen, eine gangbare Möglichkeit. Die Gefahr hier ist natürlich, daß die Abfrage mal geändert wird und dann die Control/Form nicht mehr funktioniert. Normalerweise hat ein Benutzer ja in den Source-Einstellungen eines Formulars nichts verloren und daher kann man hier auch unbesorgt den SQL-Befehl direkt hineinpinseln, womit immer gesichert ist, daß dieser auch weiterhin funktioniert.
Nachteil ist natürlich, daß die Performance darunter leidet, weil ein direkter SQL-Befehl innerhalb der Row/RecordSource immer "dynamisches SQL" bedeutet - der Befehl wird erst beim Öffnen des Formulars interpretiert und ausgeführt, während eine gespeicherte Abfrage bereits beim Speichern compiliert und optimiert wird (in etwa zu vergleichen mit gespeicherten Views/Stored Procedures auf einem SQL Server).

Das ADO-Commandobjekt und seine Parameter-Collection ist normalerweise der beste und sicherste Weg, um eine SQL-Abfrage mit Parametern zu definieren und mit Werten zu befüllen. Sie verhindert zuverlässig böswillige SQL Injections durch den User, etwa bei Eingabe von Abfragewerten oder Benutzername/Kennwort. Eine als String zusammengesetzte SQL-Abfrage läßt dagegen Manipulation zu, sofern die Parameter aus einer Benutzereingabe kommen - das ist hier aber nicht der Fall, da der Parameter eine ID sein soll, die sich aus dem Formular ergibt.

Wenn man also einen SQL-Befehl als gespeicherte Abfrage verwenden will und Parameter aus einem Formular dazu verwenden möchte, kann man einfach als Parameter direkt das Feld aus dem Formular referenzieren, etwa so:
Code:
SELECT ID, Was, auch, immer
FROM   MeineTabelle
WHERE  ID=Forms!MeinFormular!MeinIDFeld
Die Abfrage funktioniert, solange das Formular geöffnet ist, bei geschlossenem Formular würdest Du beim Öffnen der Abfrage wieder die Parameterabfrage sehen, die dann nach "Forms!MeinFormular!MeinIDFeld" fragt.

Im Formular aber ist das kein Problem, da ja das Formular zuerst geöffnet wird und damit immer geladen ist, wenn die Abfrage als Row/RecordSource ausgeführt wird.

Ein ADO-Recordset könnte theoretisch auch benutzt werden, um eine Combobox zu füllen, aber nicht direkt: Die Combobox müßte dann auf Werteliste umgestellt werden und in einer Schleife mit den Werten aus dem ADO-Recordset befüllt werden, was sehr langsam ist und kein Requery erlaubt. Eine dritte (sehr unbekannte und komplizierte) Methode besteht darin, den Herkunftstyp der Combobox auf einen VBA-Funktionsnamen zu ändern. Die Funktion kann dann beliebigen Code verwenden, um die Combobox zu füllen, muß sich aber an strenge Parameterrichtlinien und Aufrufreihenfolge halten.
Besonders bei größeren Datenmengen ist diese Methode absolut nicht zu empfehlen, da sehr langsam (langsamer als die ADO-Recordset-Methode). Weiterer Nachteil ist auch, daß diese Funktion bei jedem eingetippten Zeichen einer Combobox erneut aufgerufen ist, was die Combobox sehr träge macht.

Gruß

Christian
Gärtner mit ä
Gast


Verfasst am:
30. Nov 2010, 10:45
Rufname:

AW: Parametrisierte Abfragen in Controls - AW: Parametrisierte Abfragen in Controls

Nach oben
       Version: Office 2003

Hallo Bitsqueezer,

erstmal vielen Dank für Deine ausführliche Antwort. Da bin ich wirklich baff Smile
Der Tip mit den VBA Namen im SQL sieht nicht sonderlich ansprechend aus. Das mit den (langsamen) Funktionsnamen ist jedoch interessant: ACC: How to Fill a Combo Box with Table Names

Ich habe es jetzt erstmal so gemacht, weil ich auf diese Weise die Command und Parameter Objekte wie bisher verwenden kann.

Vielen Dank

Peter Smile))
Bitsqueezer
Office-VBA-Programmierer


Verfasst am:
30. Nov 2010, 11:20
Rufname:

AW: Parametrisierte Abfragen in Controls - AW: Parametrisierte Abfragen in Controls

Nach oben
       Version: Office 2003

Hallo Peter,

ja, genau diese Methode hatte ich gemeint, den Link hatte ich nicht mehr parat.
Sieht interessant aus, würde eine Menge sehr interessanter Möglichkeiten bieten, ist aber derart langsam, daß ich nach ein paar Experimenten damit diese Methode wieder aufgegeben habe.

Man muß immer abwägen, wie man als Endergebnis das beste herausholt, für meine Begriffe steht an erster Stelle Sicherheit und Performance, erst danach, wie sauber der Code dabei aussieht. Was hilft der schönste Code, wenn die Anwendung darunter leidet.

Meistens kann man sagen, wenn der Code mehr Arbeit macht und komplizierter ist, ist das Ergebnis oft auch besser für die Anwendung (bestes Beispiel TransferSpreadsheet gegenüber einer eigenen Excel-Export-Funktion), oft sogar schneller - leider trifft das nicht für diesen Funktionstrick hier zu, der macht Comboboxen langsamer und daher ist es wohl nur für wenige Sonderfälle interessant.

Auch in Deinem Fall könntest Du das gleiche erreichen, indem Du stattdessen ein ADO-Recordset verwendest und in die Combobox kopierst, die Funktion kann bei einer allgemeinen Requery-Funktion des Formulars dann einfach erneut aufgerufen werden, das ist immer noch schneller als diese Methode.

Übrigens fällt mir gerade ein, daß es doch noch eine weitere Methode gibt, eine Combobox mit einem Recordset zu befüllen: Die Combobox hat nämlich nicht nur eine RowSource-Eigenschaft, sondern genau wie ein Formular auch eine Recordset-Eigenschaft, mit der man einfach ein bereits geladenes Recordset zuweisen kann:
Code:
    Set MyCombo.Recordset = rs
In ACCDB/MDB funktioniert das nur mit DAO-Recordsets, in Access Projekten aber mit ADO-Recordsets.

Ansonsten hätte ich noch folgende Funktion zum Befüllen aus der ADO-Library (vollständig im Tips & Tricks-Forum):
Code:
' Fills a combobox with values from a recordset. Useful, if strSQL is too long
' to be a RowSource value.
' Only useable for short result sets as the combobox is filled per valuelist
' which has a maximum length of 32767 characters
' strHeader is an optional title line, like "ID;Header 1;Header 2"
' strAdditionalFirstLine is an optional line which should be added as first
'                        line like: 0;"All"
' Coppes
' Date: 16.09.2009
Public Sub fnADOComboboxAddItem(cmb As ComboBox, strSQL As String _
                              , Optional strHeader As String = "" _
                              , Optional strAdditionalFirstLine As String = "")
On Error GoTo fnADOComboboxAddItem_Error
    Dim rs As ADODB.Recordset
    Dim i As Long, k As Long
    Dim strItem As String

    strADOErr = "OK"
    Set rs = fnADOSelectCommon(strSQL, adLockReadOnly, adOpenForwardOnly)
    If Not rs Is Nothing Then
        If Not (rs.EOF And rs.BOF) Then
            rs.MoveFirst
            i = 1
            With cmb
                .RowSourceType = "Value List"
                .ColumnCount = rs.Fields.Count
                If strAdditionalFirstLine <> "" Then
                    .AddItem strAdditionalFirstLine, 0
                    i = i + 1
                End If
                If strHeader <> "" Then
                    .AddItem strHeader, 0
                    .ColumnHeads = True
                  Else
                    If strAdditionalFirstLine <> "" Then
                        i = 1
                      Else
                        i = 0
                    End If
                    .ColumnHeads = False
                End If
                Do While Not rs.EOF
                    strItem = "'"
                    For k = 0 To rs.Fields.Count - 1
                        strItem = strItem & Nz(rs.Fields(k)) & "';'"
                    Next k
                    strItem = Left(strItem, Len(strItem) - 2)
                    .AddItem strItem, i
                    rs.MoveNext
                    i = i + 1
                Loop
            End With
        End If
    End If
    strADOLastSQL = strSQL
fnADOComboboxAddItem_Exit:
    If Not rs Is Nothing Then
        If rs.State = adStateOpen Then rs.Close
        Set rs = Nothing
    End If
    Exit Sub
fnADOComboboxAddItem_Error:
    strADOErr = "ERROR"
    Select Case Err
      Case Else
        fnErr "modODBC->fnADOComboboxAddItem", True
        fnCloseODBCConnection
        strADOErr = "ERROR"
        Resume fnADOComboboxAddItem_Exit
    End Select
End Sub
(fnADOSelectCommon erstellt ein ADO-Recordset anhand eines SQL-Befehls, fnErr ist eine Fehlerbehandlungsfunktion und fnCloseODBCConnection schließt die Verbindung des ADO-Connection-Objektes)

Damit kann man eine Combobox mit einer Recordset-Liste universell befüllen.

Gruß

Christian
Gärtner mit ä
Gast


Verfasst am:
30. Nov 2010, 20:04
Rufname:


AW: Parametrisierte Abfragen in Controls - AW: Parametrisierte Abfragen in Controls

Nach oben
       Version: Office 2003

Die Lösung mit dem Funktionsnamen ist zumindest bei meinen Testdaten genauso schnell. Wenn der Weg über die Recordset Zuweisung später schneller ist nehme den. Muß auch nicht soviel Code umschreiben. Danke Smile
Neues Thema eröffnen   Neue Antwort erstellen Alle Zeiten sind
GMT + 1 Stunde

Diese Seite Freunden empfehlen

Seite 1 von 1
Gehe zu:  
Du kannst Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.
Du kannst Dateien in diesem Forum nicht posten
Du kannst Dateien in diesem Forum herunterladen

Verwandte Themen
Forum / Themen   Antworten   Autor   Aufrufe   Letzter Beitrag 
Keine neuen Beiträge Access Tabellen & Abfragen: Daten abfragen nach Buchstabenreihenfolge 2 wrengers 699 07. März 2005, 22:59
Gast Daten abfragen nach Buchstabenreihenfolge
Keine neuen Beiträge Access Tabellen & Abfragen: mehrer abfragen ein formular 1 romu 719 10. Jan 2005, 15:54
lothi mehrer abfragen ein formular
Keine neuen Beiträge Access Tabellen & Abfragen: Parameter Abfragen mit "Drop Down Menu" 2 tomsingapore1 1620 23. Dez 2004, 17:56
tomsingapore1 Parameter Abfragen mit "Drop Down Menu"
Keine neuen Beiträge Access Tabellen & Abfragen: parametrisierte Anfrage 1 netti 475 07. Dez 2004, 09:21
stpimi parametrisierte Anfrage
Keine neuen Beiträge Access Tabellen & Abfragen: Memoformat in Tabelle wird bei Abfragen eiskalt trunkiert?!! 8 Muschimaus 1516 03. Dez 2004, 19:23
Skogafoss Memoformat in Tabelle wird bei Abfragen eiskalt trunkiert?!!
Keine neuen Beiträge Access Tabellen & Abfragen: Abfragen- Formularfeld als Kriterium 1 Gast 684 22. Nov 2004, 15:02
Felix15 Abfragen- Formularfeld als Kriterium
Keine neuen Beiträge Access Tabellen & Abfragen: Platzhalter in Abfragen einbinden 2 santje243 915 06. Nov 2004, 12:01
santje243 Platzhalter in Abfragen einbinden
Keine neuen Beiträge Access Tabellen & Abfragen: spezielle Abfragen 1 Hilfe 704 27. Sep 2004, 17:47
Skogafoss spezielle Abfragen
Keine neuen Beiträge Access Tabellen & Abfragen: Leere Felder in Abfragen ausblenden. 3 Gast 1374 18. Aug 2004, 14:39
mabe38 Leere Felder in Abfragen ausblenden.
Keine neuen Beiträge Access Tabellen & Abfragen: Verschachtelte SQL Abfragen in ACCESS 2000? 1 Gast 1782 17. Jul 2004, 22:34
faßnacht(IT); Verschachtelte SQL Abfragen in ACCESS 2000?
Keine neuen Beiträge Access Tabellen & Abfragen: SQL Abfragen ausgeben?? 2 woerny01 669 11. Jul 2004, 07:10
Gast SQL Abfragen ausgeben??
Keine neuen Beiträge Access Tabellen & Abfragen: Eingabefelder in Abfragen?!?! 6 Diovan80 609 28. Jun 2004, 09:51
Diovan Eingabefelder in Abfragen?!?!
 

----> Diese Seite Freunden empfehlen <------ Impressum - Besuchen Sie auch: Microsoft Project