描述:实际运行的查询返回了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
**?**
发布于 2009-05-27 09:50:51
将变量和输入参数重命名,它们是不明确的。
此查询:
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
发布于 2009-05-27 10:39:01
请记住,将任何字符串与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()
函数在标准SQL中是一个有用的函数。它返回第一个非空参数。
发布于 2009-08-26 15:10:33
CONCAT_WS(分离器,str1,str2,.)CONCAT_WS()表示与分离器连接,是一种特殊形式的CONCAT()。第一个参数是其余参数的分隔符。分隔符在要连接的字符串之间添加:分隔符可以是字符串,其余的参数也可以是字符串。如果分隔符为空,则结果为空。函数在分隔符参数之后跳过任何空值。
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()跳过空字符串和空值。
https://stackoverflow.com/questions/917091
复制