Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi sql (https://www.delphipraxis.net/12558-sql.html)

Klaus D. 29. Nov 2003 18:33


sql
 
Morgen
ich mal wieder...was ist falsch?

SQL-Code:
SELECT id_Typenschild, sid_Fabrikat, Typ, Drehzahl, id_Fabrikat,
Fabrikat FROM tbl_Typenschild t1, tbl_Fabrikat t2
WHERE t1.sid_Fabrikat=t2.id_Fabrikat AND
(Typ like :p1 ) OR //gehört zur Tabelle t1
(Fabrikat like :p1) //gehört zur Tabelle t2
Danke Klaus

[edit=r_kerber]SQL-Tags eingefügt. Mfg, r_kerber[/edit]

Niels 29. Nov 2003 18:43

Re: sql
 
Tach

Setz mal t1.sid_Fabrikat=t2.id_Fabrikat in Klammern
Delphi-Quellcode:
(t1.sid_Fabrikat=t2.id_Fabrikat)
Falls das erste in jedem Fall zutreffen soll und dann zwischen dem 2. und 3. gewählt werden soll, dann muss das 2. und 3. ebenfalls in ner Klammer stehen
Delphi-Quellcode:
((Typ like :p1 ) OR (Fabrikat like :p1))

r_kerber 29. Nov 2003 18:55

Re: sql
 
Hallo Klaus,

schreibe doch mal, was für eine Meldung kommt. Außerdem wäre es hilfreich zu wissen, welche DB Du hier verwendest.
Ich bin mir nicht ganz sicher, ob es erlaubt ist, zweimal denselben Parameternamen zu verwenden.

Klaus D. 30. Nov 2003 22:09

Re: sql
 
Ich arbeite mit 'ADS'.
das oben genannte Problem ist gelöst, habe aber leider wieder ein neues.
ich habe 2.Query's.
Query1.sql:
SQL-Code:
SELECT id_Motorart, Motorart, id_Typenschild, sid_Motorart, sid_Fabrikat,
Typ, Drehzahl, Motornummer, Leistung_KW, id_Fabrikat, Fabrikat
FROM tbl_Motorart t1, tbl_Typenschild t2, tbl_Fabrikat t3
WHERE (t1.id_Motorart=t2.sid_Motorart) AND(t2.sid_Fabrikat=t3.id_Fabrikat)
Query2.sql:
SQL-Code:
SELECT id_Typenschild, id_Wickeldaten, sid_Typenschild, sid_Wicklungsart, id_WIcklungsart, Wicklungsart
FROM tbl_Typenschild t1, tbl_Wickeldaten t2, tbl_Wicklungsart t3
WHERE (t1.id_Typenschild=t2.sid_Wickeldaten) AND
(t2.sid_Wicklungsart=t3.id_Wicklungsart)
Ich möchte die Query1 mit der Query2 ref.verknüpfen(im Objektinspektor)-->bekomme ich nicht hin.

nehme ich anstatt der 2.Query eine Table und definiere für"Wicklungsart" ein Nachschlagefeld
und verknüpfe dann Query1 mit Table1 --> kein Problem.

wo ist denn mein Problem und wie bekomme ich das hin
Danke Klaus

[edit=r_kerber]SQL-Tags gesetzt. Mfg, r_kerber[/edit]

Leuselator 1. Dez 2003 02:20

Re: sql
 
Hi Klaus,

um das zu beantworten, müsstest Du schon die Tabellendefinitionen rüberrücken und biite nicht abkürzen (ref.Verknüpfen = referentiell verknüpfen?).

Nicht als Meckerei, sondern als Tip gemeint:
1. Man kann auch SQL-Statements so formatieren, das man selbst (und andere) besser den Überblick behalten.
2. Wenn Du schon Aliasse für die Tabellennamen benutzt (ist sinnvoll!), dann steele sie auch den Feldnamen voran - das vermeidet Konfusion.
3. bei 3 Tabellen und mehr, solltest Du Dir angewöhnen, mit joins zu arbeiten - erhöht die Lesbarkeit.
z.B.:
aus
SQL-Code:
SELECT id_Motorart, Motorart, id_Typenschild, sid_Motorart, sid_Fabrikat,
Typ, Drehzahl, Motornummer, Leistung_KW, id_Fabrikat, Fabrikat
FROM tbl_Motorart t1, tbl_Typenschild t2, tbl_Fabrikat t3 
WHERE (t1.id_Motorart=t2.sid_Motorart) AND(t2.sid_Fabrikat=t3.id_Fabrikat)
wird dann:
SQL-Code:
    SELECT MA.id_Motorart
           ,MA.Motorart
           ,TS.id_Typenschild
           ,TS.sid_Motorart
           ,TS.sid_Fabrikat
           ,TS.Typ
           ,TS.Drehzahl
           ,TS.Motornummer
           ,TS.Leistung_KW
           ,FB.id_Fabrikat
           ,FB.Fabrikat

      FROM tbl_Motorart AS MA
INNER JOIN tbl_Typenschild AS TS
        ON TS.sid_Motorart = MA.id_Motorart
INNER JOIN tbl_Fabrikat AS FB
        ON FB.id_Fabrikat = MA.sid_Fabrikat

           -- hier kommt dann eine echte Einschränkung, d.h. nicht die Bedingungen
           -- für die Joins sondern z.B.:
     WHERE TS.Leistung_KW > 50
       AND FB.Fabrikat in ('Siemens','Bosch','Allied Signal','Matsushita')
das macht es Dir wesentlich leichter, SQL-Statements zu lesen und der zeitliche Mehraufwand beim Formatieren wird mehr als wettgemacht durch schnelleres lesen (z.B. nach einem halben Jahr :-) )

