MySQL数据库技术(36)[MySQL防范]
本文“MySQL数据库技术(36)[MySQL防范]”是由七道奇为您精心收集,来源于网络转载,文章版权归文章作者所有,本站不对其观点以及内容做任何评价,请读者自行判断,以下是其具体内容:
6.8 其他主题
? ? 本节包含几个主题,这些主题不完好合适于本章从client1 到client5 的开辟中的任一小节的内容:
? ? ■ 在利用后果集元数据帮忙考证这些数据合适于计算之后,利用后果集数据计算后果.
? ? ■ 若何处理很难插入到查询中的数据.
? ? ■ 若何处理图形数据.
? ? ■ 若何得到表构造的信息.
? ? ■ 常见的MySQL 程序计划错误及若何避免.
? ? 6.8.1 在后果集上履行计算
? ? 迄今为止,我们集合而主要地利用了后果集元数据来打印行数据,但很明显,除打印之外,还有需求利用数据做其他事情的时刻.比方,计算基于数据值的统计信息,利用元数据确保数据合适它们要满意的需求.哪类范例的需求?关于启动程序来说,大概要校验一下正
要履行数字计算的列实际上能否包含着数字!
? ? 下面的列表显示了一个简单函数summary _ stats ( ) ,它获得后果集和列索引,并产生列值的汇总统计.该函数还列出贫乏数值的数目,它是通过查抄NULL 来检测的.这些计算包含两个数据所必须满意的需求, summary_stats() 用后果集元数据来校验:
? ? ■ 指定的列必须存在(也就是说,列索引必须在后果集列值的范围内).
? ? ■ 此列必须包含数字值.
? ? 假如这些条件不满意,则summary_stats() 只打印出错误消息并返回.代码以下:
? ? 请注意在mysql_fetch_row() 循环前面调用的mysql _ data _ seek( ).为得到一样的后果集,它允很多次调用summary _ stats()(假定要计算几列的统计值的话).每次调用summary _ stats( )都要"重新回到"到后果集的开始(这里假定mysql_store_result() 成立后果集,假如用mysql_use_result() 成立后果集就只能按次序处理行,并且只能处理一次).summary_stats() 是个相对简单的函数,但它给我们一个提醒,就是若何编写一个对比复杂的计算程序,如两个列的最小二乘回归大概尺度统计,如t -查验.
? ? 6.8.2 对查询中有疑问的数据举行编码
? ? 包含引号、空值和反斜线的数据值,假如把它们插入到查询中,在履行查询时就会产生一些问题.下面的谈论阐述了这些难点,并介绍了办理的办法.假定要制作一个SELECT 查询,它基于由name 指向的空终结串的内容:
假如name 的值近似于"0’Malley, Brian",这时举行的查询就是不法的,因为引号在引用的字符串里呈现:
? ? 需求分外注意这个引号,以便使服务器不将它注释为name 的末尾.一种办法是在字符串内利用双引号,这就是ANSI SQL 约定.SQL 支持这个约定,也答应引号在反斜线后利用:
? ? 另一个有问题之处是查询中肆意二进制数据的利用,比方,在把图形存储到数据库这样的利用程序中会发生这种情形.因为二进制数值含有一些字符,把它放到查询中是不安全的.为了办理这个问题,可以利用mysql _ escape _ string( ),它可以对特别字符举行编码,使其在引用的字符串中可以利用.mysql_escape_string() 认为的特别字符是指空字符、单引号、双引号、反斜线、换行符、回车符和C ontrol - Z(最后一个在Windows 语言环境中呈现).什么时刻利用mysql_escape_string() 呢?最保险的答复是"始终".但是,假如确信数据的情势并且知道它是精确的—大概因为预先履行了确认查抄—就没必要编码了.比方,假如处理电话号码的字符串,它完好由数字和短线构成,那么就没必要调用mysql _ escape _ string( )了,不然还是要调用.
? ? mysql_escape_string() 对有问题的字符举行编码是将它们转换为以反斜线开首的2个字符的序列.比方,空字符转换为‘ \ 0’,这里的0 是可打印的ASCII 码0,而不是空.反斜线、单引号和双引号辨别转换为‘ \ \’、‘\’’和‘\"’.调用mysql_escape_string() 的历程以下:
? ? mysql_escape_string() 对from_str 举行编码,并把后果写入to _ str中,还增添了空终结值,这样很便利,因为可以操纵像strcpy() 和strlen() 这样的函数利用该后果串.from_str 指向包含将要编码的字符串的char 缓冲区,这个字符串大概包含任何内容,此中包含二进制数据.to_str 指向一个存在的char 缓冲区,在这个缓冲区里,可以写入编码的字符串;不要传送未初始化的指针或NULL 指针,但愿由mysql_escape_string() 分配空间.由to_str 指向的缓冲区的长度至少是(from_len*2)+1 个字节(极大概from_str 中的每个字符都需求用2 个字符来编码;额外的字节是空终结值).
? ? from_len 和to_len 都是unsigned int 值,from_len 表示from_str 中数据的长度;供应这个长度是非常必要的,因为from_str 大概包含空值字节,不能把它当作空终结串.从mysql_escape_string() 返回的to_len 值是作为后果的编码字符串的实际长度,没有对空终结值举行计数.
? ? 当mysql_escape_string() 返回时, to _ str中编码的后果便可看做是空终结串,因为from_str 中的空值都被编码为‘ \ 0’.
为了重新编写构造SELECT 的代码,使名称的值即便包含引号也能工作,我们举行下面的操作:
6.8.3 图象数据的处理
mysql_escape_string() 的基本功效之一就是把图象数据加载到一个表中.本节介绍若何举行这项工作(这个谈论也实用于二进制数据的其他情势).假定想从文件中读取图象,并将它们连同唯一的标识符存储到表中.BLOB 范例对二进制数据来说是个很好的挑选,因此可以利用下面的表阐明:
? ? 实际上,要想从文件中获得图象并放入images 表,操纵下面的函数load_image() 可以实现,给出一个标识标记码和一个指向包含这个图象数据的翻开文件的指针:
? ?load_image() 不会分配非常大的查询缓冲区( 1 0 0 K),因此它只能处理相对较小的图形.
? ? 在实际的利用程序中,可以按照图形文件的大小动态地分配缓冲区.处理从数据库中恢复的图形数据(或任何二进制数据)并不像开始把它放入时那样问题重重,因为在变量MYSQL_ROW 中数据值的原始情势是有效的,通过调用mysql _ fetch _length ( ),这个长度也是有效的.必须将值看做是计数串,而不是空终结串.
? ? 6.8.4 获得表信息
? ? MySQL 答应利用下面的查询获得有关表构造的信息(下面二者是等价的):
? ? 与SELECT 相近似,两个语句都返回后果集.为了在表中找出有关列,所需做的就是处理后果集合的行,从中获得有效的信息.比方,假如从mysql 客户机上公布DESCRIBE images 语句,就会返回这样的信息:
? 假如从自己的客户机上履行一样的查询,可以得到相同的信息(没有边框).假如只想要单个列的信息,则利用以下这个查询:
? SHOW FIELDS FROM tbl _ name LIKE "col _ name"
? 此查询会返回相同的列,但只是一行(假如列不存在就不返回行).
? 6.8.5 需求避免的客户机程序计划错误
? 本节谈论一些常见的MySQL C API 程序计划错误,以及若何避免其发生(这些问题在MySQL 邮件清单中会周期性地忽然呈现).
? 1. 错误1——利用未初始化的衔接处理程序指针在本章的样例中,我们已经通过传送NULL 参数调用了m y s q l _ i n i t ( ),这就是让它分配并且初始化MYSQL 构造,然后返回一个指针.别的一种办法是将指针传送到一个已有的MYSQL 构造中.在这种情形下, mysql_init() 会将构造初始化并返回一个指针,而没必要自己分配构造.假如要利用第二种办法,则要当心会呈现一些奇妙的问题.下面的谈论指出了需求注意的一些问题.假如将一个指针传送给mysql _ init( ),它应当实际指向某些东西.看下面的代码段:
? ? 这个问题是,mysql_init() 得到了一个指针,但指针没有指向所知的任何地方.conn 是一个部分变量,因此在main() 开始履行时它是一个能指向任何地方的未初始化的存储器,这就是说mysql_init() 将利用指针,并可在内存的一些肆意区域滥写.假如幸运的话, conn 将指向您的程序地址空间的外部,这样,系统将当即终止,使您能尽早意识到代码中呈现的问题.
? ? 假如不幸的话, conn 将指向程序中今后才利用的一些数据的内部,直到再次利用那个数据时才发现问题.因此实际呈现问题的地方远比执路程序时呈现的问题多,也更难捕捉到.下面是一段有问题的代码:
? 此时, conn 是一个全局变量,因此在程序启动前,将它初始化为0(就是NULL).mysql_init() 碰到NULL 参数,因此初始化并分配一个新的衔接处理程序.只要将conn 传送给需求非NULL 衔接处理程序的MySQL CAPI 函数,系统就会崩溃.这些代码段的改正就是确保conn 有一个可知的值.比方,可以将它初始化到已经分配的MYSQL 构造地址中去:
? ? 但是,举荐的(较简单的!)办理筹划仅仅是将NULL 显式地传送给mysql _ init( ),让该函数分配MYSQL 构造,并将返回值赋值给conn:
? ? 无论若何不要忘掉查验mysql_init() 的返回值,以确保它不是NULL.
? ? 2. 错误2——有效后果集查验的失利
? ? 请记着查抄但愿得到的后果集的调用状况.下面的代码没有做到这一点:
? ? 不幸地是,假如mysql_store_result() 失利,res_set 为N U L L,while 循环也不履行了,应测试返回后果集函数的返回值,以确保实际上在举行工作.
? ? 3. 错误3—— NULL 列值惹起的失利
? ? 不要忘掉查抄mysql_fetch_row() 返回的数组MYSQL_ROW 中列值能否为NULL 指针.假如row[i] 为N U L L,则在一些机械上,下面的代码就会惹起崩溃:
? ? 该错误危害最大的部份是,有些printf() 的版本很宽大地对N U L L指针输出了"( null )",这就使错误很简单逃脱而没有把错误定位.假如把程序给了朋友,而他只有不太宽大printf( )版本,程序就会崩溃,您的朋友会认为您是个无用的程序员.循环应当写成下面这样:
? ? 不需求查抄列值能否为NULL 的惟一一次是当已经从列信息构造肯定IS _ NOT _ NULL( )为真时.
? ? 4. 错误4——传送无意义的后果缓冲区
? ? 需求您供应缓冲区的客户机库函数普通要使这些缓冲区真正存在,下面的代码违反了这个法则:
? ? 问题是什么呢?to_str 必须指向一个存在的缓冲区,而在这个样例中没有,因此,它指向了随便的位置.不要向mysql_escape_string 传送无意义的指针作为to_str 参数,不然它会任意踩踏内存.
以上是“MySQL数据库技术(36)[MySQL防范]”的内容,如果你对以上该文章内容感兴趣,你可以看看七道奇为您推荐以下文章:
本文地址: | 与您的QQ/BBS好友分享! |