2013-10-10 9 views
5

Ich habe eine große Abfrage in Firebird (was ich Flamerobin laufen verwenden), um einen Parameter der ganzen Ort verwenden, aber die Abfrage unten immer tun laufen:Variable definieren und eine Abfrage ausführen, indem EXECUTE BLOCK

SELECT * FROM customers WHERE customerid = 1234; 

Ich möchte 1234 als eine Variable definieren, sagen customerID, so dass ich es leicht durch etwas anderes ersetzen kann.

Ich habe gelernt, dass ich dies in eine EXECUTE BLOCK setzen muss.

EXECUTE BLOCK 
AS 
DECLARE customerID INT = 1234; 

BEGIN 
    SELECT * FROM customers WHERE customerid = :customerID 
END 

Wenn von Bedeutung, die Fehler Ich erhalte ist Engine Message : Dynamic SQL Error SQL error code = -104 Unexpected end of command - line 3, column 26

Antwort

10

Das Problem ist, dass Flamerobin wissen muss, wenn eine Anweisung endet und die nächste Anweisung beginnt. Standardmäßig verwendet es dafür das Semikolon (;). Ein EXECUTE BLOCK ist jedoch im Wesentlichen eine gespeicherte Prozedur, die nicht in der Datenbank gespeichert ist, also enthält es PSQL-Code, der das Semikolon auch als Anweisungstrennzeichen verwendet.

Die Konsequenz daraus ist, dass Sie Syntaxfehler bekommen, weil FlameRobin unvollständige Anweisungen an den Server sendet (das heißt: es sendet eine Anweisung nach jedem ; es begegnet).

Sie müssen FlameRobin anweisen, einen anderen Anweisungsabschluss zu verwenden, indem Sie SET TERM verwenden. Andere Firebird Query Tools (zB isql) benötigen dies ebenfalls, aber es ist eigentlich nicht Teil der Syntax von Firebird selbst!

So müssen Sie den Code auszuführen, wie:

-- Instruct flamerobin to use # as the terminator 
SET TERM #; 
EXECUTE BLOCK 
AS 
DECLARE customerID INT = 1234; 

BEGIN 
    SELECT * FROM customers WHERE customerid = :customerID; 
END# 
-- Restore terminator to ; 
SET TERM ;# 

jedoch diese Weise wird nach wie vor zu einem Fehler führen, da diese Abfrage für PSQL ungültig ist: Ein SELECT in einem PSQL Block erfordern eine INTO Klausel zur Karte die Spalten zu Variablen. Und die Werte zu erhalten, aus dem EXECUTE BLOCK zurück Sie auch eine RETURNS Klausel angeben müssen Flamerobin wie im documentation of EXECUTE BLOCK beschrieben:

-- Instruct flamerobin to use # as the terminator 
SET TERM #; 
EXECUTE BLOCK 
    RETURNS (col1 INTEGER, col2 VARCHAR(100)) 
AS 
DECLARE customerID INT = 1234; 

BEGIN 
    SELECT col1, col2 FROM customers WHERE customerid = :customerID INTO :col1, :col2; 
    SUSPEND; 
END# 
-- Restore terminator to ; 
SET TERM ;# 

Soweit ich das SUSPEND wissen ist technisch hier nicht erforderlich, aber Flamerobin wird nicht Holen Sie die zurückgegebene Zeile, wenn sie nicht enthalten ist.

Das obige funktioniert jedoch nicht, wenn die Auswahl mehrere Zeilen erzeugt. Dafür benötigen Sie FOR SELECT ... DO mit einem SUSPEND kombiniert verwenden:

-- Instruct flamerobin to use # as the terminator 
SET TERM #; 
EXECUTE BLOCK 
    RETURNS (col1 INTEGER, col2 VARCHAR(100)) 
AS 
DECLARE customerID INT = 1234; 

BEGIN 
    FOR SELECT col1, col2 FROM customers WHERE customerid = :customerID INTO :col1, :col2 
    DO 
    SUSPEND; 
END# 
-- Restore terminator to ; 
SET TERM ;# 

Die SUSPEND hier gibt die Reihe und wartet, bis der Anrufer diese Zeile geholt hat und fährt dann mit der FOR Schleife. Auf diese Weise wird es über die Ergebnisse iterieren.

IMHO das zu viel Aufwand für die Parametrierung. Vielleicht möchten Sie einfach nicht parametrieren, wenn Sie flatorebin verwenden, oder ein Werkzeug verwenden, das nach Parameterwerten für die normalen Parameter-Platzhalter von Firebird fragt (aber um ehrlich zu sein, bin ich mir nicht sicher, ob es welche gibt).

+0

Ihre Proben funktionieren einwandfrei. Vielen Dank für Ihre Antwort.Es ist in der Tat zu viel Aufwand, um es umzusetzen, ich müsste viele Abfragen ändern. Aber zumindest weiß ich, dass ich an der falschen Tür weiß. –

-2
SET TERM #; 
EXECUTE BLOCK 
RETURNS (COL1 Varchar(5) , COL2 INTEGER , COL3 INTEGER) 
AS 
DECLARE customerID INT = 5; 
BEGIN 
    FOR SELECT COSP.OSP_COMPON,COSP.OSP_DIAS FROM COSP WHERE COSP.OSP_ORDEM=2 INTO COL1 , COL3 
    DO 
    FOR SELECT CMES.MESNUM FROM CMES WHERE CMES.MESNUM = customerID INTO COL2 DO SUSPEND; 
    SUSPEND; 
END# 
SET TERM ;# 

warum im Herbst?

Verwandte Themen