Also - poste mal Deine TabellenStruktur, und Dir wird gehülft
Gruß

r_kerber 1. Dez 2003 05:54

Re: sql
 
Hallo Klaus,

Zitat:

Zitat von Klaus D.
das oben genannte Problem ist gelöst,

Und woran lag es?

Klaus D. 1. Dez 2003 19:24

Re: sql
 
Gruß
Ich habe als zip-Datei meine Datenbankstruktur hinterlegt(als Bild):
http://www.daberehlert.de/Arc32.zip

r_kerber: Und woran lag es(!die Klammern!)

danke und Tschüß aus Finsterwalde.......Klaus

Leuselator 1. Dez 2003 22:51

Re: sql
 
mir ist immer noch nicht ganz klar, was Du mit
Zitat:

2 Querys referentiell verknüpfen
meinst. Kenne Referentielle Bezüge/Integritäten zwischen Tabellen einer DB, nicht jedoch zwischen 2 Querys/Abfragen. Aber vielleicht hab ich nur mal wieder 'nen Knoten im Kopf.
Also wenn ich nicht irre möchtest Du sowas: (?)
SQL-Code:
         SELECT  MA.id_Motorart
                 ,MA.Motorart
                 ,TS.id_Typenschild
--               ,TS.sid_Motorart -- unnötig, da gleich MA.id_Motorart
--               ,sid_Fabrikat   -- dto.              FB.id_Fabrikat
                 ,TS.Typ         -- auf Deinem Plan nicht zu sehen aus welcher Tabelle
                 ,TS.Drehzahl    -- dto. (eventuell Tabellen-Präfix berichtigen)
                 ,TS.Motornummer -- dto.
                 ,TS.Leistung_KW -- dto.
                 ,FB.id_Fabrikat
                 ,FB.Fabrikat
                 ,WD.id_Wickeldaten
                 ,WA.id_Wicklungsart
                 ,WA.Wicklungsart

           FROM tbl_Motorart MA
     INNER JOIN tbl_Typenschild TS
             ON TS.sid_Motorart = MA.id_Motorart
     INNER JOIN tbl_Fabrikat FB
             ON FB.id_Fabrikat = MA.sid_Fabrikat
-- die nexten Tabellen als left outer, weil ich davon ausgehe, dass nicht zu jedem Typenschild
-- zwingend ein Eintrag in tbl_Wickeldaten existiert wenn doch, dann kannst Du sie auch
-- inner joinen:
LEFT OUTER JOIN tbl_Wickeldaten WD
             ON WD.sid_TypenSchild = TS.id_TypenSchild
