2009-05-27 35 views
1

Beschreibung: die Abfrage ausgeführt tatsächlich haben 4 Ergebnisse zurückgegeben, kann von unten sehen werden, , was ich habe ist concate nur die Einzelteile dann zurück, aber unerwartet, es ist null.Warum gibt diese MySQL-Funktion null zurück?

Ich denke, der Code ist selbsterklärend:

DELIMITER | 

DROP FUNCTION IF EXISTS get_idiscussion_ask| 

CREATE FUNCTION get_idiscussion_ask(iask_id INT UNSIGNED) RETURNS TEXT DETERMINISTIC 
BEGIN 
    DECLARE done INT DEFAULT 0; 
    DECLARE body varchar(600); 
    DECLARE created DATETIME; 
    DECLARE anonymous TINYINT(1); 
    DECLARE screen_name varchar(64); 
    DECLARE result TEXT; 
    DECLARE cur1 CURSOR FOR SELECT body,created,anonymous,screen_name from idiscussion left join users on idiscussion.uid=users.id where idiscussion.iask_id=iask_id; 
    DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done = 1; 

    SET result = ''; 
    OPEN cur1; 
    REPEAT 
    FETCH cur1 INTO body, created, anonymous, screen_name; 
    SET result = CONCAT(result,'<comment><body><![CDATA[',body,']]></body>','<replier>',if(screen_name is not null and !anonymous,screen_name,''),'</replier>','<created>',created,'</created></comment>'); 
    UNTIL done END REPEAT; 
    CLOSE cur1; 

    RETURN result; 
END | 

DELIMITER ; 

mysql> DELIMITER ; 
mysql> select get_idiscussion_ask(1); 
+------------------------+ 
| get_idiscussion_ask(1) | 
+------------------------+ 
| NULL     | 
+------------------------+ 
1 row in set (0.01 sec) 



mysql> SELECT body,created,anonymous,screen_name from idiscussion left join users on idiscussion.uid=users.id where idiscussion.iask_id=1; 
+------+---------------------+-----------+-------------+ 
| body | created    | anonymous | screen_name | 
+------+---------------------+-----------+-------------+ 
| haha | 2009-05-27 04:57:51 |   0 | NULL  | 
| haha | 2009-05-27 04:57:52 |   0 | NULL  | 
| haha | 2009-05-27 04:57:52 |   0 | NULL  | 
| haha | 2009-05-27 04:57:53 |   0 | NULL  | 
+------+---------------------+-----------+-------------+ 
4 rows in set (0.00 sec) 

Für diejenigen, die den Code nicht denken, ist selbsterklärend:

Warum gibt die Funktion NULL?

+3

Sie sollten eine Beschreibung mit einer richtigen Frage schreiben. –

+2

Ja, ich glaube wirklich nicht, dass der Code selbsterklärend ist. Selbst wenn die Leute es irgendwann herausfinden können, ist es viel hilfreicher, in Worten zu erklären, wenn Sie so viel Code haben. – Noldorin

+0

Ihr habt absolut Recht, ich habe meine Schuld korrigiert. – omg

Antwort

3

Benennen Sie Ihre Variablen und die Eingabeparameter um, sie sind nicht eindeutig.

Diese Abfrage:

SELECT body, created, anonymous, screen_name 
FROM idiscussion 
LEFT JOIN 
     users 
ON  idiscussion.uid = users.id 
WHERE idiscussion.iask_id = iask_id 

kehrt Ihre zuvor deklarierten Variablen (die NULL sind), nicht die Tabellenspalten.

Den Namen der Variablen und den Namen des Eingangsparameters mit einem Unterstrich voranstellen.

Auch stellen Sie eine zusätzliche Zuordnung führen:

FETCH cur1 INTO body, created, anonymous, screen_name; 
SET result = CONCAT(result,'<comment><body><![CDATA[',body,']]></body>','<replier>',if(screen_name is not null and !anonymous,screen_name,''),'</replier>','<created>',created,'</created></comment>'); 

Der Handler done setzt nach dem FETCH versagt, aber der result wird trotzdem zugeordnet.

Handler ändern:

