2009-12-17 6 views
5

Ich bin auf der Suche nach einer ANSI-SQL-Methode, um eine Select-Abfrage ohne einen Datensatz zurück zu geben, sondern füllen Sie die Fields-Struktur eines TDataSet.ANSI Sql-Abfrage erzwingen Rückkehr 0 Datensätze

Die Methode, die ich gefunden ist durch Hinzufügen eines „1 = 0“ in jede Abfrage, zum Beispiel:

Select Id, name, province 
from customers 
where 1=0 

Dies ist ein ziemlich einfaches Beispiel ist, es stellt sich ein wenig komplizierter, wenn ich arbeiten muss mit Abfragen, die vom Benutzer eingegeben wurden, dann analysieren Sie sie, entfernen Sie die where-Klausel, wenn sie bereits eine hat, und ersetzen Sie sie durch "1 = 0".

Wenn die letzte Klausel in der vom Benutzer eingegebenen Abfrage der ist, wo Klausel, dann gibt es kein Problem, aber was ist komplizierter Abfragen wie folgt:

select 
    c.lastname, 
    sum(cs.amount) 
from customersales cs 
join customers c on c.idcustomer=cs.idcustomer 
/* where 1=0 */ 
group by c.idcustomer, c.lastname 

Durch die Verwendung der „1 = 0 "Methode, die einzige Möglichkeit, es im vorherigen Beispiel einfügen, ist mit einem ziemlich leistungsstarken SQL-Parser (nicht vergessen, der Benutzer kann komplexe Abfragen eingeben, darunter Unterabfragen und all das), Wer kann verstehen, wo diese Zeichenfolge enthalten.

Kennt jemand einen besseren Weg, dies zu tun? Ich kann "Limit 1" nicht verwenden, da es auf ANSI-Art sein muss.

+0

Für was Sie das brauchen? –

+0

Ich brauche das, weil ich einer Software eine Funktion hinzufüge, die es dem Benutzer ermöglicht, benutzerdefinierte Abfragen zu erstellen, dann die Abfragen zum Anzeigen von Diagrammen, Tabellen und zum Erstellen von Berichten mit diesen verwendet. Ich brauche das, um die Berichte zu entwerfen. Um den Report Designer mit den verfügbaren Datensätzen (extrahiert aus den benutzerdefinierten Abfragen) zu zeigen, brauche ich diese Funktion. Die "Datasets" sind einfache Listen von Feldern, die nach den Abfragen extrahiert werden. BTW, ich benutze FastReport 4. –

+0

zum Erstellen von benutzerdefinierten Abfrage: Warum verwenden Sie nicht schnell Abfrage-Generator mit schnellen Bericht enthalten. Und warum nicht schnell cube? –

Antwort

11

Was ist mit dem Hinzufügen eines eigenen SELECT um den SELECT des Benutzers?

SELECT * FROM (
select 
    c.lastname, 
    sum(cs.amount) 
from customersales cs 
join customers c on c.idcustomer=cs.idcustomer 
/* where 1=0 */ 
group by c.idcustomer, c.lastname 
) x 
WHERE 0=1 

EDIT:ORDER BY würde mit dieser Lösung nicht funktionieren, aber da Sie keine Zeilen bekommen, könnten Sie versuchen, dass aus der Abfrage zu entfernen, wenn nötig.

+1

Danke Peter, in PostgreSQL und Firebird getestet und es funktioniert !. Das einzige, was ich hinzufügen musste, war ein Alias ​​für die innere Abfrage. Wählen Sie * aus (innere Abfrage) AS FOO mit 1 = 0. Nochmals vielen Dank. –

0

Für zukünftige Referenz, falls Leute hier ein anderes Ziel haben: Beachten Sie, dass die WHERE-Klausel einen Widerspruch darstellt, wenn der Optimierer entscheidet, den Unterplan überhaupt nicht auszuführen. Also, wenn Sie einige Nebenwirkungen der Abfrage benötigen (sei es einen Cache warm, führen Sie eine Prozedur, was auch immer), beraten werden. Sie Ihre Anfrage um SET FMTONLY

SET FMTONLY ON SELECT * FROM tablename SET FMTONLY OFF 
0

wenn Ihre MSSQL Server verwendet, dann die Anweisung ‚vorbereiten‘ anstelle von ‚ausführen‘ können. Beim Vorbereiten wird die Anweisung einfach analysiert und die Feldliste zurückgegeben.

0

In Firebird wickeln können Sie es :-)

0

Oder

CustomerSQL='SELECT <Fields> FROM <Table>'; 
MySQL=Replace(CustomerSQL,'SELECT ','SELECT TOP 0 '); 

verwenden (vielleicht mit einigem Verstand Kontrolle, aber Sie bekommen die Idee - ein SELECT TOP 0 nur die Meta-Daten zurück, den Satzaufbau und keine Aufzeichnungsdaten enthalten).