Вопрос

Описание:Запрос фактически запускается 4 результата, возвращенных, как можно увидеть ниже, то, что я сделал, просто с умолчанием элементов, а затем возвращается, но неожиданно, он нулевой.

Я думаю, что код не требует пояснений:

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?

Это было полезно?

Решение

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

Этот запрос:

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

Другие советы

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

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

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

Итак, когда вы перемещаете курсор, если body или created столбцы имеют значение NULL в любой строке, result становится НУЛЕВЫМ.Затем на последующих итерациях цикла все, что объединяется с NULL result не имеет эффекта;он остается НУЛЕВЫМ.

Попробуйте что-то вроде этого:

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() function — полезная функция стандартного SQL.Он возвращает свой первый аргумент, отличный от NULL.

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() пропускала пустые строки, а также значения NULL.

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

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

Только если одна из строк была NULL, все возвращаемое значение будет NULL.Ваши демонстрационные данные содержат только значения NULL в имени_экрана, но вы учли этот регистр.

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

Что, если вы сократите соответствующую строку в целях отладки до:

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

Он все еще возвращает NULL?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top