DECLARE EXIT HANDLER FOR SQLSTATE '02000' RETURN result; 

Schließlich: in MySQL, kann dies mit einer einzigen Abfrage durchgeführt werden. Es ist nicht nötig, dies mit einer Funktion zu tun.

SELECT GROUP_CONCAT(CONCAT(result,'<comment><body><![CDATA[',body,']]></body>','<replier>',if(screen_name is not null and !anonymous,screen_name,''),'</replier>','<created>',created,'</created></comment>') SEPARATOR '') 
FROM idiscussion 
LEFT JOIN 
     users 
ON  idiscussion.uid=users.id 
WHERE idiscussion.iask_id = @_iask_id 
+0

Vielen Dank für Sie antworten, versucht, aber ohne Fortschritte, was für ein Jammer! – omg

+0

Warum ist das dann die Antwort? Was war der Grund für dein Problem? – VVS

+0

Die Abfrage im Cursor ausgewählte Variablen, nicht Spalten – Quassnoi

1

Beachten Sie, dass die Verkettung einer beliebigen Zeichenfolge mit einem NULL NULL zurückgibt. Versuchen Sie diesen Test:

mysql> SET @s = 'test string'; 
mysql> SET @s = CONCAT(@s, '<tag>', NULL, '</tag>'); 
mysql> SELECT @s; 

Dies gibt NULL zurück.

So wie Sie durch den Cursor, wenn die body oder created Spalten sind NULL in jeder Zeile, result wird NULL. Dann hat bei nachfolgenden Iterationen der Schleife alles, was mit einem NULL result verkettet ist, keinen Effekt; es bleibt NULL.

versuchen, etwas wie folgt aus:

REPEAT 
    FETCH cur1 INTO body, created, anonymous, screen_name; 
    SET result = CONCAT(result, 
     '<comment><body><![CDATA[', 
     COALESCE(body, ''), 
     ']]></body>', 
     '<replier>', 
     IF(COALESCE(anonymous, 0) != 0, COALESCE(screen_name, ''), ''), 
     '</replier>', 
     '<created>', 
     COALESCE(created, ''), 
     '</created></comment>' 
    ); 
UNTIL done END REPEAT; 

Die COALESCE() Funktion ist eine nützliche Funktion in Standard-SQL. Es gibt sein erstes Nicht-NULL-Argument zurück.

0

Ich versuche ausführliche zu sein, weil Ihre Frage ist nicht),

Sie erwarten den Rückgabewert der Funktion nicht-NULL zu sein, da Sie den Rückgabewert sind die Schaffung von nur nicht-NULL verketten Saiten.

Nur wenn einer der Strings NULL war, wäre der gesamte Rückgabewert NULL. Ihre Demodaten enthalten nur NULL-Werte in Bildschirmname, aber Sie haben diesen Fall berücksichtigt.

Aber irgendwie (atm ich habe keine Ahnung, wie) einer der Werte muss NULL sein und die relevante Zeile zu betrachten ist die mit dem großen CONCAT.

Was passiert, wenn Sie die entsprechende Zeile für Debug-Gründe verkürzen:

SET result = if(screen_name is not null,screen_name,'') 

Ist es immer noch NULL zurück?

1

CONCAT_WS (separator, str1, str2, ...) CONCAT_WS() steht für CONCAT With Separator und ist eine spezielle Form von CONCAT(). Das erste Argument ist das Trennzeichen für den Rest der Argumente. Das Trennzeichen wird zwischen den zu verkettenden Zeichenfolgen hinzugefügt: Das Trennzeichen kann eine Zeichenfolge wie auch die übrigen Argumente sein. Wenn das Trennzeichen NULL ist, ist das Ergebnis NULL. Die Funktion überspringt alle NULL-Werte hinter dem Separator-Argument.

mysql>

SELECT CONCAT_WS(",","First name","Second name","Last Name"); 
    -> 'First name,Second name,Last Name' 

mysql>

SELECT CONCAT_WS(",","First name",NULL,"Last Name"); 
    -> 'First name,Last Name' 

Vor MySQL 4.0.14, CONCAT_WS() leere Strings sowie NULL-Werte überspringt.

Verwandte Themen