mysql_query() 和mysql_real_query() 的查询成功都会返回零值,查询失败返回非零值。查询成功指服务器认为该查询有效并接受,而且能够执行,并不是指有关该查询结果。例如,它不是指SELECT 查询所选择的行,或DELETE 语句所删除的行。检查查询的实际结果要包括其他的处理。
查询失败可能有多种原因,有一些常见的原因如下:
■ 含有语法错误。
■ 语义上是非法的例如涉及对表中不存在的列的查询。
■ 没有足够的权利访问查询所引用的数据。
查询可以分成两大类:不返回结果的查询和返回结果的查询。INSERT、DELETE和UPDATE等语句属于不返回结果类的查询,即使对修改数据库的查询,它们也不返回任何行。可返回的唯一信息就是有关受作用的行数。SELECT 语句和SHOW 语句属于返回结果类的查询;发布这些语句的目的就是要返回某些信息。返回数据的查询所生成的行集合称为结果集,在MySQL中表示为MYSQL_RES 数据类型,这是一个包含行的数据值及有关这些值的元数据(如列名和数据值的长度)的结构。空的结果集(就是包含零行的结果)要与没有结果区分开。
6.6.1处理不返回结果集的查询
处理不返回结果集的查询,用mysql_query() 或mysql_real_query() 发布查询。如果查询成功,可以通过调用mysql_ a ffected_rows() 找出有多少行需要插入、删除或修改。下面的样例说明如何处理不返回结果集的查询:
请注意在打印时mysql_ a ffected_rows() 的结果是如何转换为unsigned long 类型的,这个函数返回一个my_ulonglong 类型的值,但在一些系统上无法直接打印这个类型的值(例如,笔者观察到它可在FreeBSD 下工作,但不能在Solaris 下工作)。把值转换为unsigned long 类型并使用‘% l u’打印格式可以解决这个问题。同样也要考虑返回my_ulonglong 值的其他函数,如mysql_num_rows() 和mysql_ insert _ id ( )。如果想使客户机程序能跨系统地移植,就要谨记这一点。
mysql_ rows _ affected() 返回查询所作用的行数,但是受作用的行的含义取决于查询的类型。对于INSERT、DELETE 和UPDATE,是指插入、删除或者更新的行数,也就是MySQL实际修改的行数。如果行的内容与所要更新的内容相同,则MySQL就不再更新行。这就是说虽然可能选择行来更新(通过UPDATE 语句的WHERE 子句),但实际上该行可能并未改变。
对于UPDATE,受作用的行的意义实际上是个争论点,因为人们想把它当成被匹配的行即选择要更新的行数,即使更新操作实际上并未改变其中的值也是如此。如果应用程序需要这个信息, 则当与服务器连接时可以用它来请求以实现这个功能。将CLIENT_FOUND_ROWS 的flags 值传递给mysql_ real _ connect( )。也可以将CLIENT _ FOUND _ROWS 作为flags 参数传递给do _ connect ( );它将把值传递给mysql_ real _ connect( )。
6.6.2 处理返回结果集的查询
通过调用mysql_query() 和mysql_real_query() 发布查询之后,返回数据的查询以结果集形式进行。在MySQL中实现它非常重要, SELECT 不是返回行的唯一语句, SHOW、DESCRIBE 和EXPLAIN 都需要返回行。对所有这些语句,都必须在发布查询后执行另外的处理行操作。
处理结果集包括下面几个步骤:
■ 通过调用mysql_store_result() 或mysql_use_result() 产生结果集。这些函数如果成功则返回MYSQL_RES 指针,失败则返回N U LL。稍后我们将查看mysql_store_result() 与mysql_use_result() 的不同,以及选择其中一个而不选另一个时的情况。我们的样例使
用mysql_ store _ result( ),它能立即从服务器返回行,并将它们存储到客户机中。
■ 对结果集的每一行调用mysql_ fetch _ rows ( )。这个函数返回MYSQL_ROW 值,它是一个指向字符串数组的指针,字符串数组表示行中每列的值。要根据应用程序对行进行操作。可以只打印出列值,执行有关的统计计算,或者做些其他操作。当结果集中不再有行时, mysql_fetch_rows() 返回NULL。
■ 处理结果集时,调用mysql_free_result() 释放所使用的内存。如果忽略了这一点,则应用程序就会泄露出内存(对于长期运行的应用程序,适当地解决结果集是极其重要的;否则,会注意到系统将由一些过程所取代,这些过程消耗着经常增长的系统资源量)。
下面的样例轮廓介绍了如何处理返回结果集的查询:
我们通过调用函数process_result_set() 来处理每一行,这里有个窍门,因为我们并没有定义这个函数,所以需要这样做。通常,结果的处理集函数是基于下面的循环:
从mysql_fetch_row() 返回的MYSQL_ROW 值是一个指向数值数组的指针,因此,访问每个值就是访问row[i],这里i 的范围是从0到该行的列数减1。这里有几个关于MYSQL_ROW 数据类型的要点需要注意:
■ MYSQL_ROW 是一个指针类型,因此,必须声明类型变量为MYSQL_ROW row,而不是MYSQL_ROW *row。
■ MYSQL_ROW 数组中的字符串是空终结的。但是,列可能含有二进制数据,这样,数据中就可能含有空字节,因此,不应该把值看成是空终结的。由列的长度可知列值有多长。
■ 所有数据类型的值都是作为字符串返回的,即使是数字型的也是如此。如果需要该值为数字型,就必须自己对该字符串进行转换。
■ 在MYSQL_ROW 数组中,NULL 指针代表NULL,除非声明列为NOT NULL,否则应该经常检查列值是否为NULL 指针。
应用程序可以利用每行的内容做任何想做的事,为了举例说明这一点,我们只打印由制表符隔开列值的行,为此还需要另外一个函数, mysql_num_fields() ,它来自于客户机库;这个函数告知我们该行包括多少个值(列)。
下面就是process_result_set() 的代码:
process_result_set() 以制表符分隔的形式打印每一行(将NULL值显示为单词NULL),它跟在被检索的行计数的后面, 该计数通过调用mysql_num_rows() 来计算。像mysql_ affected_rows() 一样,mysql_num_rows() 返回my_ulonglong 值,因此,将值转换为
unsigned long 型,并用‘% l u’ 格式打印。
提取行的循环紧接在一个错误检验的后面,如果要用mysql_store_result() 创建结果集,
mysql_fetch_row() 返回的NULL值通常意味着不再有行。然而,如果用mysql_ use _ result( )创建结果集,则mysql_fetch_row() 返回的NULL 值通常意味着不再有行或者发生了错误。无论怎样创建结果集,这个测试只允许process_result_set() 检测错误。
process_result_set() 的这个版本是打印列值要求条件最低的方法,每种方法都有一定的缺点,例如假设执行下面的查询:
(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/bianchengyuyan/)
我们可以通过提供一些信息如列标签,及通过使这些值垂直排列,而使输出结果漂亮一点。为此,我们需要标签和每列所需的最宽的值。这个信息是有效的,但不是列数据值的一部分,而是结果集的元数据的一部分(有关数据的数据)。简单归纳了一下查询处理程序后,我们将在6 . 6 . 6节使用结果集元数据中给出较漂亮的显示格式。
打印二进制数据
对包含可能含有空字节的二进制数据的列值,使用‘ % s’printf() 格式标识符不能将它正确地打印; printf() 希望一个空终结串,并且直到第一个空字节才打印列值。对于二进制数据,最好用列的长度,以便打印完整的值,如可以用fwrite() 或putc( )。
6.6.3 通用目标查询处理程序
前面介绍的处理查询样例应用了语句是否应该返回一些数据的知识来编写的。这是可能的,因为查询固定在代码内部:使用INSERT 语句时,它不返回结果,使用SHOW TABLES语句时,才返回结果。
然而,不可能始终知道查询用的是哪一种语句,例如,如果执行一个从键盘键入或 猜你喜欢