![]() |
Params im ADOQuery nicht angenommen.
:wall:
Hallo, Wie kann es sein, daß zwei Queryobjekte verschieden reagieren? Ich stehe vor der Wand. Ich habe beide auf Prepared := true gesetzt, und will eine Abfrage starten. Bei diesem Code läuft alles gut:
Delphi-Quellcode:
Bei deisem nicht. Er sagt, daß er den Parameter PName nicht kenne. Selbst Wenn ich die Constante SQLSTOPPER direkt durch
intResult := conDB.BeginTrans;
try qrySQL.SQL.Clear; qrySQL.Prepared := True; intResult := qrySQL.SQL.Add( 'INSERT INTO tubes (name,description,customer,number,length,diameter,picturepath) '+ ' VALUES (:Pname,:Pdescription,:Pcustomer,:Pnumber,:Plength,:Pdiameter,:Ppicture)'); qrySQL.Parameters.ParamByName('Pname').Value := name; qrySQL.Parameters.ParamByName('Pdescription').Value := description; qrySQL.Parameters.ParamByName('Pcustomer').Value := customer; qrySQL.Parameters.ParamByName('Pnumber').Value := strtoint(ext1); qrySQL.Parameters.ParamByName('Pdiameter').Value := strtofloat(ext2); qrySQL.Parameters.ParamByName('Plength').Value := strtofloat(ext3); qrySQL.Parameters.ParamByName('Ppicture').Value := strPicturePath; intResult := qrySQL.ExecSQL; bolRet := true; conDB.CommitTrans; except bolRet := false; conDB.RollbackTrans; end; funcInsertArticle := bolRet; den SQL-String ersetze macht er es nicht. :-((((((
Delphi-Quellcode:
Das SQL-Statement ist in einer anderen Unit als Constante hinterlegt:
qryArticles.SQL.Clear;
qryArticles.Prepared := true; intRes := qryArticles.SQL.Add(SQLSTOPPER); qryArticles.Parameters.ParamByName('Pname').Value := 'test'; try intRes := qryArticles.ExecSQL; except end;
SQL-Code:
Vielen Dank und sorry für das große Post.
SELECT *
FROM stopper WHERE article_id IN (Select stopper_id FROM r_tubestopper WHERE tube_id = (Select article_id From r_articleproduct where name = :Pname AND article_id IN (Select article_id FROM tubes))) UNION SELECT * FROM stopper WHERE NOT EXISTS (SELECT * FROM stopper WHERE article_id IN (Select stopper_id FROM r_tubestopper WHERE tube_id = (Select article_id From r_articleproduct where name = :Pname AND article_id IN (Select article_id FROM tubes)))) Alexander |
Re: Params im ADOQuery nicht angenommen.
Vielleicht kommt die DB mit den UNIONS und 5 mio. Sub-scans nicht klar...
Bist du dir sicher, dass du einen Index-Scan über 3 bzw. 4 Level machen willst ?!? Nachtrag: Hatte dein "Prepared:= True" übersehen. :oops: |
Re: Params im ADOQuery nicht angenommen.
Also das Statement läuft. Ich habe es vorher direkt in der DB getestet.
Das Statement selber bekomme ich mit meinem Wissensstand immo auch nicht besser hin. Die Bedingungen sind auf jeden fall ein Muß. Könnte bestimme noch optimiert werden. Habe es jetzt aber zu laufen bekommen, in dem ich die Parameter verschieden benannt habe. irgendwie hat ihn es gestört, daß ich :Pname zwei mal im Statement hatte. Ist das normal? Naja, auf jeden Fall läuft es jetzt. Aber Vielen Dank |
Re: Params im ADOQuery nicht angenommen.
Wenn ich dein letztes Statement durch meine Oacle-IDE formatieren lasse, sieht es so aus...
SQL-Code:
Das muss einfacher gehen...
SELECT *
FROM stopper WHERE article_id In (SELECT stopper_id FROM r_tubestopper WHERE tube_id = (SELECT article_id FROM r_articleproduct WHERE Name = :Pname And article_id In (SELECT article_id FROM tubes))) UNION SELECT * FROM stopper WHERE Not Exists (SELECT * FROM stopper WHERE article_id In (SELECT stopper_id FROM r_tubestopper WHERE tube_id = (SELECT article_id FROM r_articleproduct WHERE Name = :Pname And article_id In (SELECT article_id FROM tubes)))) Zum Problem: Vielleicht musst du den zweiten Parameter umbenennen. Wenn ich in PL/SQL einen dyn. SQL benutze muss ich sogar für jedes Auftauchen einer Bindvariable einen Wert angeben! ... War ich mal wieder zu langsam... :mrgreen: |
Re: Params im ADOQuery nicht angenommen.
:-))
Aber trotzdem vielen Dank. Hast mich übrigens motiviert doch nochmal zu optimieren.
SQL-Code:
Soo, das ist schon mal ein Scan weniger. Aber hier habe ich jetzt das Problem, daß PostGres es in dem Vergleich nicht mag, daß die Felder die im letzten Select verglichen werden gleich sind. Es heißt "ERROR: Column reference "article_id" is ambiguous".
SELECT *
FROM stopper WHERE article_id IN (Select stopper_id FROM r_tubestopper WHERE tube_id = (Select article_id From r_articleproduct r, tubes t where r.name = 'test' AND r.article_id=t.article_id) UNION SELECT * FROM stopper WHERE NOT EXISTS (SELECT * FROM stopper WHERE article_id IN (Select stopper_id FROM r_tubestopper WHERE tube_id = (Select article_id From r_articleproduct, tubes where r.name = 'test' AND r.article_id=t.article_id) Dürfen die Felder wirklich nicht gleich heissen? mit dem r.article_id sind die doch eindeutig. Wenn ich in der Relationstabelle das feld auf article setzte und das Statement entsprechend ändere, dann lüpt es. Ne Idee? Vielen Dank, ALexander |
Re: Params im ADOQuery nicht angenommen.
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe die Abfrage als Textdatei angehängt. (Ich will ja nicht das sich hier noch einer die Maus wund scrollt :stupid: )
Ich habe nur schnell ein paar Klammern gesetzt und den Subselects ein paar Tabellenaliase gegönnt, müsste laufen. Ich kann mir das ja mal heute Abend genau anschauen, jetzt habe ich leider keine Zeit dafür :cry: Nachtrag: Um die Formatierung zu behalten musst du die Datei speichern (rechtsklick...). |
Re: Params im ADOQuery nicht angenommen.
Wenn ich das ganze durch meine eigene HumanBrainSqlEngine laufen lasse, kommt das heraus:
SQL-Code:
[Edit]Das Folgende wird sich später als voreilig von mir erweisen:[/Edit]
SELECT A.*
FROM stopper A INNER JOIN r_tubestopper B ON B.stopper_id = A.article_id INNER JOIN r_articleproduct C ON C.article_id = B.tube_id AND C.name = 'test' INNER JOIN tubes D ON D.article_id = C.article_id UNION SELECT A.* FROM stopper A WHERE NOT EXISTS ( SELECT article_id -- bloß keinen * hier! FROM stopper A INNER JOIN r_tubestopper B ON B.stopper_id = A.article_id INNER JOIN r_articleproduct C ON C.article_id = B.tube_id AND C.name = 'test' INNER JOIN tubes D ON D.article_id = Carticle_id ) und wenn ich mir das dann so ansehe, liefert diese Abfrage auf sehr umständliche Art und Weise das gleiche Ergebnis wie:
SQL-Code:
:-)
SELECT *
FROM stopper korrigiert mich, wenn ich das falsch sehe... Weiter: in Deinem "Where Not Exists"-Statement, solltest Du unbedingt den Stern "*" durch eine konkrete Spalte ersetzen - bringt mehr Speed. *sichgarnichtberuhigenkann* Gruß |
Re: Params im ADOQuery nicht angenommen.
Buahhaha
![]() Mann natürlich, erst alle bei denen es referenz. Einträge gibt, und dann alle wo es keine gibt... Ich habe ehrlich gesagt noch nicht mal genau hingeguckt... :roteyes: :oops: (das gibt 100 Minuspunkte auf dem Beitragszähler) |
Re: Params im ADOQuery nicht angenommen.
:)
Da muß ich Dich korregieren. Auf Grund der Problemstellung mit der ich das Programm erstelle entsteht folgende Abhängigkeit. Ich habe ein Produkt Röhrchen und Stopfen für Röhrchen. ein Produkt und ein Artikel (röhrchen oder Stopfen) werden in der n*m tabelle r_articleproduct in relation gebracht. Auf ein Röhrchen passen nur bestimmte Stopfen (Durchmesser) die in der r_tubestopper Relation dargestellt werden. So, ist in einem Produkt ein Röhrchen vorhanden, dann drüfen nur noch die Stopfen gezeigt werden, die auf grund der r_tubestopper relation zu dem in dem Produkt gehörigen Röhrchen passen. Ist kein Röhrchen im Produkt (r_articlesproduct) dann müssen alle Stopfen gezeigt werden (das ist die Union Abfrage); Somit ist es definitiv nicht "Select * From Stopper"; Zum * im Union. Da hast Du natürlich recht. Vielen Dank und gruß Alexander |
Re: Params im ADOQuery nicht angenommen.
Zitat:
Hat sich jetzt alles geklärt. Die Frage mit dem Error hat sich erledigt, da ich im SELECT nach article_id und nicht r.article_id gefragt habe. Alos vielen Dank :cheers: |
Re: Params im ADOQuery nicht angenommen.
[Edit]Und auch hier habe ich noch nicht nachgedacht:[/Edit]
Hi Alex! Ich verstehe Deine Ausführungen, aber in Bezug auf Die Query muß ich bei meiner Einschätzung bleiben - sie ist definitiv gleich select * from Stopper - d.h. Du erreichst das gewünschte Ziel so nicht. Was Du tust ist nämlich: Select * from Tabelle Where Bedingung + Select * from Tabelle Where nicht Bedingung = Select * from Tabelle ohne Bedingung Wenn Du mir eine Tabellendefinition gibst, formulier ich Dir gern ein Statement, das auch tut, was Du von ihm erwartest. Gruß |
Re: Params im ADOQuery nicht angenommen.
Das Statement funktionert bei mir aber.
Die WHERE NOT EXISTS Bedinung gibt true oder false zurück, je nachdem ob schon ein Röhrchen in der Tabelle der r_articlesproduct ist oder nicht. Sobald keines mehr drinne ist, wird WHERE NOT EXISTS immer True und alle Stopper werden ausgegeben. Wenn nun aber ein Röhrchen in der Relation drinne ist, dann ist es immer false. Somit wird das UNION Select leer sein und nur die Obere Select Anweisung wirft Datensätze aus. Aber für Bessere Lösungen bin ich immer offen. Vielen Dank, Alexander |
Re: Params im ADOQuery nicht angenommen.
OffTopic:
Wie interpretiert die DB diese Statements :?: (vorsicht sehr lang!) DB: Oracle Der dargestellte "explain plan" zeigt in welcher Reihenfolge welche Operation ausgeführt wurde. Not Exists mit SELECT *
SQL-Code:
Optimizer Plan:
SELECT t.PkSeq,
t.PkDTc, t.PkYN, t.PkHH, t.PkMM, t.PkDT, t.PkTM, t.SubKey FROM MM07.PKPROFLO_update t WHERE Not Exists (SELECT * FROM MM07.ENROLL_data e WHERE e.Subject_ID = t.Subject_ID) ORDER By t.PkSeq
Code:
__________________________________________________ __________________________________________________ _______________________
Cost Cardinality Optimizer Options Operation Timestamp Bytes
SELECT STATEMENT, GOAL = CHOOSE 3 1 CHOOSE SELECT STATEMENT 17.02.2004 15:53:50 101 SORT ORDER BY 3 1 ORDER BY SORT 17.02.2004 15:53:50 101 FILTER FILTER 17.02.2004 15:53:50 TABLE ACCESS FULL MM07 PKPROFLO_UPDATE 1 1 ANALYZED FULL TABLE ACCESS 17.02.2004 15:53:50 101 1 INDEX UNIQUE SCAN MM07 ENROLL_DBIDX 1 1 UNIQUE SCAN INDEX 17.02.2004 15:53:50 3 Not Exists mit SELECT 1 num. Spalte
SQL-Code:
Optimizer Plan:
SELECT t.PkSeq,
t.PkDTc, t.PkYN, t.PkHH, t.PkMM, t.PkDT, t.PkTM, t.SubKey FROM MM07.PKPROFLO_update t WHERE Not Exists (SELECT e.Subject_ID FROM MM07.ENROLL_data e WHERE e.Subject_ID = t.Subject_ID) ORDER By t.PkSeq
Code:
__________________________________________________ _________________________________
SELECT STATEMENT, GOAL = CHOOSE 3 1 CHOOSE SELECT STATEMENT 17.02.2004 15:54:08 101
SORT ORDER BY 3 1 ORDER BY SORT 17.02.2004 15:54:08 101 FILTER FILTER 17.02.2004 15:54:08 TABLE ACCESS FULL MM07 PKPROFLO_UPDATE 1 1 ANALYZED FULL TABLE ACCESS 17.02.2004 15:54:08 101 1 INDEX UNIQUE SCAN MM07 ENROLL_DBIDX 1 1 UNIQUE SCAN INDEX 17.02.2004 15:54:08 3 Not in (SELECT...)
SQL-Code:
Optimizer:
SELECT t.PkSeq,
t.PkDTc, t.PkYN, t.PkHH, t.PkMM, t.PkDT, t.PkTM, t.SubKey FROM MM07.PKPROFLO_update t WHERE t.Subject_ID Not In (SELECT e.Subject_ID FROM MM07.ENROLL_data e) ORDER By t.PkSeq
Code:
SELECT STATEMENT, GOAL = CHOOSE 3 1 CHOOSE SELECT STATEMENT 17.02.2004 15:54:08 101
SORT ORDER BY 3 1 ORDER BY SORT 17.02.2004 15:54:08 101 FILTER FILTER 17.02.2004 15:54:08 TABLE ACCESS FULL MM07 PKPROFLO_UPDATE 1 1 ANALYZED FULL TABLE ACCESS 17.02.2004 15:54:08 101 1 INDEX UNIQUE SCAN MM07 ENROLL_DBIDX 1 1 UNIQUE SCAN INDEX 17.02.2004 15:54:08 3 |
Re: Params im ADOQuery nicht angenommen.
Wie man sieht, ist es für die DB egal, ob man not in () oder not Eists() verwendet.
"In ()" und "Exists ()" sind aber nicht äquivalent!!! |
Re: Params im ADOQuery nicht angenommen.
Ähh, da hast Du halb recht.
Denn SELECT * FROM Stopper WHERE NOT EXISTS () ist was anderes als SELECT * FROM Stopper WHERE article_id NOT IN (). Die Obere Bedingung verknüpft nicht mit einem Attribut im SELECT, sondern ist WHERE 1 oder WHERE 0; Somit werden alle angezeigt, wenn es keine Tube in r_articlesproduct gibt. Wenn es welche gibt, muß dann noch die Bedingung artcile_id NOT IN () stimmen. Somit ist es nicht die direkte verneinung. (A ^ B) v (C ^ not B) A = Select FROM Stopper Where NOT EXISTS B C = Select FROM Stopper Where article ID IN B B = Die Menge der Röhrchen die Zu dem Produkt gehören. gruß, Alexander |
Re: Params im ADOQuery nicht angenommen.
Es ging mir hauptsächlich darum, dass ein Select * in einen NOT Exists nicht langsamer als ein Select ID ist.
Ich habe einfach eine Abfrage genommen, die ich gerade in irgendeinem Fenster hatte und habe sie danch umgeformt. Im diesem Fall sind alle 3 Abfragen absolut identisch! |
Re: Params im ADOQuery nicht angenommen.
@George: das wiederum hängt stark vom Optimizer der verwendeten DB ab, und ist somit keine verläßliche Größe - das mit dem Stern kann man sich abgewöhnen. Tut nicht weh. und ist im Zweifel schneller. Und gerade bei komplexeren Querys kann man somit dem Optimizer (so er vorhanden/gut ist) unter die Arme greifen.
|
Re: Params im ADOQuery nicht angenommen.
@ahachmann: Ich muß Abbitte leisten! Du hast Recht, was das Not Exists angeht.
Da hatte Ich einen Knoten im Kopf der in Richtung: "where id not in(...)" ging. Sorry! *AschekübelNimmtUndÜberKopfStülpt* Gruß |
Re: Params im ADOQuery nicht angenommen.
Jeweils 1 join eingespart:
SQL-Code:
[Edit]Konnte auf diese Abkürzung nur kommen, weil mir ahachmann per PN das DB-Modell
SELECT S.*
FROM r_articleproduct AP INNER JOIN r_tubestopper TS ON TS.tube_id = AP.article_id INNER JOIN stopper S ON S.article_id = AP.article_id AND S.article_id = TS.stopper_id WHERE AP.name = 'test' UNION SELECT * FROM stopper WHERE NOT EXISTS( SELECT S.* FROM r_articleproduct AP INNER JOIN r_tubestopper TS ON TS.tube_id = AP.article_id INNER JOIN stopper S ON S.article_id = AP.article_id AND S.article_id = TS.stopper_id WHERE AP.name = 'test' ) zukommen lassen hat - aus dem ursprünglichen Post wäre man wohl nicht darauf gekommen.[/Edit] *BlamageSchweissVonStirnWischt* Gruß |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:58 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz