2010-11-25 36 views
3

我正在嘗試編寫一個存儲過程以將多行文本連接在一起以將其作爲單個字符串返回。例如:Firebird 2.1存儲過程以連接多行上的文本

CREATE TABLE TEST (
ID INTEGER, 
SEQ INTEGER, 
TEXT VARCHAR(255)); 

COMMIT; 

INSERT INTO TEST (ID, SEQ, TEXT) VALUES (1, 1, "LINE 1"); 
INSERT INTO TEST (ID, SEQ, TEXT) VALUES (1, 2, "LINE 2"); 
INSERT INTO TEST (ID, SEQ, TEXT) VALUES (1, 3, "LINE 3"); 

COMMIT; 

SET TERM !!; 
CREATE PROCEDURE concat_names (iID INTEGER) 
    RETURNS (CONCAT VARCHAR(2000)) 
AS 
DECLARE VARIABLE name VARCHAR(255); 
BEGIN 
    CONCAT = ''; 
    FOR SELECT TEXT FROM TEST where id=:iID INTO :name 
    DO BEGIN 
    CONCAT = CONCAT || name; 
    END 
END!! 
SET TERM ;!! 

commit; 

然而,當我運行:

select concat from concat_names(1); 

它總是返回零行。

任何想法?

回答

7

你忘記了SUSPEND。您的proc應該看起來像這樣:

SET TERM !!; 
CREATE PROCEDURE concat_names (iID INTEGER) 
    RETURNS (CONCAT VARCHAR(2000)) 
AS 
DECLARE VARIABLE name VARCHAR(255); 
BEGIN 
    CONCAT = ''; 
    FOR SELECT TEXT FROM TEST where id=:iID INTO :name 
    DO BEGIN 
    CONCAT = CONCAT || name; 
    END 
    SUSPEND; 
END!! 
SET TERM ;!! 

您可以在沒有存儲過程的情況下實現相同的結果。使用LIST聚合函數:

SELECT LIST(text, '') FROM TEST where id=:iID 

LIST的第二個參數是分隔符。如果您僅以字段名稱調用LIST,則將使用逗號','來分隔值。

+0

安德烈·HI的,暫停位的作品,但列表中沒有,因爲你不能保證行會由SELECT語句返回的順序。如果您通過SEQ列進行排序,則需要按它進行分組,然後不會返回正確的結果。我已經試過這個想法,它會更有效率。順便問一下,你是來自GBS的Andrei K嗎? – williamsdb 2010-11-26 08:47:31

0

在這種情況下現場測試可以奔空,你不想設置爲null整個結果使用它是有用的:的

CONCAT = CONCAT || coalesce(name,''); 

代替

CONCAT = CONCAT || name; 
0

不使用一個存儲過程和使用版本Firebird 2.5,LIST聚合函數將返回「列中非空值的逗號分隔字符串串聯」*。使用上述測試表,在SQL

SELECT LIST(TEXT) 
    FROM TEST 

回報

1號線,2,第3行

這可能是一些利益。

*從火鳥參考頁here