说明 实际运行的查询返回了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
?
答案 0 :(得分: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
答案 1 :(得分: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参数。
答案 2 :(得分:1)
CONCAT_WS(分隔符,str1,str2,...) CONCAT_WS()代表CONCAT With Separator,是CONCAT()的一种特殊形式。第一个参数是其余参数的分隔符。在要连接的字符串之间添加分隔符:分隔符可以是字符串,其余参数也可以。如果分隔符为NULL,则结果为NULL。该函数在separator参数后跳过任何NULL值。
的MySQL&GT;
SELECT CONCAT_WS(",","First name","Second name","Last Name");
-> 'First name,Second name,Last Name'
的MySQL&GT;
SELECT CONCAT_WS(",","First name",NULL,"Last Name");
-> 'First name,Last Name'
在MySQL 4.0.14之前,CONCAT_WS()跳过空字符串以及NULL值。
答案 3 :(得分:0)
我试着变得冗长,因为你的问题不是;)
您期望函数的返回值为非NULL,因为您通过仅连接非NULL字符串来创建返回值。
仅当其中一个字符串为NULL时,整个返回值才为NULL。您的演示数据仅在screen_name中包含NULL值,但您尊重这种情况。
但不知何故(atm我不知道怎么做)其中一个值必须为NULL,并且要查看的相关行是具有大CONCAT的值。
如果因调试原因将相关行缩短为:
,该怎么办?SET result = if(screen_name is not null,screen_name,'')
它是否仍然返回NULL?