LEFT OUTER JOIN tbl_WicklungsArt WA
             ON WA.id_WicklungsArt = WD.sid_WicklungsArt

     WHERE (TS.Typ        like :p1) -- Tabellenpräfixe checken und ggF. anpassen
        OR (TS.Fabrikat   like :p1)
        OR (TS.Drehzahl   like :p1)
        OR (TS.Motornummer like :p1)
        OR (TS.Leistung_KW like :p1)
Das sollte schnuckeln...
Gruß

Edit: PS: ich habegerade gesehen, das die WickeldatenQuery in Deiner Text.rtf falsch ist - das letzte Komma vor dem FROM ist zuviel (beliebter Fehler - deshalb habe ich mir die Schreibweise mit vorangestelltem Komma (s.o.) angewöhnt, da man so mit cut&paste Spalten vertauschen kann, ohne Stress zu bekommen)

Klaus D. 2. Dez 2003 18:25

Re: sql
 
Morgen und Danke
Ich werde es mir gleich anschauen.(komme gerad von der Arbeit)
mit referentiell verknüpfen meine ich:die Referentielle Integrität zwischen den beiden Query's im Objektinspektor
oder zu Laufzeit)herstellen.
--------------------------------------------------
Ich habe einfach 2 DBGrid auf meine Form .
DBGrid(1)--->Query(1)
DBGrid(2)--->Query(2)
der User hat nur die Möglichkeit im Grid(1) zu arbeiten und zu suchen.
Die Query (2) darf eben nur die datensätze liefern die zu den aktiven Datensatz in Query (1) gehören.
oder nehme ich doch anstatt einer 2.Query einfach eine Table und erstelle Nachschlagefelder
für die Polzahl,Nutenzahl u.s.w.

Danke für Deine Ausdauer.Tschüß Klaus

Knoten im Kopf ?....kennnnn ich, lag aber bestimmt an meine Ausdrucksweise,
erkläre doch mal jemanden ein Problem wenn man selber nicht so richtig das Problem versteht !
Ich betreibe das Proggen eben nur als Hobby und mein größtes Problem ist mein Zeitproblem.
aber was soll's Danke für die schnelle Hilfe

r_kerber 2. Dez 2003 18:28

Re: sql
 
Zitat:

Zitat von Klaus D.
mit referentiell verknüpfen meine ich:die Referentielle Integrität zwischen den beiden Query's im Objektinspektor

Sollte man die RI nicht auf der DB definieren?

Klaus D. 2. Dez 2003 18:44

Re: sql
 
Gruß
ja das ist ja richtig ,mache ich in der "ARC32" von ADS(oder zu Laufzeit).
ich meine das ja so, daß ich doch der Query2 die MasterSource,Schlüssel und IndexName mitteilen muß.
So war es jedenfalls mit den Tables.

wenn ich in der Query(2) nur eine einfache SELECT Abfrage mache ohne irgendwelche Filter über "1"Tabelle
bekomme ich ja auch keine Probleme mit den verknüpfungsangaben im Objektinspektor.
Sobald ich aber die Abfrage über mehrere Tabellen mache und versuche die Angaben
(MasterSource,oder IndexName)im Objektinspektor zu machen bekomme ich einen Indexfehler
Tschö Klaus

ich glaube da muß ich irgendwie selber hinter kommen kann man halt schlecht erklären,
Danke und Tschüß Klaus

Leuselator 2. Dez 2003 21:38

Re: sql
 
ok. Jetzt glaube ich zu verstehen, was Du meinst. Das ist keine referentielle Integrität. Eher eine parameterabhängige Query. Machst Du so:

Query1:
SQL-Code:
         SELECT  MA.id_Motorart
                 ,MA.Motorart
                 ,TS.id_Typenschild
