http://www.cnblogs.com/snooper/archive/2009/09/07/1561715.html
mantis的安装配置(for windows)
http://blog.csdn.net/lyd518/article/details/1857073
下面是邮件服务器:
在c:\php-5.0.3\php.ini文件中查找smtp,将localhost改为你的发件服务器,如SMTP =
smtp.163.com
在php.ini文件中查找sendmail_from,将前面的分号去掉,并在后面填上邮件地址
在c:\mantis-0.19.2\config_inc.php文件中添加
$g_smtp_host='smtp.163.com';////IP地址也可以
$g_smtp_username='yourusername';
$g_smtp_password='yourpassword';
$g_phpMailer_method =2;
查找$g_return_path_email,将后面的邮件地址改为有效的地址,这一点非常重要,不然将无法正常
发送激活注册的邮件。
config_inc.php其它邮件地址最好也改为有效的地址。
$g_smtp_username,$g_smtp_password在服务器需要验证时用,不需验证时不用加,或设为
$g_smtp_username='
$g_smtp_password='
现在你可以注册新用户,并使用发送邮件功能了。
(4)关于界面语言(汉化)
在这个版本中已经自带了中文简体,以管理员身份登陆后,选择个人帐号(My Account),然后选择更改个人设置(Preferences),找到界面语言(Language),选择下拉列表中 chinese_simplified,点击更新设置(Updata Prefs)之后重新登陆就ok了
邮件服务器的配置:
1.fast mail
server安装可以网络上搜到,一路安装下来,设置SMTP gateways为你的IP取一个名字如:huan.com,
2.加用户:admin@huan.com
3,可用OUTLOOK设置验证你的邮件器是否可以发邮件
因为向往 所以选择了远方 因为无可依靠 所以必须坚强
BugFree是借鉴
微软的研发流程和
Bug管理理念,使用PHP+MySQL独立写出的一个Bug管理 系统。简单实用、免费并且开放源代码(遵循GNU GPL)。 命名BugFree 有两层意思:一是希望软件中的缺陷越来越少直到没有,Free嘛;二是表 示它是免费且开放源代码的,大家可以自由使用传播。
如何有效地管理软件产品中的 Bug,是每一家软件企业必须面临的问题。遗憾的是很多软件企业还是停留在作坊式的研发模式中,其研发流程、研发工具、人员管理不尽人意,无法有效的保证质量、控制进度,并使产品可持续发展。
具体安装操作步骤:
步骤一:下载XAMpp安装包
此安装包中有Apache 、
MySQL、PHP 等所需的工具
下载地址:http://www.apachefriends.org/zh_cn/xampp-linux.html
步骤二:安装
2、将下载的压包文件拷贝到 /opt 目录下
3、解压安装:
cd /opt
tar xvfz xampp-linux-1.7.7.tar.gz
注意:执行此命令时,会自动覆盖xampp旧版本
4.修改lampp的默认端口号80
vim /opt/lampp/etc/httpd.conf
修改80端口为自定义端口号
5.运行
/opt/lampp/lampp start
Starting XAMPP 1.7.7...
LAMPP: Starting Apache...
LAMPP: Starting MySQL...
LAMPP started.
【注意】如果启动失败,请先停掉相关服务httpd,mysql,ftp
pkill httpd
pkill mysql
pkill ftp
检查启动状态/opt/lampp/lampp status
6. 配置mysql(可参考http://www.cnblogs.com/dengzhangkun/articles/3664488.html)
登陆mysql (首次登陆密码为空)
Mysql -uroot -p
回车登陆
设置root密码:password=set password(‘123456’);
授远程登陆权限(navigate可以访问)
GRANT ALL PRIVILEGES ON *.* TO root@'211.151.97.%' IDENTIFIED BY '!@#$%^123456' WITH GRANT OPTION;
GRANT select,CREATE,INSERT,UPDATE ON *.* TO user_lampp@'211.151.97.%' IDENTIFIED BY '!@#123456';
执行flush privileges 刷新权限设置
7. 重启lampp
/opt/lampp/lampp restart
步骤三:下载BugFree并安装
1、下载地址:http://www.bugfree.org.cn/blog/?page_id=9 (bugfree官方网站)
2、下载完成后,先在本地机器,解压
3、将解压后的文件复制到Linux系统下 opt/lampp/htdocs 目录下
本地浏览器里登陆:
http://serverName:端口/bugfree/
然后一步一步设置
检查环境
① 安装页面提示,设置文件库读写权限
② cd /opt/lampp/htdocs
③ mkdir BugFile
④ 创建BugFile文件夹
⑤ 配置读写权限
⑥ chmod 777 /opt/lampp/htdocs/BugFile
⑦ chmod 777 /opt/lampp/htdocs /bugfree/assets
⑧ chmod 777 //opt/lampp/htdocs /bugfree/protected/runtime
⑨ chmod 777 -R /opt/lampp/htdocs /bugfree/protected/config
⑩ chmod 777–R /opt/lampp/htdocs /bugfree/install
设置数据库地址、用户名、密码、数据库名
安装
TestLink所需环境为PHP+MYSQL (支持MS
SQL等),系统推荐使用PHP5.2,安装成功以后,如果运行时出错,主要两种错:
[1].HP Warning: strtotime(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'UTC' for '8.0/no DST' instead in XXX
解决该错误的方法是找到错误的PHP文件,打开
1、在php文件头加上:date_default_timezone_set("PRC");
2、更改php.ini种date.timezone的属性值为PRC,同时去掉前面的注释就可以了。
[2].Deprecated: Function ereg_replace() is deprecated in D:\Program Files\Apache Software Foundation\Apache2.2\htdocs\testlink\lib\functions\lang_api.php on line 173
解决该错误的方法是打开PHP.INI文件,将
;extension=php_mbstring.dll
改为
extension=php_mbstring.dll
以及将
;mbstring.func_overload = 0
修改为:
mbstring.func_overload = 7
修改之后,系统成功运行
进去之后,还会发现一个WARNING:
There are security warnings for your consideration. To disable any reference to these checkings, set $tlCfg->config_check_warning_mode = 'SILENT';
这需要打开TestLink下config.inc.php文件,将
$tlCfg->config_check_warning_mode = 'FILE';
改为
$tlCfg->config_check_warning_mode = 'SILENT';
再运行,WARNING消失!
1. Testlink 中新增custom field。
2. 用例中custom field中加入该用例对应测试类名和方法名,格式:com.example.demo.TestUrl#prodApi。
3. Jenkins中安装Testlink Plugin,安装后在“管理Jenkins”->“组态设定”->“TestLink Installation”中填入你的Testlink资料。
URL:http://localhost/testlink-1.9.9/lib/api/xmlrpc/v1/xmlrpc.php
Developer Key:在Testlink的“My Settings”->“API interface”中,“Generate a new key”。
4. Jenkins的专案设定中,“新增建置后步骤”选择“Invoke Testlink”,然后在“TestLink Configuration”中填入Testlink中对应的资料。然后“Result Seeking Strategy”->“add strategy”选择“
JUnit method name”并填入对应资料(“Include Pattern”填入“**/TEST-*.xml”)。
5. 构建项目,完成后应该见到Testlink有相应的执行结果。
CERT安全编程团队,隶属于卡内基梅隆大学软件工程学院,最近发布了
Android平台上Java应用的安全编程指南。
CERT在该领域已经有所积累,并且在2013年发布CERT Java安全编程规范,后来出版Java编程指南:可靠安全编程的75条建议一书,该Android指南是对以上
工作成果的拓展和延伸。所以,在新版Android编程规范和指南中,一部分是参照已有的Java规范指南,当然也少不了与Android相关,致力于解决
移动相关问题的新规则。
Lori Flynn是发起CERT Android编程规范和指南的研究人员之一,据她所说,“其他地方也存在这样的Android安全编程建议,但是我们发现这些建议都不完整并且分散在网络的各个角落。”CERT研究人员采用以下三种方式制定了新版Android编程规范与指南:
挖掘CERT已有的安全编程规范;
研究已有漏洞
数据库,包括国土安全部的国家漏洞数据库等;
研究目前与安全相关的文献,比如,研究论文、在线
文章以及安全会议演讲等。
所有规范和指南都可以在CERT Wiki上获取。每条记录以简要概述开头,然后描述此条规范所要解决的安全问题,并且包括违规代码案例。Wiki中还提供了基于严重程度的评分、漏洞被恶意使用的可能性,以及如果在代码中发现漏洞,修复漏洞的成本等。
小编联系了Lori Flynn,并针对CERT Android安全编程规范和指南采访了她。Lori目前在CERT的工作不仅包括完善新版安全编程规范,还包括对移动应用进行组合性静态分析,检查是否符合Android平台的数据流规则。她工作经历丰富,包括网络安全研究,基于标准的安全分析,以及合作开发了一种检测多态程序的新型静态分析方法,并且取得了专利。Flynn在圣克鲁斯获得了加利福尼亚大学的计算机科学博士学位,她的研究方向是移动自组网络的安全多播路由协议。
Lori,您能简要介绍一下Android安全编程规范和指南的目标受众有哪些吗?
我们制定的Android安全编程规范和指南目前主要面向使用Java语言的Android应用开发人员。但是,我们也在着手制定适用于基于底层(非Java)语言如C和C++所开发应用的安全规范。我们的目标是帮助开发人员构建可靠安全的系统,但是这些规范和指南对实现其他质量特性如可靠性也大有裨益。
所有希望保护客户系统免受危害的组织或个人,在其开发人员遵循规则和指南并产出安全代码后,都会从中受益。金融、卫生和防御系统都必须小心保护其应用所处理的信息。有些应用处理的数据非常敏感——比如,用户的信用卡信息、位置、短信、联系方式和照片。除了对用户造成潜在伤害外,非安全代码可能会使处于金融风险中的开发人员走上法庭,也可能使整个公司失去公众信任(和导致销售损失),或导致困难局面,使给公众造成不安全印象的单应用销售乏力。
总而言之,知晓Android安全编程规范和指南,不论对于大型组织还是独立应用开发者都会有所帮助。
软件开发管理者、软件需求方,或者其他软件开发和需求专家可以将安全编程规范作为禁止性需求的参考。教育工作者也可以通过该指南教会学生安全开发Android应用的方法。
据您所知,移动相关人员在碰到应用安全问题时面临的主要挑战是什么?在移动领域,您是否知道某些特定安全相关问题?
除了已知的公认安全编程问题以及规范和指南给出的修复方法外,无法有效把控应用的数据去向也是我们面临的挑战之一。信息泄露如此泛滥,Android应用之间的相互影响是主要原因。我们目前正在研发静态分析工具,用于检测和消除这些漏洞。有了这些工具,用户——包括个人和组织——将更有信心解决部分应用的数据泄露问题。然而,尽管我们目前的工作有效促进了安全分析的发展,但是还是无法解决底层代码或反射面临的安全问题。数据流安全问题同样非常严重,所以有许多工业界和学术界的研究人员在这方面倾注心血。
另一个问题是可用性。实际上在我们深入分析数据流时,应用需要给用户展现对应选项,还得让用户(开发人员用户排除在外)容易明白这些选项的意义。Adrienne Porter Felt(
Google)已经发表了若干非常优秀的研究论文,分析了用户界面安全问题并给出了修复建议。她的工作涉及面向开发人员的可用性问题,比如与权限相关的不恰当API,可能导致正常开发人员的权限过大,进而被恶意应用利用。
Android安全还面临另一个问题,在Google修复Android暴露的安全问题后,因为各种原因,移动运营商可能在很长时间后才将安全更新推送给用户。这就导致在这段时间内,与应用相关的数据将面临巨大的风险。
遵循Android安全编程规范和指南,对应用有哪些好处?您有没有这方面的案例,遵循指南后,应用能够避免以前遇到的安全问题?
如果我们能够严格遵守Android安全编程规范和指南,数据和系统会更安全。举个例子吧,DRD00-J禁止将敏感数据保存到SD卡中,因为其他应用可以读取SD卡,DRD01-J限制内容提供者中敏感数据的权限等。Skype的Android应用曾经出现过一个漏洞,该应用将联系信息和个人用户信息保存在未加密数据库中,并且没有实施权限控制。如果应用遵守DRD01-J就可以避免该问题。
为了改善语言的安全现状,SCI(Secure Coding Initiative)发起了开发编程语言国际规范的工作。该规范致力于防范代码漏洞,并充分利用在研发CERT安全编码规范和
一致性测试中所收集的信息。
您对应用CERT安全编程规范和指南有哪些建议方法,工具、流程或其他方法都可以?感兴趣的开发人员或组织要如何开始呢?
我建议开发人员首先通读我们的技术报告,移动源码安全分析实验室:Java和Android安全编程规则和分析,然后浏览Android安全编程首页。我们打算创建单独的CERT编程规范,就像其他CERT安全编程规范一样可以通过CERT编程规范Wiki主页访问。该首页概述了我们目前在研发Android安全编程规范方面的工作:分析(适用性)和扩展已有Java规范;分析(适用性)和扩展Java指南,虽然该指南还在制定过程中;制定面向Android的安全编程规范,但该规范并不一定只针对Java语言。查看出现在首页中的三个主题链接,这是Android安全编程规范制定中的主要课题。
接下来,我建议开发人员浏览一遍DRD规范和指南,并考虑如何将它们应用到应用编程中。然后,我建议大家阅读Java CERT
Oracle安全编程规范(Addison-Wesley Professional, 2011)中适用于Android的Java规范,包括Wiki,关注该书相关的主题。这些规则是安全应用必须遵守的,这也是将其放在指南前面的原因。读完规则后,以同样方式阅读Java编程指南:可靠安全编程的75条建议(Addison-Wesley Professional,2013)。虽然我们不一定能够立即将书中列出的规范和指南应用到工作中,但是这些知识精华会印入我们的脑海,当开发应用需要用到这些规范和指南时,我们可以再仔细查看。另外我们值得做的是订阅安全编程简报,LinkedIn上的安全编程讨论,还有安全编程wiki中的提醒,当增加新规范和指南时会立即提醒。这些渠道有助于开发人员及时知晓安全方面的修复程序。
您在Android安全编程规范方面的工作完成了吗?或是您有没有设想将来涉及其他领域?
我们在Android安全编程指南方面的工作还在继续。另一个我们特别想研究的领域是分析CERT安全编程指南在基于C和C++的Android应用中的适用性。我们已经有了初步的分析,但是要检验Android底层编程接口如何影响已有编程规则的适用性,还要付出更多努力。同时,我们也会完善应用于反射的初步规则和指南。
你们的团队还有其他类似的项目吗?
我们的CERT安全编程倡议(SCI)已经为C、C++、Java和Perl制定了安全编程规范,其中一些规范已经被像Cisco和Oracle这样的企业在公司范围内采用。我们鼓励开发人员以及其他使用这些语言工作的组织使用我们的安全编程规范,这将会带来诸多好处,就像使用Android安全编程规范和指南一样。
SCI的目标是将漏洞的数目降低到某个级别,有效缓解运营环境中的风险应用。该目标通过在实现和测试阶段预防编程错误或检测并清除安全缺陷来达成。同时,SCI也在持续壮大源码分析实验室(SCALe),支持根据我们的编程规范对系统进行一致性测试,包括针对移动平台(Mobile SCALe)的一致性测试。移动SCALe目前专注于Android平台,因为这是我们在制定安全编码规范和指南时所面向的首个移动平台。我们还计划支持针对Apple iOS和Microsoft
Windows 8的安全编程规范和一致性测试。
前面说到在实施冒烟
测试自动化时候,当时使用的selenium1.0所支持的浏览器版本太低,无法满足我们的需求,面对这个问题,唯有升级我们的框架,可是面前有1千多条自动化用例等着,的确需要花费很大的人力和时间来完成。当时后台组也已有人研究过Webdriver,在其中一个产品中用起来了,但是并没有对原来的东西全部升级,不过至少证明了它的实用价值。当时我跟我老大说我研究下Webdriver,OK的话要不我们索性全部升级吧。当时他还持怀疑的态度,毕竟这并不是一个小的
工作量。
就这样开始了升级之旅。刚开始时就是我自己查了很多的资料,通过新建一个项目,把原来下面所有内容复制过来,把Maven的POM文件中dependency全部改成了全新的Webdriver,然后对框架中driver实例化的地方进行了修改,当然这些还远远不够。因为两个版本设计理念不一样,原来的方法也无法通用,为了便于日后分享给大家顺利开展工作,是很有必要把两个版本如何操作页面元素的做个对比。接下来就是把我们日常用到的方法罗列出来,包括打开页面,点击元素,输入,下拉选择,单选,复选,获取文本内容,弹出框,frame的操作等等,接着把在1.0里的方法写出来,把2.0对应的方法也写出来,然后再对其中一条用例进行实验,把底层这些方法改成新的。
到这里,钻研之路就进行的差不多了,见证奇迹的时刻到了。如果我说一运行case就通过了,也许这并不值得怀疑,但是事实上并没有这么顺利,中间遇到的诸多事宜我也记不清了,但是好在最后的确是通过了。我甚是欣喜,告诉了我老大,同时我组织我们组其他几个做自动化的同学开始了全面的升级行动。我把中间做过的事情整理成了文档,把1.0 VS 2.0的方法整理成表格,方便大家对照修改。当时我们做这个的顺序是:第一步,把所有底层的方法对照着表格全部改完,认真思考的你可能也看出来了,这的确是个苦差事,已经没有什么技术含量了;第二步,分工把所有的冒烟级别用例重新调试运行直到测试通过。
经过大家一个Q的努力,升级工作圆满结束,不过在这之后,原来那1千多条case其实也被我们放弃了,主要原因并不是调试的工作量,而是那些是之前专门的自动化组写的用例,很多都不是按照业务重点来写的,对我们的价值并不大,之后我们所完成的400多条都是基于重新梳理手工用例后实施的,当然这些也都是基于新升级的框架上写的。当时在升级过程中关于如何进行的修改还写了一篇博文,请查看历史
文章。
版权声明:本文出自 zzzmmmkkk 的51Testing软件测试博客:http://www.51testing.com/?258885
原创作品,转载时请务必以超链接形式标明本文原始出处、作者信息和本声明,否则将追究法律责任。
相关文章:
2014年4月21日,我很荣幸进入网易
工作,新的环境、新的同事及新任务项目对我来说都是全新的挑战,非常感谢领导、负责人及其他同事的关心照顾和指导。到网易已经一个多月了,针对这段时间的工作情况,做以下总结:
一、关于工作
1、熟悉
每个公司的项目产品流程都不一样的,换了工个环境,所熟悉的业务和环境都改变了,要从头开始了解。刚到网易,首先肯定是熟悉,熟悉同事、熟悉环境。一开始同事们就很照顾我,有问必答,让我一点点慢慢熟悉起来。虽然我是外包人员,但在这里完全感受不到以前听别人说的外包人员怎么怎么的情况。最开始,自己也有点顾忌,后来就想通了,感谢翟姐的一句话让我更有自信。第二步,熟悉项目、熟悉产品、熟悉业务,第一周,主要了解已有的产品和项目,照着已有的用例进一步了解。第二周,开始了解新项目需求。
项目、业务稍微熟悉了之后(好吧,其实很多东西都还不是很熟),慢慢开始参与新项目的测试分析和
用例设计,同事们很照顾,先分配了一些比较简单、比较基础的模块给我,让我慢慢上手。虽然大学毕业到现在2年多时间一直从事
软件测试,不过以前接触较多的还是
手机软件测试,在
web测试上是比较浅层的经验,也算个菜鸟吧,很多web测试需要注重的点会考虑不周全、隐藏点会遗漏,划分测试分析分类时思路比较乱,感谢丹姐帮我看测试分析,帮我分析比较清晰的思路和分类。设计测试分析和用例时注意一下几点:
1)熟悉需求和业务,不了解需求或需求不明确的情况不能盲目设计;
2)设计过程有疑点,需求有问题时及时与他人沟通,找策划确认,不要按照自己常理和想象做决定
3)考虑
测试用例的复用性,功能相似的模块可以考虑整合到一起,不需设计重复用例
4)对用例进行分类,划分思路清晰的分类,评审时能够让他人比较清晰的了解
5)根据测试用例的设计方法(等价类、边界值、错误推测、因果图等等)进行用例设计,当然也要根据产品模块情况,针对比适用的模块,可以减少一定工作量,不适用的模块反而会加大工作量。
3、测试维护任务
目前接触了两个维护任务,任务比较简单,但也不能因为简单而稍有马虎,要对维护任务的需求了解清楚,有针对性的测试。开发提测后,不仅要对修改的模块进行测试,还要了解修改的地方影响的范围,对有影响的地方也要测试回归一下。
做测试以来,一直对
自动化测试、
性能测试比较憧憬,自己也有买参考书、根据网上资料进行学习,不过平时不常用,时间一久就抛之脑后了(自己知道这个问题,一直努力改正来着)。
Dagger是网易杭研QA自己开发的一个WebUI自动化测试框架,基于
Selenium和TestNG组合和封装的。在熟悉环境和看测试分析的时候,看到刘主席在跟比我晚2天来的实习MM讲解这个框架,心里痒痒,一旁观摩了一下,然后问同事要了资料,空闲之余根据wiki上的资料例子学习,因为对Selenium和TestNG也不熟悉,使用过程中问题比较多,下载的包不对、缺少必要的jar包、执行wiki上的用例代码报错或找不到页面元素、缺少浏览器驱动等,然后网络上搜索各种问题解决方案。一些小问题基本解决了,想着拿现有网站练练手(这就是典型的还没学会走就想着飞啊),照葫芦画瓢的写了一堆,执行各种错误,度娘都解决不了了。所有还是要一步一个脚印慢慢走——先把Dagger放一边,找到一些比较基础的Selenium资料,目前正在循序渐进的学习,然后等Selenium扎实了继续学习TestNG,等这些都熟练了再去征战Dagger。
在今后的工作中,我会不断完善自己,提高业务&技术水平,相互学习,共同进步!做好自己的本职工作,为公司创造更高的价值,力争取得更大的成绩。
今天 在项目中看一个存储过程的时候,发现同事写的之前的有些逻辑错误,可能这个错误比较典型吧 拿出来分享一下,不使用公司的
数据库,所以在自己的机子上模拟了一下这个场景。OK
首先,就是2个表,
表temp1,包括id1,val1,2个字段,
表temp2,包括id2,val2 2个字段。
首先,情景大致是这样的,2个表的ID是有关联的,就是把temp2中包含的temp1的id的数据,在temp1中把val1都设置为1,不包含的设置为0.
首先,发一下之前错误的存储过程。
create or replace procedure mysdtest as cursor te_v1 is select id1,val1 from Temp1; cursor te_v2 is select id2,val2 from Temp2; v1_t te_v1%rowtype; v2_t te_v2%rowtype; begin open te_v1; loop fetch te_v1 into v1_t; exit when te_v1%notfound; open te_v2; loop fetch te_v2 into v2_t; exit when te_v2%notfound; if v1_t.id1=v2_t.id2 then update temp1 set val1='1' where id1=v1_t.id1; else update temp1 set val1='0' where id1=v1_t.id1; end if; end loop; close te_v2; end loop; close te_v1; end; |
这样写逻辑是存在问题的,2层循环,结果就会发现都是0,仔细读一下程序就会发现问题
比如说有一个值 t1 在表temp1中有值,应该更新val1为1,但是遍历到下一个t2时,此时t1不符合,然后就执行else 那么t1的val1就又变回了0,所以,程序执行完,都执行了else里面的,当然就错了。
正确的写法很多种,这里我就以设置带参数的游标为例,将2个游标建立关系,再进行遍历就不会出现问题。
如下:
create or replace procedure myt as cursor te_v1 is select id1,val1 from Temp1; cursor te_v2(idv2 varchar2) is select count(*) from temp2 where id2=idv2; v1_t te_v1%rowtype; numv varchar2(2); begin open te_v1; loop fetch te_v1 into v1_t; exit when te_v1%notfound; open te_v2(v1_t.id1); fetch te_v2 into numv; if numv=0 then update TEMP1 set val1='0' where id1=v1_t.id1; else update TEMP1 set val1='1' where id1=v1_t.id1; end if; close te_v2; end loop; close te_v1; end; |
ok,这种问题我们应该注意到
数据库是以某种数据模型所确定的数据结构方式来组织和存储某个组织(或部门)相互关联的数据集。数据库管理系统是一种帮助用户建立、使用、管理和维护数据库的计算机系统软件。或者说,数据库管理系统是开发一个实际应用数据库的工具并支撑其运行的平台。数据库管理系统必须与其管理的数据库的数据模型相一致。
1.数据模型
数据模型是对现实世界数据特征进行抽象的工具,用来描述和处理现实世界中的数据和信息。数据模型要能较真实地模拟现实世界,既要便于人们理解,又要便于在计算机上实现。数据模型主要由数据结构、数据操作、数据完整性规则三个部分组成。数据结构描述了组成数据库的基本成分;数据操作描述了对数据结构允许执行的操作集合;完整性规则描述了对数据结构所具有的约束和存储规则。
2.关系数据模型
关系数据模型的数据结构是人们日常事务处理中常见的二维表结构(如工资发放表)。关系数据模型将数据看成是二维表中唯一的行号和列号确定的一个表中元素,即关系数据模型是用二维表的方式来组织、存储和处理数据和信息的。从应用的角度来看,任何一个组织(或部门)的关系数据库的基本组成成分是二维表,或者说某个组织(或部门)的数据库是由若干张相互关联的二维表组成。由于二维表结构清晰、简单、易于理解,也易于计算机实现(存储、操作、控制),加上关系数据模型有数学理论基础(集合论、关系代数),因此现在的数据库管理系统软件都是基于关系数据模型研发的,如
SQL SERVER、ORACLE、DB2、SYBASE、ACCESS、FOXPRO等等。也就是说,用这些关系数据库管理系统软件为某个组织开发的会计数据库系统必须按关系数据模型来组织数据。那么,关系数据模型中的二维表与数据库中的数据文件之间有何联系?
下面我们通过会计科目代码表来介绍关系数据模型的基本概念及其与数据库中的数据文件之间的对应关系:
(1)关系、二维表、数据文件:关系数据模型中用关系来表述现实世界中能够相互区别的要管理的数据对象集。每一个关系都有一个关系名和一组表述其特征的属性集,人们就是通过这些属性集区别不同的关系。如记账凭证、会计科目、总账都可以称之为关系,它们都是要管理的数据对象集,都有各自的属性集。一个关系用一张二维表表示,表名对应关系名。二维表由有限个不重复的行组成,表中的每一列不可再分。一张二维表在关系数据库中用一个数据文件存储。如“会计科目代码表”在会计数据库中用一个数据文件存储,文件名可以用表名“会计科目代码”,使计算机中存储的文件内容与现实世界管理的数据对象相联系。
(2)记录:二维表中的每一行称为一个记录,描述了关系中一个具体的个体,在数据文件中是一个记录值。如表1中第一行为现金账户的记录,描述了现金账户在会计科目代码文件中所有属性的取值(特征)。
(3)属性、列、字段:二维表中的每一列是一个属性,描述了关系的一个特征。一个二维表的所有列构成了一个关系的属性集,通过它可以区别不同的二维表(关系)。二维表中的每一列的数据属于同一类型。每一列的列名对应关系的属性名,同时对应数据文件中的字段名。如表1用6个列表示会计科目代码的属性,其中第三列表示属性“科目性质”,当某条记录取值为1时,表示是资产类科目。
(4)主码、主关键字:指二维表中的某个列(属性)或某几个列(或属性组),它们的值能够唯一确定表中或数据文件中的一个记录。如表1中的“科目代码”属性可以作为主码(或主关键字),用来唯一识别表中的每一个会计科目。
(5)域:描述二维表中每一列属性或数据文件的某一字段的取值类型和范围。如表1中每一列的列名下面的括号中的内容表示该列的取值类型和范围,其中第四列“底层明细标志”表示某个科目是不是最底层明细科目(不再有下层科目),只有两种取值T(真)和F(假)。
(6)关系模式:一个关系模式由一个关系名及它所有的属性构成,它对应一个二维表的表名和表头栏目行(列的集合),构成了一个二维表的框架,同时也是设计该二维表的数据文件结构的依据。
至此,我们直观地介绍了关系数据库中的关系、二维表、数据文件之间各个概念的对应关系。由于二维表中的行与数据文件的记录、二维表的列(属性)与数据文件的字段之间相互对应,因此,审计人员只要掌握了会计账务数据库的二维表结构及表之间的关联也就能够分析电子账的结构。
例如,将会计科目代码表转换成关系数据库中的数据文件结构
3.关系数据模型的数据操作
从数学的角度看,关系数据模型的数据操作是基于集合的操作,操作对象和操作结果都是集合。从数据处理的角度看,数据操作的对象和结果都是二维表。对二维表的操作主要有:
(1)对表中的行(记录)进行操作:指对一张表中指定范围的记录进行有条件的操作,操作的结果组成一张新表。例如,从“会计科目代码表”中筛选出资产类科目组成新的“资产类科目代码表”,操作的范围是整个“会计科目代码表”,条件是“科目性质等于1”。对表中的行进行操作后的结果表的结构与原表相同,记录数小于或等于原表。
(2)对表中的列(属性)进行操作:指对一张表中指定的列进行有条件的操作,操作的结果组成一张新表。例如,从“会计科目代码表”中选出“科目代码”、“科目名称”两列,组成新的科目代码对应表,新表只有“科目代码”和“科目名称”两列。显然,列操作后的结果表的结构与原表不同,结果表小于或等于原表。
(3)连接:对两张表或多张表进行有条件的连接操作,生成一张新表。连接操作后的结果表大于等于操作前的表。
从应用的角度看,对二维表中的数据操作功能主要包括更新(增加、修改、删除)数据和检索(查询)数据,即对二维表填入和修改数据,并从表中检索出数据进行加工应用。
4.关系数据模型的数据完整性规则
数据完整性是指数据库中存储的数据是有意义的或正确的。关系数据模型中的数据完整性规则是指对二维表的定义和操作过程中要遵循的某些约束条件。主要包括:
(1)实体完整性:指每张表都必须有主码,而且表中不允许存在无主码值的记录和主码值相同的记录。如表1中的每一个记录都必须有科目代码,并且不能有相同科目代码的记录和无科目代码的记录。
(2)参照完整性:指一张表的某列的取值受另一张表的某列的取值范围约束,描述了多张表之间的关联关系。例如,记账凭证表中的“科目代码”列的取值受到会计科目代码表的“科目代码”取值范围的限定。
(3)用户定义完整性。指针对某一具体应用定义的数据库约束条件,反映某一具体应用所涉及的数据必须满足应用语义的要求。即限制属性的取值类型及范围,防止属性的值与应用语义矛盾。如表1中,“科目性质”的取值只能是1(资产)、2(负债)、3(权益)、4(成本)、5(损益)。
5.从关系数据模型得到的启示
(1)基于关系数据模型的会计账务数据库是以二维表为基本部件构建的,数据库中的每一个数据文件对应一张二维表,数据文件之间的关联也可以用二维表之间的关联来表示,对二维表的定义和数据操作必须满足数据完整性约束条件。构建一个会计账务数据库首先要将会计账务管理的对象,如会计科目、记账凭证、日记账、明细账、总账及它们之间的关系抽象成二维表的形式,弄清了它们的二维表结构也就弄清了它们的数据文件结构,即电子账结构。因此,会计账务数据库结构设计可以转变成会计账务数据的二维表及二维表之间的关联设计,而一张二维表的表头栏目(属性集)反映了表的结构特征,是设计数据文件结构的依据。
(2)依据关系数据模型研发的关系数据库管理系统是开发和管理会计数据库系统的工具软件,也是支持所开发的会计数据库系统运行的平台,任何一个会计账务数据库都必须在某一个关系数据库管理系统的在线管理下运行。由于不同的数据库软件公司提供的关系数据库管理系统软件的各个版本的功能强弱、所适应的计算机系统的运行环境(单机、网络等)、所提供的对表的操作命令等都有所不同,因此,审计人员要审查电子账,首先要了解被审单位的电子账的数据库管理系统软件的名称(例如是SQL SERVER或ORACLE)、版本(单机、网络,第几版)、打开数据库(表)以及对表操作的命令格式和命令等。尽管各种关系数据库管理系统软件版本有差异,但通过以上对关系数据模型的操作可以了解到:表的主要操作类型和功能基本一致。审计人员仅需要掌握最基本的打开、检索、汇总数据库(表)等操作命令就能进行审查会计账务数据库的基本工作,并非深不可测。
/** * 本例解决的问题: * 核心问题:通过SQLiteOpenHelper类创建 数据库对象 * 通过数据库对象对数据库的数据的操作 * 1.sql语句方式操作SQLite数据库 * 2.谷歌提供的api对SQLite数据库的操作 * 3.SQLite对事务的操作 */ import com.ghsy.createsqlitedb.db.MyOpenHelper; import android.content.ContentValues; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.test.AndroidTestCase; public class Test extends AndroidTestCase { MyOpenHelper oh; SQLiteDatabase db; public void test() { // 创建一个MyOpenHelper对象 // 改动此处的版本,会运行upgrade方法--upgrade方法中加入?了一列 MyOpenHelper oh = new MyOpenHelper(getContext(), "people.db", null, 3); // 假设数据库不存在,先创建数据库,再打开数据库,假设已经存在,直接打开 SQLiteDatabase db = oh.getWritableDatabase(); db.close(); } // 測试框架初始化完毕 /** * This method is called before a test is executed */ @Override protected void setUp() throws Exception { // TODO Auto-generated method stub super.setUp(); oh = new MyOpenHelper(getContext(), "people.db", null, 3); db = oh.getWritableDatabase(); } |
// ===========sql语句方式操作SQLite数据库================================
public void insert() { db.execSQL("insert into person(name, phone, money) values(?, ?, ?)", new Object[] { "大明", "18666", 6000 }); db.execSQL("insert into person(name, phone, money) values(?, ?, ?)", new Object[] { "小红", "18666", 6000 }); db.execSQL("insert into person(name, phone, money) values(?, ?, ?)", new Object[] { "大红", "18666", 6000 }); } public void delete() { db.execSQL("delete from person where name = ?", new Object[] { "大明" }); } public void update() { db.execSQL("update person set money = 10000 where name = ?", new Object[] { "小明" }); } public void query() { // 游标,存放查询返回的数据,获取方法跟resultSet高度雷同 Cursor c = db.rawQuery("select * from person", new String[] {}); while (c.moveToNext()) { String name = c.getString(c.getColumnIndex("name")); String phone = c.getString(c.getColumnIndex("phone")); System.out.println(name + ";" + phone); } } |
// ==============谷歌提供的api对SQLite数据库的操作======================
/** * api-insert data to table */ public void insertApi() { ContentValues cv = new ContentValues(); cv.put("name", "微明"); cv.put("phone", 15666); cv.put("money", 630); long id = db.insert("person", null, cv); System.out.println(id); } /** * api-delete data from table * * @return the number of rows affected */ public int deleteApi() { int affectedNum = db.delete("person", "name=?", new String[] { "小红" }); return affectedNum; } /** * api-update */ public void updateApi() { ContentValues contentValues = new ContentValues(); contentValues.put("name", "小红"); contentValues.put("money", "10"); // return the number of rows affected db.update("person", contentValues, "name=?", new String[] { "大红" }); } public void queryApi() { Cursor cursor = db.query("person", new String[] { "phone", "money" }, null, null, null, null, null); while (cursor.moveToNext()) { String phone = cursor.getString(cursor.getColumnIndex("phone")); String money = cursor.getString(cursor.getColumnIndex("money")); System.out.println(phone + "##" + money); } } |
// ===============SQLite对事务的操作=====================
/** * 银行转账操作 */ public void transation(){ db.beginTransaction(); try { //name为微明的用户向小红转账 ContentValues contentValues=new ContentValues(); contentValues.put("money", 1000); db.update("person", contentValues, "name=?", new String[]{"微明"}); ContentValues contentValues2=new ContentValues(); contentValues2.put("money", 1100); db.update("person", contentValues2, "name=?", new String[]{"小红"}); //全部语句运行完毕,若没有异常,则会运行这句设置事务成功的标记 db.setTransactionSuccessful(); } finally { //会检查事务的标识,若没有调用setTransactionSuccessful()方法设置标志,则回滚事务。否则提交事务。 db.endTransaction(); } } } MyOpenHelper.java **SQLiteOpenHelper: * A helper class to manage database creation and version management. * 所以,SQLiteOpenHelper是对库本身的操作。若要对库中数据操作,须要使用库对象的方法。 */ import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; public class MyOpenHelper extends SQLiteOpenHelper { //name:数据库文件的名字 //factory:游标工厂 //version:版本号,必须大于等于1 public MyOpenHelper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); // TODO Auto-generated constructor stub } //数据库创建时调用 @Override public void onCreate(SQLiteDatabase db) { //创建一个person表 db.execSQL("create table person(_id integer primary key autoincrement, name char(10), phone char(20))"); System.out.println("oncreate调用了"); } //数据库升级时调用 @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // TODO Auto-generated method stub System.out.println("onupgrade调用了"); db.execSQL("alter table person add money char(20)"); } } |