2009-05-27 5 views
1

Описание: запрос реально работать уже 4 результаты возвращаются, как можно видеть из ниже, , что я просто concate пункты затем вернуться, , но неожиданно, это нуль.Почему эта функция MySQL возвращает null?

Я думаю, что код сам за себя:

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) 

Для тех, кто не думает, что код сами за себя:

Почему функция возвращает NULL?

+3

Вы должны написать описание с правильным вопросом. –

+2

Да, я действительно не думаю, что код не требует пояснений. Даже если люди могут понять это в конце концов, гораздо полезнее фактически объяснить словами, когда у вас есть такой код. – Noldorin

+0

Вы, парни, абсолютно правы, я исправил свою ошибку. – omg

ответ

3

Переименуйте переменные и параметр ввода, они неоднозначны.

Этот запрос:

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

возвращает ваши заявленные ранее переменные (которые NULL), а не столбцов таблицы.

Подготавливайте имена переменных и имя входного параметра под знаком подчеркивания.

Также вы сделаете дополнительное присваивание результата:

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>'); 

Обработчик устанавливает done после FETCH терпит неудачу, но result получает назначение, тем не менее.

Изменить обработчик:

DECLARE EXIT HANDLER FOR SQLSTATE '02000' RETURN result; 

Наконец: в MySQL, это может быть сделано с помощью одного запроса. Нет необходимости делать это с помощью функции.

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

Благодарим вас за ответ, попробовали, но без прогресса, как жаль! – omg

+0

Так почему же тогда это ответ? Какова была причина вашей проблемы? – VVS

+0

Запрос в курсоре выбранных переменных, а не столбцов – Quassnoi

1

Имейте в виду, что объединение любой строки вместе с NULL возвращает NULL. Попробуйте этот тест:

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

Это возвращает NULL.

Так как вы прокручиваете курсор, если столбцы body или created являются NULL в любой строке, то result становится NULL. Затем на последующих итерациях цикла ничего не контактирует с NULL result; он остается NULL.

попробовать что-то вроде этого:

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; 

COALESCE() функция является полезной функцией в стандартном SQL. Он возвращает свой первый аргумент, отличный от NULL.

0

Я стараюсь быть многословным, потому что ваш вопрос не является;)

Вы ожидали возвращаемое значение функции, чтобы быть не-NULL, так как вы создаете возвращаемое значение конкатенации только не NULL строки.

Только если одна из строк была NULL, полное возвращаемое значение было бы NULL. Ваши демо-данные содержат только значения NULL в имени screen_name, но вы соблюдали этот случай.

Но как-то (atm, я понятия не имею, как) одно из значений должно быть NULL, а соответствующая строка - с одним из больших CONCAT.

Что делать, если вы сократите соответствующую строку для отладки причинам до:

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

ли она по-прежнему возвращать NULL?

1

CONCAT_WS (разделитель, str1, str2, ...) CONCAT_WS() означает CONCAT С сепаратором и является специальной формой CONCAT(). Первый аргумент - это разделитель для остальных аргументов. Разделитель добавляется между строками, которые нужно конкатенировать: разделитель может быть строкой, как и остальные аргументы. Если разделитель равен NULL, результат будет NULL. Функция пропускает любые значения NULL после аргумента разделителя.

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' 

До MySQL 4.0.14, CONCAT_WS() пропускает пустые строки, а также пустые значения.