--               ,TS.sid_Motorart -- unnötig, da gleich MA.id_Motorart
--               ,sid_Fabrikat   -- dto.              FB.id_Fabrikat
                 ,TS.Typ         -- auf Deinem Plan nicht zu sehen aus welcher Tabelle
                 ,TS.Drehzahl    -- dto. (eventuell Tabellen-Präfix berichtigen)
                 ,TS.Motornummer -- dto.
                 ,TS.Leistung_KW -- dto.
                 ,FB.id_Fabrikat
                 ,FB.Fabrikat
           FROM tbl_Motorart MA
     INNER JOIN tbl_Typenschild TS
             ON TS.sid_Motorart = MA.id_Motorart
     INNER JOIN tbl_Fabrikat FB
             ON FB.id_Fabrikat = MA.sid_Fabrikat

     WHERE (TS.Typ        like :p1) -- Tabellenpräfixe checken und ggF. anpassen
        OR (TS.Fabrikat   like :p1)
        OR (TS.Drehzahl   like :p1)
        OR (TS.Motornummer like :p1)
        OR (TS.Leistung_KW like :p1)
Query2:
SQL-Code:
         SELECT WD.id_Wickeldaten
                ,WA.id_Wicklungsart
                ,WA.Wicklungsart
-               ,UndWasImmerDuSonstNochSoBrauchst

          FROM tbl_Wickeldaten WD
    INNER JOIN tbl_WicklungsArt WA
            ON WA.id_WicklungsArt = WD.sid_WicklungsArt
         WHERE WD.sid_TypenSchild = :id_TypenSchild
--                                  ^<--- der DoppelPunkt macht's!
Der Doppelpunkt vor dem "id_Typenschild" macht daraus einen Parameter. Der wird nun folgendermaßen aus der 1. Query immer dann mit einem frischen Wert versorgt, wenn dort ein anderer Datensatz gewählt wird:

Auf Formular gehören 2 TDataSources. Die eine im ObjektInspektor (Eigenschaft DataSet) an die 1. Query, die andere an die 2. Query hängen. Wieder im OI die Eigenschaft DataSource der 2. Query auf 1. DataSource (Die mit 1.Query verbunden ist) setzen.

Fertig. Muß gehen. Eigentlich. Probiermal. :gruebel:
Gruß

Klaus D. 2. Dez 2003 22:05

Re: sql
 
Morgen Leuselator
Der Doppelpunkt macht es.hab ich noch nirgends gesehen.
in meinem SQL-Buch stand auch nichts dazu, habe mir aber am Sonntag ein umfassenderes Werk bei Ebay ersteigert. mal schauen ob ich da weiter komme.
Danke noch mal.Tschö Klaus

PS.ist schon der Hammer wie ein wildfremde Leute helfen ! :cheers:

Klaus D. 3. Dez 2003 21:14

Re: sql
 
Gruß
Habe mich mit der Sache beschäftigt...sieht gut.
habe zwar noch ein Problem aber ich versuche es erst einmal alleine.
zu folgenden Codes habe ich aber noch eine Fräge:
Code:
 *SELECT* WD.id_Wickeldaten
* * * * * * * * ,WA.id_Wicklungsart
* * * * * * * * ,WA.Wicklungsart
-* * * * * * * *,UndWasImmerDuSonstNochSoBrauchst
* * * * * FROM tbl_Wickeldaten WD
* * INNER JOIN tbl_WicklungsArt WA
* * * * * * ON WA.id_WicklungsArt = WD.sid_WicklungsArt
* * * * *WHERE WD.sid_TypenSchild = :id_TypenSchild
--* * * * * * * * * * * * * * * * * ^<--- der DoppelPunkt macht's!
1:wieso brauche ich für "id_Typenschild" in der letzten Zeile keinen Tabellenpräfix.
2:unter welchen Stichpunkten muß ich suchen um etwas in der OH oder irgend einen SQL-Buch
zu diesem Thema zu finden wie heißt der Operator(= :)in der SQL-Sprache ?

Robert_G 3. Dez 2003 23:11

Re: sql
 
Für :id_Typenschild brauchst du keinen Tabellennamen, weil es keine Spalte, sondern eine Variable ist.

