弱检查变量
使用$@variable_name语法的变量不会检查类型,也不会检查之前是否给它分配过值,因此如果变量类型错误或未定义,MySQL不会报告任何警告或错误。例如,假设你将变量$@county写成$@conty了,由于拼写有误,这个错误的变量不会被赋予任何值,MySQL便会给它赋予一个“none”或“null”值。
在下面的例子中,我创建了一个变量@xml_cities,在文本节点中包含三个国家的城市,接着我创建了两个变量存储XPath信息,第一个SELECT查询显示@state_index_first变量和ExtractValue()函数的值,由于@state_index_first变量包含一个值“1”,//state[@state_index_first]表达式检索第一个城市的结果是“Chicago”。
第二个SELECT查询检索@state_index_second变量的值,以及ExtractValue()函数返回的结果,正如预期那样,它返回“Ocean City”。
最后一个SELECT语句有点问题,因为没有@state_index_third变量,ExtractValue()函数运行后无值返回,这样可能导致我们认为确实没有更多的城市。
-> <state value="New Jersey">Ocean City</state>
-> <state value="Maryland">Baltimore</state>';
Query OK, 0 rows affected (0.21 sec)
mysql> SET @state_index_first = 1, @state_index_second = 2;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT @state_index_first, ExtractValue(@xml_cities,
-> '//state[$@state_index_first]') AS 'First City';
+--------------------+------------+
| @state_index_first | First City |
+--------------------+------------+
| 1 | Chicago |
+--------------------+------------+
1 row in set (0.00 sec)
mysql> SELECT @state_index_second, ExtractValue(@xml_cities,
-> '//state[$@state_index_second]') AS 'Second City';
+---------------------+-------------+
| @state_index_second | Second City |
+---------------------+-------------+
| 2 | Ocean City |
+---------------------+-------------+
1 row in set (0.00 sec)
mysql> SELECT @state_index_third, ExtractValue(@xml_cities,
-> '//state[$@state_index_third]') AS 'Third City';
+--------------------+------------+
| @state_index_third | Third City |
+--------------------+------------+
| NULL | |
+--------------------+------------+
1 row in set (0.00 sec)
强检查变量
正是由于上面的原因,强烈建议使用强检查变量,这并没什么奇怪的,因为强检查变量作为计算机编程语言的一个标准已经有很长一段时间了,如果要使用$variable_name语法,需要在存储过程中声明变量,这样的变量属于本地变量,是要进行类型和值的检查的。
下面的存储过程接受一个xml_data字符串,并将ExtractValue()函数返回的结果添加到一个临时表中,这样我们就可以一次查询所有的城市了。
CREATE PROCEDURE get_cities(IN 'xml_data' varchar(255))
BEGIN
DECLARE i INT DEFAULT 1;
DECLARE city_name VARCHAR(100);
CREATE TEMPORARY TABLE cities (
match_number INT UNSIGNED NOT NULL DEFAULT 0,
name VARCHAR(100) NULL );
SET city_name = ExtractValue(xml_data, '//state[$i]');
WHILE city_name != "" DO
INSERT INTO cities
SELECT i, city_name;
SET i = i+1;
SET city_name = ExtractValue(xml_data, '//state[$i]');
END WHILE;
SELECT * FROM cities;
DROP TABLE cities;
END |
DELIMITER ;
CALL get_cities(@xml_cities);
+--------------------+------------+
| match_number | name |
+--------------------+------------+
| 1 | Chicago |
+--------------------+------------+
| 2 | Ocean City |
+--------------------+------------+
1 row in set (0.01 sec)
小结
虽然在MySQL中使用XML还有些限制,但每个新版本都会带来更多的与XML相关的功能,也有第三方厂家提供了工具来弥补这些缺陷。我希望未来看到支持新的,冗余更少的数据格式标记,如JSON。