Schlag in deinem Buch mal unter Bind-Variable oder in der OH unter "Params property (TQuery)" nach.
In der OH ist dort auch gleich ein Code-Beispiel.

Hoffe es hat dir geholfen.

Leuselator 4. Dez 2003 01:17

Re: sql
 
Also ergänzend zum vorangegangenen Posting:

Der Doppelpunkt hat mit SQL herzlich wenig zu tun, er kennzeichnet einen Parameter für ein Delphi-TDataSet und soll Dir als Delphianer nur das Leben ein bisserl erleichtern.

Die TDataSet-Komponente "parst" (liest/durchsucht) Deinen SQL-Text und wenn sie auf einen Doppelpunkt stößt, interpretiert sie das darauf Folgende als Parameternamen (wie eine benamste Variable halt) und versucht dann, diesen Parameter-Platzhalter durch einen Wert zu ersetzen, bevor sie den SQL-Text auf die Datenbank losläßt (Die könnte mit dem Doppelpunkt/Parametername-Konstrukt nämlich nichts anfangen).

Da wir die 2. Query über die 1. DataSource an die 1. Query gebunden haben und dort ein Feld mit dem Namen "id_..." existiert, welches genauso heißt wie unser Doppelpunkt-Parameter, nimmt Dir die TQuery-Komponente Arbeit ab, indem Sie den Parameter in der 2. Query durch den entsprechenden Feldwert aus der 1. Query immer dann ersetzt, wenn dort ein Wechsel des Datensatzes vorgenommen wird.

Das gleiche Ergebnis würdest Du erzielen, wenn Du auf jeden Datensatzwechsel der 1. Query (Ereignis OnScroll) "von Hand" reagieren würdest und in der OnScroll-Routine der 1. Query folgendes tätest:
1. Schliessen 2. Query,
2. Löschen des SQL-Textes der 2. Query
3. denselben neu generieren (letzte Zeile dort:
Code:
Query2.SQL.Add('where sid_BlaBlaBla = '+IntToStr(Query1.FieldByName('id_BlaBlaBla').AsInteger));
4. 2. Query wieder öffnen

Du siehst, das die Doppelpunktvariante um einiges bequemer ist.

Ausserdem ist der Doppelpunkt so neu für Dich nicht - schau Dir mal Deine ursprünglichen Querys an - dort verwendest Du :p1 - das ist nix anderes als eine Variable Namens "p1", die Du dann später mit dem Wert des Edits füllst.

Gruß

Robert_G 4. Dez 2003 11:29

Re: sql
 
Ich hoffe das wird jetzt nich OT, aber Bind-variablen sind Bestandteil von SQL (wenigstens der Implementierungen in den "großen" DBs).

als Beispiel - Oracle anonym. Block:
SQL-Code:
DECLARE
   xyz VARCHAR2(20);
   CURSOR test_Cur(i_Name IN VARCHAR2) IS
      SELECT *
      FROM  scott.emp t
      WHERE t.ename = i_Name;

   test_Rec test_Cur%ROWTYPE;
BEGIN
   xyz := 'SMITH';
   OPEN test_Cur(xyz);
   FETCH test_Cur
      INTO test_Rec;
   CLOSE test_Cur;
END;
oder
SQL-Code:
DECLARE
   xyz     VARCHAR2(20);
   test_Rec scott.emp%ROWTYPE;
BEGIN
   xyz := 'SMITH';
   EXECUTE IMMEDIATE 'SELECT *' || chr(10) || 
                     'FROM  scott.emp t' || chr(10) ||
                     'WHERE t.ename = :i_Name'
      INTO test_Rec
      USING xyz;
END;
Im Statement-Cache taucht das auf:
(genau das gleiche wenn ich Bind-variablen in einer Delphi-Query verwende)
SQL-Code:
SELECT *   FROM SCOTT.EMP T WHERE T.ENAME = :b1

Garby 4. Dez 2003 11:56

Re: sql
 
Hallo,

@George: Du hast vollkommen recht. Wenn der DB-Server keine Variablen unterstützen würde, müsste er bei jedem erneuten Ausführung des Statements neu Parsen und den Ausführungsplan neu erstellen.
Ich glaube aber Leuselator meint das Verlinken zweier DataSets mittels TDataSet.DataSource. Da kann seine Aussage durchaus stimmen.

Klaus D. 4. Dez 2003 19:07

Re: sql
 
Hey
der Begriff Bind-Variable ist egal wo ich suche unbekannt.
Trotzdem Danke

Robert_G 4. Dez 2003 21:45

Re: sql
 
Wird vielleicht nur un Oracle so genannt, ich kenn's halt nur so.

Leuselator 4. Dez 2003 23:36

Re: sql
 
Bin verunsichert.
In MS-SQL (kenn ich ab besten - was nicht heißen muß das ich's gut kenne :-)) gibt es Variablen, die von der Deklaration dem Oracle-Statement sehr änlich sind:
SQL-Code:
Declare @Variablenname Varchar(30), -- @ leitet lokale Variable ein
        @@AndererName Integer      -- @@ für globale Variablen

set @Variablenname = 'Wert' -- Wertzuweisung in TransactSQL

select @@AndererName = id from Tabelle where Bedingung -- Wertzuweisung aus Abfrage

select * from Tabelle where ID = @@AndererName -- Zugriff auf Variable
Das alles versteht sich aber als "innerhalb des DB-Servers" gültig und zugreifbar. Wenn ich von Delphi aus, also von Clientseite(ausserhalb Server) solche Variablen füllen möchte, dann mache ich es bisher so:
Delphi-Quellcode:
Query.SQL.Add('Declare @MeineVariable Integer              ');
Query.SQL.Add('   set @MeineVariable = :MeinDelphiParameter'); // dieser Parameter wird von Delphi
Query.SQL.Add(' select *                                    '); // vor senden an die DB ersetzt
Query.SQL.Add('  from Tabelle                             '); // sagt zumindest der Profiler
Query.SQL.Add(' where Feld = @MeineVariable');
Ende meines Lateins.
Gruß
*InLernmodusUmschalt*

Robert_G 5. Dez 2003 09:17

Re: sql
 
@Leuselator
Dein ":MeinDelphiParameter" ist eine Variable mit der die DB arbeitet.
Außer die Standard Delphi Compos zum DB-Zugriff ersetzen tatsächlich den SQL-Code.
(Wär aber ziemlich bescheuert)


Variablen sollte man eigentlich immer verwenden und auf fixe Vergleiche verzichten.
SQL-Code:
XYZ = 'Hallo'
Denn wie Garby bereits sagte, deine DB wird jedesmal den Code neu Parsen müssen, die Ursprungsmenge der vorherigen Abfrage verwerfen und alles (wirklich alles!) neu holen.
Mit bind-Variablen bleibt das Statement gleich - Es wird also nur neu gefiltert.

Gerade in Anwendnugen, bei denen von vielen Clients ähnliche Abfragen gestellt werden wirst du merken, dass diese beim ersten Mal wie normal laufen und danach nur noch ein paar Millisekunden!

Ich hoffe das beendet jetzt diese OT - Variablendiskussion.

Klaus D. 7. Dez 2003 13:51

Re: sql
 
Hallo Delphi-Gemeinde
weiß jemand ob ADS mit dem Operator"AS" in einem SQL-String probleme hat?
Code:
SELECT * FROM tbl_Typenschild AS TS
fehler!
lasse ich "AS" weg klappt alles,im Codes vom Leuselator verwendete er einmal den Operator !(vom 1.12."3.20Uhr)
Danke Klaus :gruebel:

r_kerber 7. Dez 2003 14:56

Re: sql
 
Hallo Klaus,

wie es bei ADS weiß ich nicht. Ich verwende den Operator "AS" bei anderen DB's (Informix, Oracle, Interbase, ...) ausschließlich für Tabellenspalten. Bei den Tabellen selbst lasse ich diesen weg!

Robert_G 7. Dez 2003 19:48

Re: sql
 
"AS" kann man in Standard-SQL nicht für ein Tabellen-Alias verwenden, schreib das Alias einfach dahinter.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:40 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz