发布新日志

  • ORA-12514&GLOBAL_DBNAME & SERVICE_NAME

    2010-12-28 17:39:46

    ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务
    上面的话很容易误解,让人认为数据库服务名(SERVICE NAME)有问题,其实他指的是tnsnames.ora中配置的别名ALIAS所对应的SERVICE_NAME,与在LISTENER中的注册的一堆服务名找不到(也可能一个也没有,比如只配置了动态监听)。

    GLOBAL_DBNAME 是指listener.ora文件中注册静态监听时的服务名。
    另在PARAMETER(spfile)中也可用SERVICE_NAME参数指定注册动态监听时的服务名。

    而tnsnames.ora中的服务名SERVICE_NAME的可选值为静态和动态注册的服务名(SERVICE_NAME),也即listener.ora中的GLOBAL_DBNAME和PARAMETER中的SERVICE_NAME,可以是任意支持的字符,但两者必须与保持一致。而sqlplus中的链接字符串,并不是SERVICE_NAME,而是一个SERVICE_NAME的ALIAS(在tnsname.ora中配置) 。

    静态监听的目的,除了简化配置外,还可以提供在数据库未启动前仍能连接的功能。
    一般(默认)情况下GLOBAL_DBNAME,SERVICE_NAME,ALIAS 及其他的DB_NAME,DB_UNIQUE_NAME,SID_NAME均一样,导致了“傻傻分不清楚”。

    附简单的listener.ora(部分):
        (SID_DESC =
          (GLOBAL_DBNAME = qa)                    ####listener中的service_name
          (ORACLE_HOME = /u01/app/oracle/product/10.2.0)
          (SID_NAME = qa )                               ####listener中的sid_name
    tnsnames.ora(部分):
    QA =                                      ####上面说的别名ALIAS,可以任意填写哦,连接数据库时用的就是它了
      (DESCRIPTION =
        (ADDRESS_LIST =
          (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.101)(PORT = 1521))
        )
        (CONNECT_DATA =
          (SERVICE_NAME = qa)                ####可以任意填写哦,前提是与上面listener中的GLOBAL_DBNAME
        )                                                    #### 或参数文件中的SERVICE_NAME一致
      )


    以上仅作备忘。另:本篇文章仅讨论通过SERVICE_NAME连接数据库的方法
  • LoadRunner负载测试之Windows常见性能计数器,分析服务器性能瓶颈(二)

    2010-12-16 11:37:19

    判断瓶颈
     一、判断应用程序的问题 

    如果系统由于应用程序代码效率低下或者系统结构设计有缺陷而导致大量的上下文切换(context switches/sec显示的上下文切换次数太高)那么就会占用大量的系统资源,如果系统的吞吐量降低并且CPU的使用率很高,并且此现象发生时切换水平在15000以上,那么意味着上下文切换次数过高.


     


    contextswitches/sec

    contextswitches/sec


     

     

     

     

    从图的整体看.context switches/sec变化不大,throughout曲线的斜率较高,并且此时的contextswitches/sec已经超过了15000.程序还是需要进一步优化.


    二、判断CPU瓶颈

    如果processor queue length显示的队列长度保持不变(>=2)个并且处理器的利用率%Processortime超过90%,那么很可能存在处理器瓶颈.如果发现processor queue length显示的队列长度超过2,而处理器的利用率却一直很低,或许更应该去解决处理器阻塞问题,这里处理器一般不是瓶颈.


     


    CPU瓶颈

    CPU瓶颈


     

     

     

     

    %processor time平均值大于95,processor queue length大于2.可以确定CPU瓶颈.此时的CPU已经不能满足程序需要.急需扩展.

    CPU资源成为系统性能的瓶颈的征兆:

    很慢的响应时间(slow response time)

    CPU空闲时间为零(zero percent idle CPU)

    过高的用户占用CPU时间(%User Time)

    过高的系统占用CPU时间(%Priviliaged Time:长期大于90%或者95%)

    长时间的有很长的运行进程队列(Process Queue Lengt:大于处理器个数+1)


    三、判断内存泄露问题

    内存问题主要检查应用程序是否存在内存泄漏,如果发生了内存泄漏,process\private bytes计数器和process\working set 计数器的值往往会升高,同时avaiable bytes的值会降低.内存泄漏应该通过一个长时间的,用来研究分析所有内存都耗尽时,应用程序反应情况的测试来检验.


     


    内存泄露

    内存泄露


     

     

     

    图中可以看到该程序并不存在内存泄露的问题.内存泄露问题经常出现在服务长时间运转的时候,由于部分程序对内存没有释放,而将内存慢慢耗尽.也是提醒大家对系统稳定性测试的关注.

    Windows资源监控中,如果Process\Private Bytes计数器和Process\Working Set计数器的值在长时间内持续升高,同时Memory\Available bytes计数器的值持续降低,则很可能存在内存泄漏。


    四、判断内存不足

    如果队列长度(Avg.Disk Queue Length)增加的同时页面读取速率(Page Reads/sec)并未降低,则内存不足。

    如果Available Mbytes(剩余物理内存数)的值很小(4 MB 或更小),则说明计算机上总的内存可能不足,或某程序没有释放内存。


    五、硬件问题

    请观察 Processor\ Interrupts/sec 计数器的值,该计数器测量来自输入/输出 (I/O) 设备的服务请求的速度。如果此计数器的值明显增加,而系统活动没有相应增加,则表明存在硬件问题。


    六、I/O资源成为系统性能的瓶颈的征兆

    IO Data Bytes/sec(处理从I/O操作读取/写入字节的速度。这个计数器为所有由本处理产生的包括文件、网络和设备I/O的活动计数。)

    IO Data Operations/sec

    IO Other Bytes/sec

    IO Other Operations/sec

    IO Read Bytes/sec(每秒IO读取字节数)

    IO Read Operations/sec

    IO Write Bytes/sec(每秒IO写出字节数)

    IO Write Operations/sec

    过高的磁盘利用率(high disk utilization)

    太长的磁盘等待队列(Physical Disk\ Current Disk Queue Length,正在等待磁盘访问的系统请求数量)

    等待磁盘I/O的时间所占的百分率太高(Average Disk Queue Length)

    太高的物理I/O速率:large physical I/O rate(not sufficient in itself)

    过低的缓存命中率(low buffer cache hit ratio(not sufficient in itself))

    太长的运行进程队列,但CPU却空闲(Process Queue Length)

    在方案运行中,如果出现了大于3个用户的业务操作失败,或出现了服务器shutdown的情况,则说明在当前环境下,系统承受不了当前并发用户的负载压力,那么最大并发用户数就是前一个没有出现这种现象的并发用户数


    七、监视磁盘的使用情况

    监视磁盘活动涉及两个主要方面:


    监视磁盘 I/O 及检测过度换页
    隔离 SQL Server 产生的磁盘活动

      监视磁盘 I/O 及检测过度换页 

    可以对下面两个计数器进行监视以确定磁盘活动:


    PhysicalDisk: % Disk Time 
    PhysicalDisk: Avg. Disk Queue Length 

    在系统监视器中,PhysicalDisk:% Disk Time计数器监视磁盘忙于读/写活动所用时间的百分比。如果PhysicalDisk: % Disk Time计数器的值较高(大于 90%),请检查PhysicalDisk: Current Disk Queue Length计数器了解等待进行磁盘访问的系统请求数量。等待 I/O 请求的数量应该保持在不超过组成物理磁盘的轴数的 1.5 到 2 倍。大多数磁盘只有一个轴,但独立磁盘冗余阵列 (RAID) 设备通常有多个轴。硬件 RAID 设备在系统监视器中显示为一个物理磁盘。通过软件创建的多个 RAID 设备在系统监视器中显示为多个实例。

    可以使用Current Disk Queue Length和% Disk Time计数器的值检测磁盘子系统中的瓶颈。如果Current Disk Queue Length和% Disk Time计数器的值一直很高,则考虑下列事项:


    使用速度更快的磁盘驱动器。
    将某些文件移至其他磁盘或服务器。
    如果正在使用一个 RAID 阵列,则在该阵列中添加磁盘。

    如果使用 RAID 设备,% Disk Time计数器会指示大于 100% 的值。如果出现这种情况,则使用PhysicalDisk: Avg.Disk Queue Length计数器来确定等待进行磁盘访问的平均系统请求数量。

    I/O 依赖的应用程序或系统可能会使磁盘持续处于活动状态。

    监视 Memory: Page Faults/sec计数器可以确保磁盘活动不是由分页导致的。在 Windows 中,换页的原因包括:


    配置进程占用了过多内存。
    文件系统活动。

    如果在同一硬盘上有多个逻辑分区,请使用Logical Disk计数器而非Physical Disk计数器。查看逻辑磁盘计数器有助于确定哪些文件被频繁访问。当发现磁盘有大量读/写活动时,请查看读写专用计数器以确定导致每个逻辑卷负荷增加的磁盘活动类型,例如,Logical Disk: Disk Write Bytes/sec。


    八、判断磁盘瓶颈

    Disk Time和Avg.Disk Queue Length的值很高,而Page Reads/sec页面读取操作速率很低,则可能存在磁盘瓶径。

    Physical Disk\ Disk Reads/sec and Disk Writes/sec

    Physical Disk\ Current Disk Queue Length

    Physical Disk\ % Disk Time

    LogicalDisk\ % Free Space

    测试磁盘性能时,将性能数据记录到另一个磁盘或计算机,以便这些数据不会干扰您正在测试的磁盘。

    可能需要观察的附加计数器包括 Physical Disk\ Avg.Disk sec/Transfer 、Avg.DiskBytes/Transfer,和Disk Bytes/sec。

    Avg.Disk sec/Transfer 计数器反映磁盘完成请求所用的时间。较高的值表明磁盘控制器由于失败而不断重试该磁盘。这些故障会增加平均磁盘传送时间。对于大多数磁盘,较高的磁盘平均传送时间是大于 0.3 秒。

    也可以查看 Avg.Disk Bytes/Transfer 的值。值大于 20 KB 表示该磁盘驱动器通常运行良好;如果应用程序正在访问磁盘,则会产生较低的值。例如,随机访问磁盘的应用程序会增加平均 Disk sec/Transfer 时间,因为随机传送需要增加搜索时间。

    Disk Bytes/sec 提供磁盘系统的吞吐率。

    决定工作负载的平衡要平衡网络服务器上的负载,需要了解服务器磁盘驱动器的繁忙程度。使用 Physical Disk\ %Disk Time 计数器,该计数器显示驱动器活动时间的百分比。如果 % Disk Time 较高(超过90%),请检查 Physical Disk\ Current Disk Queue Length 计数器以查看正在等待磁盘访问的系统请求数量。等待 I/O 请求的数量应当保持在不大于组成物理磁盘的主轴数的 1.5 到2倍。

    尽管廉价磁盘冗余阵列 (RAID) 设备通常有多个主轴,大多数磁盘有一个主轴。硬件 RAID设备在“系统监视器”中显示为一个物理磁盘;通过软件创建的 RAID 设备显示为多个驱动器(实例)。可以监视每个物理驱动器(而不是 RAID)的 Physical Disk 计数器,也可以使用 _Total 实例来监视所有计算机驱动器的数据。

    使用 Current Disk Queue Length 和 % Disk Time 计数器来检测磁盘子系统的瓶颈。如果Current Disk Queue Length 和 % Disk Time 的值始终较高,可以考虑升级磁盘驱动器或将某些文件移动到其他磁盘或服务器。

  • LoadRunner负载测试之Windows常见性能计数器,分析服务器性能瓶颈(一)

    2010-12-16 11:35:30

    监测对象
    一、System(系统) 
    %Total Processor Time

    系统中所有处理器都处于繁忙状态的时间百分比,对于多处理器系统来说,该值可以反映所有处理器的平均繁忙状态,该值为100%,如果有一半的处理器为繁忙状态,该值为50%服务器。器消耗的处理器时间数量.如果服务器专用于sql server可接受的最大上限是80% -85 %.也就是常见的CPU 使用率.


     File Data Operations/sec

    计算机对文件系统进行读取和写入操作的频率,但是不包括文件控制操作


    Process Queue Length

    线程在等待分配CPU资源所排队列的长度,此长度不包括正在占有CPU资源的线程。如果该队列的长度大于处理器个数+1,就表示处理器有可能处于阻塞状态(参考值:<=处理器个数+1)


    二、Processor(处理器) 
    %Processor Time

    CPU利用率,该计数器最为常用,可以查看处理器是否处于饱和状态,如果该值持续超过 95%,就表示当前系统的瓶颈为CPU,可以考虑增加一个处理器或更换一个性能更好的处理器。(参考值:<80%)


     %Priviliaged Time

    CPU在特权模式下处理线程所花的时间百分比。一般的系统服务,进城管理,内存管理等一些由操作系统自行启动的进程属于这类


    %User Time

    与%Privileged Time计数器正好相反,指的是在用户状态模式下(即非特权模式)的操作所花的时间百分比。如果该值较大,可以考虑是否通过算法优化等方法降低这个值。如果该服务器是数据库服务器,导致此值较大的原因很可能是数据库的排序或是函数操作消耗了过多的CPU时间,此时可以考虑对数据库系统进行优化。表示耗费CPU的数据库操作,如排序,执行aggregate functions等。如果该值很高,可考虑增加索引,尽量使用简单的表联接,水平分割大表格等方法来降低该值。


    %DPC Time

    处理器在网络处理上消耗的时间,该值越低越好。越低越好。在多处理器系统中,如果这个值大于50%并且Processor:% Processor Time非常高,加入一个网卡可能会提高性能,提供的网络已经不饱和。


    三、Memory(内存)
    Page Faults/sec

    当处理器在内存中读取某一页出现错误时,就会产生缺页中断,也就是 page Fault。如果这个页位于内存的其他位置,这种错误称为软错误,用Transition Fault/sec来衡量;如果这个页位于硬盘上,必须从硬盘重新读取,这个错误成为硬错误。硬错误会使系统的运行效率很快将下来。Page Faults/sec这个计数器就表示每秒钟处理的错误页数,包括硬错误和软错误。


    Page Input/sec

    表示为了解决硬错误而写入硬盘的页数(参考值:>=Page Reads/sec)


    Page Reads/sec

    表示为了解决硬错误而从硬盘上读取的页数。


    Page/sec

    表示为了解决硬错误而从硬盘上读取或写入硬盘的页数(参考值:00~20)


    Pages per second:

    每秒钟检索的页数。该数字应少于每秒一页Working set:理线程最近使用的内存页,反映了每一个进程使用的内存页的数量。如果服务器有足够的空闲内存,页就会被留在工作集中,当自由内存少于一个特定的阈值时,页就会被清除出工作集。


    Available Mbytes

    剩余的可用物理内存,单位是兆字节(参考值:>=10%)用物理内存数. 如果Available Mbytes的值很小(4 MB 或更小),则说明计算机上总的内存可能不足,或某程序没有释放内存。


    Cathe Bytes

    文件系统的缓存(默认为50%的可用物理内存)


    四、Process(进程)
    private Bytes

    进程无法与其他进程共享的字节数量。该计数器的值较大时,有可能是内存泄露的信号


    Work set

    最近处理线程使用的内存页


    五、PhysicalDisk(磁盘)
    %Disk Time

    表示磁盘驱动器为读取或写入请求提供服务所用的时间百分比,如果只有%Disk Time比较大,硬盘有可能是瓶颈。指所选磁盘驱动器忙于为读或写入请求提供服务所用的时间的百分比。如果三个计数器都比较大,那么硬盘不是瓶颈。如果只有%Disk Time比较大,另外两个都比较适中,硬盘可能会是瓶颈。在记录该计数器之前,请在Windows 2000的命令行窗口中运行diskperf -yD。若数值持续超过80%,则可能是内存泄漏。应当总小于90%


    Average Disk Queue Length

    表示磁盘读取和写入请求提供服务所用的时间百分比,可以通过增加磁盘构造磁盘阵列来提高性能(<=磁盘数的2倍)读取和写入请求(为所选磁盘在实例间隔中列队的)的平均数。该值应不超过磁盘数的1.5~2 倍。要提高性能,可增加磁盘。注意:一个Raid Disk实际有多个磁盘。不应当超过物理磁盘数量的2倍,正常值<0.5


    Average Disk Read Queue Length

    表示磁盘读取请求的平均数


    Average Disk write Queue Length

    表示磁盘写入请求的平均数


    Average Disk&nbsp;sec/Read

    磁盘中读取数据的平均时间,单位是秒


    Average Disk&nbsp;sec/Transer

    磁盘中写入数据的平均时间,单位是秒,一般来说,定义该值小于15ms最为优异,介于15-30ms之间为良好,30-60ms之间为可以接受,超过60ms则需要考虑更换硬盘或硬盘的RAID方式了


    %Disk reads/sec(physicaldisk_total):

    每秒读硬盘字节数. 该指标应总小于磁盘I/O子系统的容量


    %Disk write/sec(physicaldisk_total):

    每秒写硬盘字节数. 该指标应当总小于硬盘I/O子系统的容量


    Disk&nbsp;Bytes/sec&nbsp;

    指在进行写入或读取操作时从磁盘上传送或传出的字节速率。此值取决于硬盘的速度

    Disk Transfers/sec&nbsp;

    指在此盘上读取/写入操作速率。正常值<(Disk&nbsp;Bytes/sec)/3,此值过大表示系统要求的IO速度已接近硬盘的最大速度,要更换更快的硬盘

    六、Network Interface(网络)
    Byte Total/sec

    表示网络中接受和发送字节的速度,可以用该计数器来判断网络是否存在瓶颈(参考值:该计数器和网络带宽相除,<50%)

  • Oracle时间戳

    2010-12-16 09:52:20

    Oracle Databse 9i数据库引入了一种新特性,可以存储时间戳。时间戳可以存储世纪、4位年、月、日、时(以24小时格式)、分、秒。与DATE类型相比,时间戳具有以下优点:

        ● 时间戳可以存储秒的小数位。

        ● 时间戳可以存储时区。

        下面介绍时间戳类型。

     使用时间戳类型

        时间戳有3种类型,如表所示。

        表  时间戳类型

    类    型 说    明
    TIMESTAMP[(seconds_precision)] 存 储世纪、4位的年、月、日、时(以24小时格式)、分和秒。seconds_precision为可选参数,用于指定精度,该参数为一个整数,范围从 0~9,默认值为9;意思是表示秒的数字的小数点右边可以存储9位数字。如果试图在秒的小数中保存超过TIMESTAMP存储精度的数字,那么该小数将被 取整
    TIMESTAMP[(seconds_precision)]WITH TIME ZONE 扩展TIMESTAMP,用于存储时区
    TIMESTAMP[(seconds_precision)]WITH LOCAL TIME ZONE 扩展TIMESTAMP,将给定的时间值转换成数据库的本地时区。转换过程称为时间值的规格化(normalizing)

     

    我的例子:

    create table test_timestamp (
    id integer primary key,name varchar2(20),time timestamp(9)
    );
    insert into test_timestamp values(1,'tester1',systimestamp);
    select * from test_timestamp;

       接下来的几节将介绍如何使用这些时间戳。

    1. 使用TIMESTAMP类型

        与其他类型类似,TIMESTAMP类型也可以用来在表中定义列。下面这个语句用于创建一个表purchases_with_timestamp,该表用来存储顾客的购买记录。该表包含了一个TIMESTAMP类型的列made_on,该列用来记录顾客在何时购买了产品。注意TIMESTAMP的精度设置为4(这意味着在秒的小数点右边可以存储4位小数):


    1.  CREATE TABLE purchases_with_timestamp (   
    2. product_id INTEGER REFERENCES products(product_id),   
    3. customer_id INTEGER REFERENCES customers(customer_id),   
    4. made_on TIMESTAMP(4)   
    5. );  
     

     

    注意:

    purchases_with_timestamp表由store_schema.sql脚本创建和填充。本章的其他表也是由该脚本创建,因此不需要输入CREATE TABLE语句或本章所示的任何INSERT语句。

    要向数据库提供一个TIMESTAMP字面值,可以在一个时间值前面指定TIMESTAMP关键字,格式如下:


    1. TIMESTAMP 'YYYY-MM-DD HH24:MI:SS.SSSSSSSSS'  

         注意在小数点后面有9个S字符,这意味着可以在字符串中为秒的小数部分指定9个数字。TIMESTAMP列中可以实际存储多少位数字取决于在定义该列时为秒的小数部分指定了多少位数字。例如,purchases_with_timestamp表的made_on列可以存储最多4位小数的秒数。如果试图向该表中添加一行秒的精度超过4位小数的记录,小数部分就会被取整。例如:

     


    1. 2005-05-13 07:15:31.123456789  

         将被取整为:


    1. 2005-05-13 07:15:31.1235  
     

     

        下面这个INSERT语句向purchases_with_timestamp表中添加一行记录,注意此处使用了TIMESTAMP关键字指定一个时间值:


    1. INSERT INTO purchases_with_timestamp (   
    2. product_id, customer_id, made_on   
    3. VALUES (   
    4. 1, 1, TIMESTAMP '2005-05-13 07:15:31.1234'  
    5. );  
     

        下面这个查询对purchases_with_timestamp表进行检索:


    1.  SELECT *   
    2. FROM purchases_with_timestamp;   
    3.   
    4. PRODUCT_ID CUSTOMER_ID  MADE_ON   
    5. ---------- -----------  --------------------------   
    6. 1              1 13-MAY-05 07.15.31.1234 AM  

     

    2. 使用TIMESTAMP WITH TIME ZONE类型

    TIMESTAMP WITH TIME ZONE类型对TIMESTAMP进行了扩展,用于存储时区。下面这个语句创建一个表purchases_timestamp_with_tz,该表用于存储顾客的购买记录。该表包含了一个TIMESTAMP WITH TIME ZONE类型的列made_on,该列用来记录该顾客在何时购买了产品:


    1.  CREATE TABLE purchases_timestamp_with_tz (   
    2. product_id INTEGER REFERENCES products(product_id),   
    3. customer_id INTEGER REFERENCES customers(customer_id),   
    4. made_on TIMESTAMP(4) WITH TIME ZONE   
    5. );  
     

    要向数据库提供一个带有时区信息的时间戳,可以在TIMESTAMP子句中加上时区信息。例如,下面这个TIMESTAMP子句包含了时差-07:00:

     


    1.  TIMESTAMP '2005-05-13 07:15:31.1234 -07:00'  
    2. 此处也可以指定一个时区名,下面这个例子就指定PST作为时区使用:   
    3. TIMESTAMP '2005-05-13 07:15:31.1234 PST'  
    4. 下面这个INSERT语句向purchases_timestamp_with_tz表中添加两行记录:   
    5. INSERT INTO purchases_timestamp_with_tz (   
    6. product_id, customer_id, made_on   
    7. VALUES (   
    8. 1, 1, TIMESTAMP '2005-05-13 07:15:31.1234 -07:00'  
    9. );   
    10.   
    11. INSERT INTO purchases_timestamp_with_tz (   
    12. product_id, customer_id, made_on   
    13. VALUES (   
    14. 1, 2, TIMESTAMP '2005-05-13 07:15:31.1234 PST'  
    15. );  
     

    下面这个查询对purchases_timestamp_with_tz表进行检索:


    1.  SELECT *   
    2. FROM purchases_timestamp_with_tz;   
    3.   
    4. PRODUCT_ID  CUSTOMER_ID MADE_ON   
    5. ----------  ----------- ---------------------------------   
    6. 1             1  13-MAY-05 07.15.31.1234 AM -07:00   
    7. 1             2  13-MAY-05 07.15.31.1234 AM PST  

     

    3. 使用TIMESTAMP WITH LOCAL TIME ZONE类型

    TIMESTAMP WITH LOCAL TIME ZONE类型对TIMESTAMP进行了扩展,用于存储一个转换为数据库设置的本地时区的时间戳。在为一个TIMESTAMP WITH LOCAL TIME ZONE类型的列存储一个时间戳值时,这个时间戳就被转换(或被规格化)为数据库的时区设置。当检索这个时间戳时,它就被规格化为当前会话中的时区设置。

    提示:

    如果企业已经实现了一个全球系统,可以通过世界各地访问,那么就应该使用TIMESTAMP WITH LOCAL TIME ZONE类型来存储时间戳。这是因为数据库会将时间戳存储为数据库所在时区中的本地时间,但是在对它们进行检索时,却可以看到规格化为本地时区的时间戳。

    假设数据库时区是PST(比UTC晚8个小时),想向数据库中存储下面的时间戳:

     

    2005-05-13 07:15:30 EST

     

    由于EST比UTC晚5个小时,因此EST与PST之间差3个小时(8 - 5 = 3)。要将前面的时间戳规格化为PST,就必须从时间戳中减去3个小时就得到下面的规格化的时间戳:

     

    2005-05-13 04:15:30
    

     

    这是数据库的TIMESTAMP WITH LOCAL TIME ZONE列中所存储的时间戳。

    下面这个语句创建一个表purchases_ with_local_tz,该表用于存储顾客的购买记录。该表包含了一个TIMESTAMP WITH LOCAL TIME ZONE类型的列made_on,该列用来记录顾客在何时购买了产品:

     


    1.  CREATE TABLE purchases_with_local_tz (   
    2. product_id INTEGER REFERENCES products(product_id),   
    3. customer_id INTEGER REFERENCES customers(customer_id),   
    4. made_on TIMESTAMP(4) WITH LOCAL TIME ZONE   
    5. );  

     下面这个INSERT语句向purchases_ with_local_tz表中添加一行记录,并将该行的made_on列值设置为2005-05-13 07:15:30 EST:

     


    1.  INSERT INTO purchases_with_local_tz (   
    2. product_id, customer_id, made_on   
    3. VALUES (   
    4. 1, 1, TIMESTAMP '2005-05-13 07:15:30 EST'  
    5. );  

     

    虽然made_on列的时间戳设置为2005-05-13 07:15:30 EST,但数据库中实际存储的时间戳是2005-05-13 04:15:30(时间戳规格化为PST)。

    下面这个查询对purchases_ with_local_tz表进行检索:


    1.  SELECT *   
    2. FROM purchases_with_local_tz;   
    3.   
    4. PRODUCT_ID  CUSTOMER_ID  MADE_ON   
    5. ----------  -----------  --------------------------   
    6. 1             1   13-MAY-05 04.15.30.0000 AM  
     

    因为我的数据库时区和会话时区都是PST,所以此查询返回的时间戳都是针对PST的。

    警告:

    前面这个查询返回的时间戳规格化为PST。如果数据库时区或会话时区不是PST,则运行查询时返回的时间戳会有所不同(它将规格化为您的时区)。

    如果将当前会话的本地时区设置为EST,并重新执行上面这个查询,就会看到时间戳被规格化为EST:

     


    1.  ALTER SESSION SET TIME_ZONE = 'EST';   
    2.   
    3. Session altered.   
    4.   
    5. SELECT *   
    6. FROM purchases_with_local_tz;   
    7.   
    8. PRODUCT_ID CUSTOMER_ID  MADE_ON   
    9. ---------- -----------  --------------------------   
    10. 1             1   13-MAY-05 07.15.30.0000 AM  

     

    可以看到,此查询返回的时间戳是13-MAY-05 07.15.30.0000 AM,这是规格化为会话时区EST的时间戳。因为EST比PST早3小时,所以必须将13-MAY-05 04:15:30(数据库中存储的时间戳)增加3小时,得到13-MAY-05 07.15.30 AM(查询返回的时间戳)。

    下面这条语句将会话时区设置回PST:

     


    1. ALTER SESSION SET TIME_ZONE = 'PST';   
    2.   
    3. ession altered.  
  • Mercury Business Process Testing (ZT)

    2009-11-24 11:55:20

    Mercury 在 Quality Center 8.0 时就推出 Business Process Testing,到现在已经进步到 9.0 的版本了。为什么 Mercury 发展出 Business Process Testing 呢?Business Process Testing 的好处在哪?要如何使用Business Process Testing?我将在以下的文章为大家做个介绍。

    传动自动化测试的限制

      软体的自动化测试在过去一段时间中有长足的进步。每个世代的產品都成功解决了某些重要的挑战,但是同时也引进了不同的问题等待解决。

      第一代的自动化测试大概在15年前开始,透过硬体的方式录製键盘的输入并播放,但缺少检查点(checkpoint)的功能,而且测试脚本很难维护。

      第二代的自动化测试则大约在10年前开始的,这时已经由硬体转变成透过软体录製/播放(capture/playback)的方式產生测试脚本(scrīpt),并且也增加了检查点的功能,可以对软体做验证,测试的范围也比硬体方式的自动化方式大了许多。比较大的问题是测试脚本也是一种程式语言,所以测试人员也需要懂程式语言,换句话说就是要会写程式。而且当软体有变动时,测试脚本也需要同步更新,这对测试人员来说是一大挑战,测试人员常常就是整个测试脚本再重新录製一遍。

    以下為Mercury WinRunner测试脚本的范例

      在2001年开始了第三代的自动化测试称為「测试框架(test framework)」,主要是把测试脚本给抽象化(abstraction)(註:如Keyword-Driven Test),让非技术人员(如系统分析师、使用者等)即使不懂测试脚本,不会写程式的情况下,也可以使用自动化测试工具建立自动化测试个案。

      举个 Mercury QuickTest Professional Keyword-Driven Test的测试脚本為例子,测试人员不管是录製、编辑或是看到的测试脚本都是以「click the “OK” button」这样的关键字所呈现的。

    「测试框架」确实是增加了测试团队的生產力,但是还是有些缺点:

    *         以Keyword方式建立的测试脚本还是在测试步骤的层次,当设计一个复杂的商业流程测试个案可能还是需要大量的Keyword。对测试人员而言还是需要耗费大量的时间。

    *          「测试框架」对於测试人员而言,只是测试脚本长得不再像是程式原始码,而像是在Excel中填入Keyword罢了,其实还是在写测试脚本。

    *           支援「测试框架」的自动化测试工具通常与之前的测试工具做法不同,例如不提供录製的功能,而限制了其弹性。再者,测试人员在使用这类工具时也常常不知其所以然,在不瞭解内部的运作下,很难对Keyword做客製化。

    *          「测试框架」即使已经被抽象化了,但是其层次还是停留在「步骤」的层次,尚未提升到「业务流程」的层次,迫使测试人员在建立测试脚本时,还是需要以「程式人员」的思考方式建立测试脚本,而不是以「业务人员」的角度来建立测试脚本。

    *         「测试框架」的测试脚本没有与测试文件建立关联性,测试人员还是需要花费大量的工时在建立与维护测试文件的工作上。

      从上面的问题,可以看出「测试框架」这样的方式,对於具备技术背景的测试人员也许还 OK,但是对没有技术背景的测试人员如(业务人员或是使用者),还是有其使用上的困难。

      Mercury Business Process Testing – 是一种转变而非一种新技术

      Mercury很快地意识到这些挑战,并非只有单单改进第三代自动化测试工具就能解决,需要的是一个全新的方式。所以从测试脚本的设计、自动化、维护以及文件化做一个全面且根本的进化,进而发展出第四代的自动化测试工具「Mercury Business Process Testing」 。

      相较於Keyword-Driven Testing,Business Process Testing的抽象化层次更高,到达了「业务流程」的层次。

      以下的例子可以看出一个有登入动作的测试个案,使用Keyword-Driven Testing的方式,至少需要4个步骤:开啟应用程式登入视窗、输入帐号、输入密码、按下OK按钮来完成登入的动作。但是以Business Process Testing的方式,登入的动作就成為一个可以接受以帐号、密码為参数而且可以重复使用的业务流程元件。

    Business Process Testing的优点

    使用Business Process Testing的自动化测试主要有以下的优点:

    *         透过非技术性、元件化、以业务流程层次的方式设计测试个案,让业务人员以及一般使用者也可以参与自动化测试的工作。

    *          业务元件可以被不同的测试个案所使用,加快建立自动化测试脚本的时间,并降低维护的成本。

    *          建立或维护测试脚本时也会同时更新测试个案文件,大大缩短维护测试文件的时间。

    如何Mercury Business Process Testing

      Business Process Testing需要Mercury Quality Center与QuickTest Professional配合才能运作。同时测试团队中也需要二种角色,一是熟悉QuickTest Professional测试工具的人员(Automation Engineer),负责建立并维护Application Area、物件库(object repository)、library files、recovery scenarios,另外也需要负责对Business Component进行除错的工作;另一是非常熟悉业务流程的人员(Subject Matter Expert),透过Quality Center介面,设计Business Component以及Business Process Test并运用Application Area将其自动化。

      使用Business Process Test的流程如下:

    建立Business Component

      首先建立一个名為Login的Business Component,并且填入相关资讯,如Summary、Pre-Condition、Post-Condition,让想要使用此Business Component的人员知道其目的、用途以及使用条件与限制。

    输入测试步骤

    点选上方的Design Steps,开始输入测试步骤,含Step Name、Descrīption、Expected Result。

    点选New Step将其餘的测试步骤也一併输入,最后可以看到此Busniess Component的执行步骤如下。

    建立Business Process Test

    点选Mercury Quality Center的Test Plan,建立一个名為「预定机位」的Business Process Test。

    输入此测试个案的描述。

    将Business Component加入Business Process Test中

      在Test scrīpt点选Select Component,将刚刚建立的Busniess Component依序以滑鼠拖拉到中间的区块。此Business Process Test由Login、Create Order、Update Order、Logout 4个Business Component所组成。

    将Business Component自动化

      再回到Business Components将其转成自动化测试脚本,在Design Steps点选QuickTest Keyword-Driven,将此Business Components转成QuickTest Keyword-Driven类型的测试脚本。Business Components支援三种类型的脚本:QuickTest Keyword-Driven、QuickTest scrīpted、WinRunner。

      转成QuickTest Keyword-Driven脚本后,点选Automation就可以看到其Keyword-Driven的脚本,目前都还是ManualStep。

      选择Application Area。这个Application Area内含测试物件(Test Object)、Keyword steps、函式库等等。

    将Keyword-Driven步骤加入Business Component中

      直接在Keyword View上透过选取Item、Operation、输入Value的方式建立Keyword-Driven脚本。

    第一个步骤為执行Flight Reservation程式,在Item栏位就不是选取Test Object,而是选取Operation,然后在Operation栏位选择OpenApp表示此步骤是要执行一个程式,同时在Value栏位输入这个程式的路径,这样第一个步骤就完成了。

    Item选取Login Diaglog的Test Object,然后在Operation选取Activate,表示此步骤為开啟登入视窗,Value栏位则不需要输入任何值。

      选取AgentName的EditBox,Operation则是Set,表示要在Agent Name这个EditBox输入资料,至於要输入什麼资料就直接输入在Value栏位中。

    在Value栏位输入mercury。

    以相同的方式加入其他的步骤,完成后整个Business Component的执行脚本如下。


    1
  • VBS字符串函数

    2009-11-06 12:01:04

    1. Split(expression, delimiter, count, compare)
    返回基于 0 的一维数组,其中包含指定数目的子字符串。
    expression:必选。字符串表达式,包含子字符串和分隔符。如果 expression 为零长度字符串,Split 返回空数组,即不包含元素和数据的数组。
    delimiter:可选。用于标识子字符串界限的字符。如果省略,使用空格 (" ") 作为分隔符。如果 delimiter 为零长度字符串,则返回包含整个 expression 字符串的单元素数组。
    count:可选。被返回的子字符串数目,-1 指示返回所有子字符串。
    compare:可选。compare 参数可以有以下值:0 执行二进制比较;1 执行文本比较;2 执行基于数据库(在此数据库中执行比较)中包含的信息的比较。

    2. Replace(expression, find, replacewith, compare, count, start)
    返回字符串,其中指定数目的某子字符串被替换为另一个子字符串。
    expression:必选。字符串表达式,包含要替换的子字符串。
    find:必选。被搜索的子字符串。
    replacewith:必选。用于替换的子字符串。
    start:可选。expression 中开始搜索子字符串的位置。如果省略,默认值为 1。
    count:可选。执行子字符串替换的数目。如果省略,默认值为 -1,表示进行所有可能的替换。
    compare:可选。参数值同上。

    3. Mid(string, start, length)
    从字符串中返回指定数目的字符。
    string:字符串表达式,从中返回字符。如果 string 包含 Null,则返回 Null。
    start:string 中被提取的字符部分的开始位置。如果 start 超过了 string 中字符的数目,Mid 将返回零长度字符串 ("")。
    length:要返回的字符数。如果省略或 length 超过文本的字符数(包括 start 处的字符),将返回字符串中从 start 到字符串结束的所有字符。

    4. LTrim(string), RTrim(string), Trim(string)
    返回不带前导空格 (LTrim)、后续空格 (RTrim) 或前导与后续空格 (Trim) 的字符串副本。
    string:参数是任意有效的字符串表达式。如果 string 参数中包含 Null,则返回 Null。

    5. InStr(start, string1, string2, compare)
    (InstrRev(start, string1, string2, compare))
    返回某字符串在另一字符串中从头部出现的位置
    (返回某字符串在另一字符串中从结尾出现的位置)。
    start:可选。数值表达式,用于设置每次搜索的开始位置。如果省略,将从第一个字符的位置开始搜索。如果 start 包含 Null,则会出现错误。如果已指定 compare,则必须要有 start 参数。
    string1:必选。接受搜索的字符串表达式。
    string2:必选。要搜索的字符串表达式。
    compare:可选。参数值同上。

    6. String(number, character)
    返回具有指定长度的、重复字符组成的字符串。
    number:返回字符串的长度。如果 number 参数包含 Null,则返回 Null。
    character:指定字符或字符串表达式的字符代码,其中字符串表达式的第一个字符用于组成返回的字符串。如果 character 参数包含 Null,则返回 Null。

    7. Space(number)
    返回由指定数目的空格组成的字符串。
    number:参数为字符串中用户所需的空格数。

    8. Left(string, length), Right(string, length)
    返回指定数目的从字符串的左边(右边)算起的字符。
    string:字符串表达式,其最左边(右边)的字符被返回。如果 string 参数中包含 Null,则返回 Null。
    length:数值表达式,指明要返回的字符数目。如果是 0,返回零长度字符串 ("");如果大于或等于 string 参数中的字符总数,则返回整个字符串。

    9. Len(string | varname)
    返回字符串内字符的数目,或是存储一变量所需的字节数。
    string:任意有效的字符串表达式。如果 string 参数包含 Null,则返回 Null。
    varname:任意有效的变量名。如果 varname 参数包含 Null,则返回 Null。

    10. Asc(string)
    返回与字符串的第一个字母对应的 ANSI 字符代码。
    string:参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。

    11. Chr(charcode)
    返回与指定的 ANSI 字符代码相对应的字符。
    charcode:参数是可以标识字符的数字。从 0 到 31 的数字表示标准的不可打印的 ASCII 代码。例如,Chr(10) 返回换行符。

    12. LCase(string), UCase(string)
    返回字符串的小写(大写)形式,所有大写(小写)字母和非字母字符保持不变。
    string:参数是任意有效的字符串表达式。如果 string 参数中包含 Null,则返回 Null。

    13. Join(list, delimiter)
    返回一个字符串,此字符串由包含在数组中的许多子字符串联接创建。
    list:必选。包含要联接的子字符串一维数组。
    delimiter:可选。在返回字符串中用于分隔子字符串的字符。如果省略,将使用空字符 ("")。 如果 delimiter 是零长度字符串,则在同一列表中列出全部项,没有分界符。

    14. StrComp(string1, string2, compare)
    返回指示字符串比较结果的值。StrComp 函数有以下返回值:-1, 0, 1, Null。
    string1, string2:必选。任意有效的字符串表达式。
    compare:可选。参数值同上。

    15. StrReverse(string)
    返回字符串,此字符串与指定字符串顺序相反。
    string:参数是要进行字符反向的字符串。如果 string 是零长度字符串 (""),则返回零长度字符串。如果 string1 为 Null,则会出现错误。

    二、VBScript其他函数介绍

    1. Option Explicit
    用于 Script. 级强制要求显式声明该 Script. 中的所有变量。如果使用 Option Explicit,该语句必须出现在 Script. 的任何过程之前。使用 Option Explicit 语句时,必须使用 Dim、Private、Public 或 ReDim 语句显式声明所有变量。如果试图使用未经声明的变量名,则会出现错误。

    2. UBound(arrayname, dimension)(LBound(arrayname, dimension))
    返回指定数组维数的最大可用下标。(返回指定数组维的最小可用下标)。
    arrayname:数组变量名,遵循标准变量命名约定。
    dimension:指明要返回哪一维下界的整数。使用 1 表示第一维,2 表示第二维,以此类推。如果省略 dimension 参数,默认值为 1。
    UBound 函数与 LBound 函数一起使用,用于确定数组的大小。使用 LBound 函数可以确定数组某一维的下界。所有维的默认下界均为 0。

    3. IsArray, IsDate, IsEmpty, IsNull, IsNumeric, IsObject
    判断是否数组,日期,Empty,Null,数值或对象。

    4. CBool, CByte, CCur, CDate, CDbl, CInt, CLng, CSng, CStr
    变量类型转换函数,分别转化为Boolean, Byte, Currency, Date, Double, Integer, Long, Single, String类型。

    5. On Error Resume Next
    启动错误处理程序。若不使用 On Error Resume Next 语句,发生的任何运行时错误都将是致命的,即显示错误信息并终止运行。On Error Resume Next 会使程序从紧随产生错误的语句之后的语句继续执行,或是从紧随最近一次调用过程(该过程含有 On Error Resume Next 语句)的语句继续运行。这个语句可以不顾运行时错误,继续执行程序,之后您可以在过程内部建立错误处理例程。在调用另一个过程时,On Error Resume Next 语句变为非活动的。所以,如果希望在例程中进行内部错误处理,则应在每一个调用的例程中执行 On Error Resume Next 语句。

    6. Err.{property | method}
    Err.Number为出错的个数。Err.Raise可以在代码中生成运行时的错误。Err.Clear可用于重新设置Err。

    7. RGB(red, green, blue)
    返回代表 RGB 颜色值的整数。
    red:必选。0 到 255 间的整数,代表颜色中的红色成分。
    green:必选。0 到 255 间的整数,代表颜色中的绿色成分。
    blue:必选。0 到 255 间的整数,代表颜色中的蓝色成分。

    8. 函数
    [Public | Private] Function name [(arglist)]
    [statements]
    [name = expression]
    [Exit Function]
    [statements]
    [name = expression]
    End Function

    声明 Function 过程的名称、参数以及构成其主体的代码。

    Public:表示 Function 过程可被所有 Script. 中的所有其他过程访问。
    Private:表示 Function 过程只可被声明它的 Script. 中的其他过程访问。
    name:Function 的名称,遵循标准的变量命名约定。
    arglis:代表调用时要传递给 Function 过程的参数的变量列表。用逗号隔开多个变量。
    statements:在 Function 过程的主体中执行的任意语句组。
    expression:Function 的返回值。

    9. 过程
    [Public | Private] Sub name [(arglist)]
    [statements]
    [Exit Sub]
    [statements]
    End Sub

    声明 Sub 过程的名称、参数以及构成其主体的代码。

    10. Set bjectvar = {objectexpression | Nothing}
    将对象引用赋给变量或属性。
    objectvar:变量或属性的名称,遵循标准变量命名约定。
    objectexpression:由对象名称、另一个已声明为相同对象类型的变量或返回相同对象类型的对象的函数或方法组成的表达式。
    Nothing:停止 objectvar 与任何指定对象的关联。当没有其他变量引用 objectvar 原来所引用的对象时,如将其赋为 Nothing 会释放与该对象所关联的所有系统和内存资源。

    11. Rem comment 或 ' comment
    用于包含程序中的解释性注释。comment 参数是需要包含的注释文本。在 Rem 关键字和 comment 之间应有一个空格。

    12. DateSerial(year, month, day)
    对于指定的年、月、日,返回 Date 子类型的 Variant。

    13. TimeSerial(hour, minute, second)
    返回一个 Date 子类型的 Variant,含有指定时、分、秒的时间。

    14. Date, Time, Now
    系统的日期,时间。

    15. Year, Month, Day, Hour, Minute, Second
    把日期或时间拆分开为年、月、日、小时、分钟、秒。

    16. DateDiff(interval, date1, date2)
    interval:必选。字符串表达式,表示用于计算 date1 和 date2 之间的时间间隔。
    date1, date2:必选。日期表达式。用于计算的两个日期。
    interval 参数可以有以下值:
    yyyy 年
    q 季度
    m 月
    y 一年的日数
    d 日
    w 一周的日数
    ww 周
    h 小时
    m 分钟
    s 秒

    17. Rnd(number)
    number 参数可以是任意有效的数值表达式。Rnd 函数返回一个小于 1 但大于或等于 0 的随机数。要产生指定范围的随机整数,请使用以下公式:
    Int((upperbound - lowerbound + 1) * Rnd + lowerbound)
    这里, upperbound 是此范围的上界,而 lowerbound 是此范围内的下界。

    18. TypeName(varname)
    返回一个字符串,提供有关变量的 Variant 子类型信息。
    TypeName 函数返回值如下:
    Byte 字节值
    Integer 整型值
    Long 长整型值
    Single 单精度浮点值
    Double 双精度浮点值
    Currency 货币值
    Decimal 十进制值
    Date 日期或时间值
    String 字符串值
    Boolean Boolean 值;True 或 False
    Empty 未初始化
    Null 无有效数据
    实际对象类型名
    Object 一般对象
    Unknown 未知对象类型
    Nothing 还未引用对象实例的对象变量
    Error 错误
  • QTP连接数据库-recordset相关整理

    2009-11-05 12:28:22

    RecordSet对象(代表来自基本表或命令执行结果的记录的全集。)

    为了更精确地跟踪数据,要用RecordSet组件创建包含数据的游标,游标就是储存在内存中的数据:

      rs = Server.CreateObject("ADODB.RecordSet")

      rs.Open(sqlStr,conn,1,A)

      注:A=1表示读取数据;A=3表示新增、修改或删除数据。

      在RecordSet组件中,常用的属性和方法有:

      rs.Fields.Count:RecordSet对象字段数。

      rs(i).Name:第i个字段的名称,i为0至rs.Fields.Count-1

      rs(i):第i个字段的数据,i为0至rs.Fields.Count-1

      rs("字段名"):指定字段的数据。

      rs.Record.Count:数据记录总数。

      rs.EOF:是否最后一条记录。

      rs.MoveFirst:指向第一条记录。

      rs.MoveLast:指向最后一条记录。

      rs.MovePrev:指向上一条记录。

      rs.MoveNext:指向下一条记录。

      rs.GetRows:将数据放入数组中。

      rs.Properties.Count:ADO的ResultSet或Connection的属性个数。

      rs.Properties(item).Name:ADO的ResultSet或Connection的名称。

      rs.Properties:ADO的ResultSet或Connection的值。

      rs.close():关闭连接。

    Recordset 对象的属性
    1、CursorType 属性
    AdOpenForwardOnly: 仅向前游标,默认值。除了只能在记录中向前滚动外,与静态游标相同。当只需要在记录集中单向移动时,使用它可提高性能。(顾名思义,这种游标只能向前移动。然而,由于这种游标功能有限,将它用于系统资源时是非常有效的。)
    AdOpenKeyset: 键集游标。尽管从您的记录集不能访问其他用户删除的记录,但除无法查看其他用户添加的记录外,键集游标与动态游标相似。仍然可以看见其他用户更改的数据。(KeySet游标允许你看见自它创建起其他用户所做的修改,然而你却不能看到其他用户增加或删除的记录。)
    AdOpenDynamic :动态游标。可以看见其他用户所作的添加、更改和删除。允许在记录集中进行所有类型的移动,但不包括提供者不支持的书签操作。(此类型的游标功能强大同时也是耗费系统资源最多的游标。Dynamic游标可以看到他们保存记录集合的所有变化。使用Dynamic游标的用户可以看到其他用户所做的编辑、增加、删除。如果数据提供者允许这种类型的游标,那么它是通过每隔一段时间从数据源重取数据来支持这种可视性的。毫无疑问这会需要很多的资源。 )
    AdOpenStatic:静态游标。可以用来查找数据或生成报告的记录集合的静态副本。另外,对其他用户所作的添加、更改或删除不可见。(Static类游标只是数据的一幅快照。这就是说,它无法看到自它创建以后其他用户对RecordSet所做的修改。采用这类游标你可以向前和向后航行。由于其功能简单,资源的需求比Dynamic要小! )
    需要注意的是:一旦打开RecordSet,你就无法改变CursorType属性。但是,如果你首先关闭RecordSet,改变CursorType属性,然后重新打开RecordSet,那么你仍可以有效地改变游标的类型!

    2、LockType 属性
    在任何同时可被多用户修改的数据库应用程序中,你必须处理可能发生的多个用户同时对同一条记录进行操作时的情况。当这种情况出现时,数据的完整性就会受到威胁,这是因为一个用户可能会在不自觉地在保存自己所做的修改时覆盖他人的修改。到时候你会觉得自己好象是没有做事。为了处理这种情况。ADO允许你在对RecordSet对象进行更新时决定并发事件控制的类型,当一个用户编辑时,如何由他对记录进行锁定。这就是由LockType属性所决定的。这个属性有四个值:
    adLockReadonly:默认值,只读。无法更改数据。(这是RecodSet的默认值,如果你把锁定的方式设为该值,那么你将不能更新 Recordset。)
    adLockPessimistic:保守式记录锁定(逐条)。提供者执行必要的操作确保成功编辑记录,通常采用编辑时立即锁定数据源的记录的方式。(如果设置为此类锁定,记录被锁定,且只有在编辑开始到将记录更新的提交给数据提供者这段时间内进行编辑的用户才可以访问! )
    adLockOptimistic:开放式记录锁定(逐条)。提供者使用开放式锁定,只在调用 Update 方法时锁定记录。(只有在将数据提交给数据提供者的那一瞬间才把记录锁定。)
    adlockBatchOptimistic:开放式批更新。用于与立即更新模式相反的批更新模式。(设定为这种类型的锁定制式将被称为批量更新模式的RecordSet。 可以加快更新RecordSet修改数据的速度,但因为同时更新多个记录,它也会恶化与并发访问相关的问题! )

    3、AbsolutePage 属性
    AbsolutePage属性设定当前记录的位置是位于哪一页的页数编号;使用PageSize属性将Recordset对象分割为逻辑上的页数,每一页的记录数为PageSize(除了最后一页可能会有少于PageSize的记录数)。这里必须注意并不是所有的数据提供者都支持此项属性,因此使用时要小心。
    与AbsolutePosition属性相同,AbsolutePage属性是以1为起始的,若当前记录为Recordset的第一行记录,AbsolutePage为1。可以设定AbsolutePage属性,以移动到一个指定页的第一行记录位置。
    4、AbsolutePosition属性
    若您需要确定目前指标在RecordSet中的位置,您可以用AbsolutePosition属性。
    AbsolutePosition属性的数值为目前指标相对於第一笔的位置,由1算起,即第一笔的AbsolutePosition为1。
    注意,在存取RecordSet时,无法保证RecordSet每次都以同样的顺序出现。
    若要启用AbsolutePosition,必须先设定为使用用户端cursor(指针):rs.CursorLocation=3

    5、PageCount属性
    使用PageCount属性,决定Recordset对象包括多少“页”的数据。这里的“页”是数据记录的集合,大小等于PageSize属性的设定,即使最后一页的记录数比PageSize的值少,最后一页也算是PageCount的一页。必须注意也并不是所有的数据提供者都支持此项属性。

    6、PageSize属性
    PageSize属性是决定ADO存取数据库时如何分页显示的关键,使用它就可以决定多少记录组成一个逻辑上的“一页”。设定并建立一个页的大小,从而允许使用AbsolutePage属性移到其它逻辑页的第一条记录。PageSize属性能随时被设定。

    7、RecordCount属性
    这也是一个非常常用和重要的属性,我们常用RecordCount属性来找出一个Recordset对象包括多少条记录。使用 RecordCount 属性可确定Recordset 对象中记录的数目。ADO 无法确定记录数时,或者如果提供者或游标类型不支持 RecordCount,则该属性返回 –1。读已关闭的 Recordset 上的 RecordCount 属性将产生错误。Recordset 对象的游标类型会影响是否能够确定记录的数目。对仅向前游标,RecordCount 属性将返回 -1,对静态或键集游标返回实际计数,对动态游标取决于数据源返回 -1 或实际计数。

    8、BOF与EOF属性
    通常我们在ASP程序中编写代码来检验BOF与EOF属性,从而得知目前指标所指向的RecordSet的位置,使用BOF与EOF属性,可以得知一个Recordset对象是否包含有记录或者得知移动记录行是否已经超出该Recordset对象的范围。
    若当前记录的位置是在一个Recordset对象第一行记录之前时,BOF属性返回true,反之则返回false。
    若当前记录的位置是在一个Recordset对象最后一行记录之后时,EOF属性返回true,反之则返回false。
    (BOF与EOF都为True表示在RecordSet里没有任何记录。)

    9、Filter 属性
    为 Recordset 中的数据指定筛选条件,使用 Filter 属性可选择性地屏蔽 Recordset 对象中的记录,已筛选的 Recordset 将成为当前游标。
    这将影响基于当前游标返回值的其他属性,如 AbsolutePosition、AbsolutePage、RecordCount 和 PageCount,因为将 Filter 属性设置为特
    定值可将当前记录移动到满足新值的第一个记录。
    这属性我认为相当有用处,有的时候我们打开了Recordset进行了某些判断以后我们还想过滤记录也就是重新调整 sql 语句,难道我们关闭Recordset再用新的SQL语句打开?不是,我们用Filter属性进行过滤,比如说
    rs.open exec,conn,1,1
    if .... then rs.filter="name='xxx'"
    而不是
    rs.open exec,conn,1,1
    if ... then
    rs.close
    exec=exec&" where name='xxx'"
    rs.open exec,conn,1,1
    end if
    实际上再很多地方不得不用到Filter,在以后的ASP技巧中会说到,大家也可以想一下。
    明天继续说Recordset对象的方法。

    Recordset对象的方法
    1、AddNew 方法
    创建可更新 Recordset 对象的新记录。
    recordset.AddNew FieldList, Values
    FieldList   可选。新记录中字段的单个名称、一组名称或序号位置。
    Values   可选。新记录中字段的单个或一组值。如果 Fields 是数组,那么 Values 也必须是有相同成员数的数组,否则将发生错误。字段名称的次序必须与每个数组中的字段值的次序相匹配。
    我们一般是
    rs.addnew
    rs("xx")=xx
    rs("xx")=xx
    rs.update
    需要注意的是在立即更新模式(调用 Update 方法时提供者会立即将更改写入基本数据源)下,调用不带参数的 AddNew 方法可将 EditMode 属性设置为 adEditAdd。提供者将任何字段值的更改缓存在本地。调用 Update 方法可将新记录传递到数据库并将 EditMode 属性重置为 adEditNone。如果传送了 Fields 和 Values 参数,ADO 则立即将新记录传递到数据库(无须调用 Update),且 EditMode 属性值没有改变 (adEditNone)。
    可能大家会问在ASP中使用ADO的AddNew方法和直接使用“Insert into...”语句有和不同?那种方式更好?答:ADO的AddNew方法只是将“Insert into ”语句封装了起来,所以,当对大量数据进行操作的时候,直接使用SQL语句将会大大加快存取数据的速度,因为他减少了ADO的“翻译”时间。

    2、Delete 方法
    删除当前记录或记录组。
    recordset.Delete AffectRecords
    AffectRecords   AffectEnum 值,确定 Delete 方法所影响的记录数目,该值可以是下列常量之一。
    AdAffectCurrent 默认。仅删除当前记录。
    AdAffectGroup 删除满足当前 Filter 属性设置的记录。要使用该选项,必须将 Filter 属性设置为有效的预定义常量之一。
    adAffectAll 删除所有记录。
    adAffectAllChapters 删除所有子集记录。
    使用立即更新模式将在数据库中进行立即删除,否则记录将标记为从缓存删除,实际的删除将在调用 Update 方法时进行。
    3、Update 方法
    保存对 Recordset 对象的当前记录所做的所有更改
    recordset.Update Fields, Values
    Fields   可选。变体型,代表单个名称;或变体型数组,代表需要修改的字段(一个或多个)名称及序号位置。
    Values   可选。变体型,代表单个值;或变体型数组,代表新记录中字段(单个或多个)值。
    如果希望取消对当前记录所做的任何更改或者放弃新添加的记录,则必须调用 CancelUpdate 方法。
    4、CancelUpdate 方法
    recordset.CancelUpdate
    使用 CancelUpdate 方法可取消对当前记录所作的任何更改或放弃新添加的记录。在调用 Update 方法后将无法撤消对当前记录或新记录所做的更改,如果在调用 CancelUpdate 方法时添加新记录,则调用 AddNew 之前的当前记录将再次成为当前记录。如果尚未更改当前记录或添加新记录,调用 CancelUpdate 方法将产生错误。
    5、Find 方法
    搜索 Recordset 中满足指定标准的记录。如果满足标准,则记录集位置设置在找到的记录上,否则位置将设置在记录集的末尾。
    Find (criteria, SkipRows, searchDirection, start)
    criteria   字符串,包含指定用于搜索的列名、比较操作符和值的语句。
    SkipRows    可选,长整型值,其默认值为零,它指定当前行或 start 书签的位移以开始搜索。
    searchDirection    可选的 SearchDirectionEnum 值,指定搜索应从当前行还是下一个有效行开始。其值可为 adSearchForward 或
    adSearchBackward。搜索是在记录集的开始还是末尾结束由 searchDirection 值决定。
    start    可选,变体型书签,用作搜索的开始位置。
    criteria “比较操作符”可以是“>”(大于)、“<”(小于)、“=”(等于)、“>=”(大于或等于)、“<=”(小于或等于)、“<>”
    (不等于)或“like”(模式匹配)。 criteria 中的值可以是字符串、浮点数或者日期。字符串值以单引号分界(如“state = 'WA'”)。
    日期值以“#”(数字记号)分界(如“start_date > #7/22/97#”)。
    需要注意的是find是不支持多字段。但是可以用filter实现。"name='abc'"AND "city='sh'" 是不允许的
    6、Move 方法
    移动 Recordset 对象中当前记录的位置
    recordset.Move NumRecords, Start
    NumRecords    带符号长整型表达式,指定当前记录位置移动的记录数。
    Start    可选,字符串或变体型,用于计算书签。也可为下列值之一:
    AdBookmarkCurrent 默认。从当前记录开始。
    AdBookmarkFirst 从首记录开始。
    AdBookmarkLast 从尾记录开始。
    需要注意的是:
    (1)如果 NumRecords 参数大于零,则当前记录位置将向前移动(向记录集的末尾)。如果 NumRecords 小于零,则当前记录位置向后移动(向记录集的开始)。
    (2)从空的 Recordset 对象调用 Move 方法将产生错误。
    (3)如果 Move 调用将当前记录位置移动到首记录之前,则 ADO 将当前记录放置在记录集(BOF 为 True)的首记录之前。在 BOF 属性已经为 True 时试图向后移动将产生错误;如果 Move 调用将当前记录位置移动到尾记录之后,则 ADO 将当前记录放置在记录集(EOF 为 True)的尾记录之后。在 EOF 属性已经为 True 时试图向前移动将产生错误。
    7、MoveFirst、MoveLast、MoveNext 和 MovePrevious 方法
    在指定 Recordset 对象中移动到第一个、最后一个、下一个或前一个记录并使该记录成为当前记录。
    recordset.{MoveFirst | MoveLast | MoveNext | MovePrevious}
    需要注意的是:
    (1)使用 MoveNext 方法将当前记录向前移动一个记录(向 Recordset 的底部)。如果最后一个记录是当前记录并且调用 MoveNext 方法,则 ADO 将当前记录设置到 Recordset (EOF 为 True)的尾记录之后。当 EOF 属性已经为 True 时试图向前移动将产生错误。
    (2)使用 MovePrevious 方法将当前记录位置向后移动一个记录(向记录集的顶部)。Recordset 对象必须支持向后游标移动;否则方法调用将产生错误。如果首记录是当前记录并且调用 MovePrevious 方法,则 ADO 将当前记录设置在 Recordset (BOF 为 True)的首记录之前。而 BOF 属性为 True 时向后移动将产生错误。
    8、Clone 方法
    创建与现有 Recordset 对象相同的复制 Recordset 对象。可选择指定该副本为只读。
    Set rstDuplicate = rstOriginal.Clone
    rstDuplicate   对象变量,标识正在创建的复制 Recordset 对象。
    rstOriginal   对象变量,标识要被复制的 Recordset 对象。
    使用 Clone 方法可创建多个 Recordset 对象副本,这对于希望在给定的记录组中保留多个当前记录十分有用。使用 Clone 方法比使用与初始定义相同的定义创建和打开新 Recordset 对象要有效得多。
    也就是说
    rs.open exec,conn,1,1
    rs2.open exec,conn,1,1
    应该这么改写
    rs.open exec,conn,1,1
    rs2=rs.clone
    需要注意的是:
    (1)新创建副本的当前记录将设置为首记录。
    (2)关闭原始 Recordset 时并不关闭它的副本,而关闭某个副本也将不关闭原始 Recordset 或任何其他副本。

    9、Close 方法
    关闭打开的对象及任何相关对象。
    object.Close
    需要注意的是:
    (1)使用 Close 方法可关闭Recordset 对象以便释放所有关联的系统资源。关闭对象并非将它从内存中删除,可以更改它的属性设置并且在
    此后再次打开。要将对象从内存中完全删除,可将对象变量设置为 Nothing。
    (2)如果正在立即更新模式下进行编辑,调用 Close 方法将产生错误,应首先调用 Update 或 CancelUpdate 方法。

    10、Open 方法,为什么最后说这个,因为前面的各项属性方法没有弄清楚,我们是不会理解CursorType参数的
    recordset.Open Source, ActiveConnection, CursorType, LockType, Options
    Recordset对象可以通过Source属性来连接Command对象。Source参数可以是一个Command对象名称、一段SQL命令、一个指定的数据表名称或是一个Stored Procedure。假如省略这个参数,系统则采用Recordset对象的Source属性。ActiveConnection
    Recordset对象可以通过ActiveConnection属性来连接Connection对象。这里的ActiveConnection可以是一个Connection对象或是一串包含数据
    库连接信息(ConnectionString)的字符串参数。CursorType
    Recordset对象Open方法的CursorType参数表示将以什么样的游标类型启动数据,包括adOpenForwardOnly、adOpenKeyset、adOpenDynamic及ad
    OpenStatic,分述如下:
    --------------------------------------------------------------
    常数 常数值 说明
    -------------------------------------------------------------
    adOpenForwardOnly 0 缺省值,启动一个只能向前移动的游标(Forward Only)。
    adOpenKeyset 1 启动一个Keyset类型的游标。
    adOpenDynamic 2 启动一个Dynamic类型的游标。
    adOpenStatic 3 启动一个Static类型的游标。
    -------------------------------------------------------------
    以上几个游标类型将直接影响到Recordset对象所有的属性和方法,以下列表说明他们之间的区别。
    Recordset属性 adOpenForwardOnly adOpenKeyset adOpenDynamic adOpenStatic

    AbsolutePage 不支持 不支持 可读写 可读写
    AbsolutePosition 不支持 不支持 可读写 可读写
    BOF 只读 只读 只读 只读
    CursorType 可读写 可读写 可读写 可读写
    EOF 只读 只读 只读 只读
    Filter 可读写 可读写 可读写 可读写
    LockType 可读写 可读写 可读写 可读写
    PageCount 不支持 不支持 只读 只读
    PageSize 可读写 可读写 可读写 可读写
    RecordCount 不支持 不支持 只读 只读
    AddNew 支持 支持 支持 支持
    CancelBatch 支持 支持 支持 支持
    CancelUpdate 支持 支持 支持 支持
    Close 支持 支持 支持 支持
    Delete 支持 支持 支持 支持
    Move 不支持 支持 支持 支持
    MoveFirst 支持 支持 支持 支持
    MoveLast 不支持 支持 支持 支持
    MoveNext 支持 支持 支持 支持
    MovePrevious 不支持 支持 支持 支持
    Open 支持 支持 支持 支持
    Update 支持 支持 支持 支持
    UpdateBatch 支持 支持 支持 支持
    --------------------------------------------------------------
    Recordset对象Open方法的LockType参数表示要采用的Lock类型,如果忽略这个参数,那么系统会以Recordset对象的LockType属性为预设值。LockType参数包含adLockReadOnly、adLockPrssimistic、adLockOptimistic及adLockBatchOptimistic等,分述如下:
    常数 常数值 说明
    --------------------------------------------------------------
    adLockReadOnly 1 缺省值,Recordset对象以只读方式启动,无法运行AddNew、Update及Delete等方法
    adLockPrssimistic 2 当数据源正在更新时,系统会暂时锁住其他用户的动作,以保持数据一致性。
    adLockOptimistic 3 当数据源正在更新时,系统并不会锁住其他用户的动作,其他用户可以对数据进行增、删、改的操作。
    adLockBatchOptimistic 4 当数据源正在更新时,其他用户必须将CursorLocation属性改为adUdeClientBatch才能对数据进行增、删、改的操作。
    需要注意的是:
    如果数据源没有返回记录,那么提供者将 BOF 和 EOF 属性同时设置为 True,并且不定义当前记录位置。如果游标类型允许,仍然可以将新数据添加到该空 Recordset 对象。

     

  • QTP连接数据库-rst.recordcount返回-1(ZT)

    2009-11-05 12:25:28

    今天,在一个asp技术群里一个朋友问了这么一个问题:rs.recordcount为什么返回值总是-1呢?以前在asp编程的过程中也碰到过相同的问题,于是就告诉他方法,但是,无论怎么改总是不可以。最后发现,他连接的是mysql数据库,而我做过的那些是access数据库。因此,问题也就出来了。怎么解决呢?

    他的原本语句:rs.open "select A_name from area where A_state='1' order by A_id asc",conn,1,1。然后输出rs.recordcount的值是-1.怎么改?

    1).为了书写简便,我写成这样:rs.open sql,conn,3,1.我让他改成这样,结果还是返回-1.纳闷,曾经在access数据库编程中,只要改了这个参数,一切ok.看来,还有问题。难道是数据库问题?

    2).在rs.open sql,conn,1,1之前添加一句:rs.cursorlocation = 3。结果,还是不可以。

    3).改成:rs.cursorlocation = 3    rs.open sql,conn,3,1.ok.成功!

    下面解释一下:rs.open sql,conn,3,1。这句中两个参数分别表示游标类型和锁定类型。什么是游标类型

    游标类型:

    Const adOpenForwardOnly = 0
    前向游标,为缺省游标,提供最快的运行性能。用它打开recordset,从对至尾顺序取得所有结果。它不支持向后滚动,只允许在结果间单向移动。

    Const adOpenKeyset = 1
    静态游标,反映第一次打开游标时表中数据的状态,游标无法查明底层表中的数据行是否更新过、删除过或添加了新的数据。不过与只能前移的洲标不同,静态游标可以在结果间前后滚动。

    Const adOpenDynamic = 2
    键盘驱动的游标,可以查询表中底层数据行的某些变化,但不是全部。它特别是可以准确反映数据是否更新过。但它不能查明其它用户是否曾删除过数据行(删除掉的数据行在recordset中会留下空洞)。键盘驱动的游标支持在结果间前后滚动。

    Const adOpenStatic = 3
    动态游标,是最丰富的游标类型。游标打开时可以查询其他用户对表的任何改动,而且支持滚动。

    什么是锁定类型?

    Const adLockReadOnly = 1
    缺省的上锁类型,只读方式上锁允许多个用户同时读取同样的数据,但不能改变数据。

    Const adLockPessimistic = 2
    以悲观上锁方式打开数据对象。该方式假定在你编辑记录时会有其它用户访问数据。此时一旦你开始编辑记录,其它用户就不能访问该数据。

    Const adLockOptimistic = 3
    以乐观上锁方式打开数据对象。该方式假定在你编辑记录时不会有其它用户访问数据。在完成改变之前,其它用户不能访问该记录。

    Const adLockBatchOptimistic = 4
    执行多行批处理更新时使用这种类型

    那么rs.cursorlocation = 3又是什么意思呢?就是代表使用客户端光标,也就是rs.CursorLocation = adUseClient。对应的是 rs.CursorLocation = adUseServer 服务端光标。

    看看下面更详细的解释:

    CursorLocation 属性

        设置或返回游标服务的位置。

         设置和返回值

         设置或返回可设置为以下某个常量的长整型值。

    常量 说明
    adUseNone 没有使用游标服务。(该常量已过时并且只为了向后兼容才出现)。
    adUseClient 使用由本地游标库提供的客户端游标。本地游标服务通常允许使用的许多功能可能是驱动程序提供的游标无法使用的,因此使用该设置对于那些将要启用的功能是有 好处的。AdUseClient 具有向后兼容性,也支持同义的 adUseClientBatch。
    adUseServer 默认值。使用数据提供者的或驱动程序提供的游标。这些游标有时非常灵活,对于其他用户对数据源所作的更改具有额外的敏感性。但是,Microsoft Client Cursor Provider(如已断开关联的记录集)的某些功能无法由服务器端游标模拟,通过该设置将无法使用这些功能。


    说明


    该属性允许在可用于提供者的各种游标库中进行选择。通常,可以选择使用客户端游标库或位于服务器上的某个游标库。

    该属性设置仅对属性已经设置后才建立的连接有影响。更改 CursorLocation 属性不会影响现有的连接。

    对于 Connection 或关闭的 Recordset 该属性为读/写,而对打开的 Recordset 该属性为只读。

    由 Execute 方法返回的游标继承该设置。Recordset 将自动从与之关联的连接中继承该设置。

    远程数据服务用法 当用于客户端 (ADOR) Recordset 或 Connection 对象时,只能将 CursorLocation 属性设置为 adUseClient。

  • 密码不满足策略

    2009-10-30 18:32:31

    装QC的时候遇到的问题,改了密码安全策略都无效,原来是要刷新,晕死~

    折腾了一下午

    修改“域安全策略”和“域控制器安全策略”,将其中限制密码的策略都取消,然后运行gpupdate。就可以了

     

    Windows 2003 无法设置密码解决办法

    在设置win2003的域用户密码时,老是出现这样的提示——

    windows无法设置linxiaoyan的密码,原因是:

    密码不满足密码策略的要求。检查最小密码长度,密码复杂性和密码历史的要求。

    我设置的密码都是六位数以上的,有数字的,有字母的,有混合的。可是都不行。请问是什么原因,如何设置

    对于2003域,默认域的安全策略与2000域不同。要求域用户的口令必须符合复杂性要求,且密码最小长度为7。口令的复杂性包括三条:一是大写字母、小写字母、数字、符号四种中必须有3种,二是密码最小长度为6,三是口令中不得包括全部或部分用户名。当然也可以重新设默认域的安全策略来解决。

    选择 开始>程序>管理工具>域安全策略>帐户策略>密码策略

    密码必须符合复杂性要求:由“已启用”改为“已禁用”;

    密码长度最小值:由“7个字符”改为“0个字符”

    使此策略修改生效有如下方法:

    1、等待系统自动刷新组策略,约5分钟~15分钟

    2、重启域控制器(若是修改的用户策略,注销即可)

    3、使用gpupdate命令

    仅刷新计算机策略:gpupdate/target:computer

    仅刷新用户策略:gpupdate/target:user

    二者都刷新:gpupdate

  • 仓央嘉措情歌

    2008-09-01 10:35:59

    (一)

    第一最好不相见,如此便可不相恋。

    第二最好不相知,如此便可不相思。

    第三最好不相伴,如此便可不相欠。

    第四最好不相惜,如此便可不相忆。

    第五最好不相爱,如此便可不相弃。

    第六最好不相对,如此便可不相会。

    第七最好不相误,如此便可不相负。

    第八最好不相许,如此便可不相续。

    第九最好不相依,如此便可不相偎。

    第十最好不相遇,如此便可不相聚。

    但曾相见便相知,相见何如不见时。

    安得与君相诀绝,免教生死作相思。

    (二)

    我问佛:为何不给所有女子羞花闭月的容颜?

    佛曰:那只是昙花的一现,用来蒙蔽世俗的眼

    没有什么美可以抵过一颗纯净仁爱的心

    我把它赐给每一个女子,

    可有人让它蒙上了灰。

    我问佛:世间为何有那么多遗憾?

    佛曰:这是一个婆娑世界,

    婆娑即遗憾,没有遗憾,

    给你再多幸福也不会体会快乐  

     

    我问佛:如何让人们的心不再感到孤单?

    佛曰:每一颗心生来就是孤单而残缺的,

    多数带着这种残缺度过一生

    只因与能使它圆满的另一半相遇时

    不是疏忽错过,就是已失去了拥有它的资格 

     

    我问佛:如果遇到了可以爱的人,

    却又怕不能把握该怎么办?

    佛曰:留人间多少爱,迎浮世千重变

    和有情人,做快乐事

    别问是劫是缘  

     

    我问佛:如何才能如你般睿智?

    佛曰:佛是过来人,人是未来佛

    我也曾如你般天真

    佛门中说一个人悟道有三阶段:“勘破、放下、自在。”

    的确,一个人必须要放下,才能得到自在。

    (三)

    那一天,那一月,那一年,那一世

    那一刻,我升起风马,不为乞福,只为守候你的到来 

        那一日,垒起玛尼堆,不为修德,只为投下心湖的石子    

        那一瞬,我飞升成仙,不为长生,只为佑你平安喜乐

    那一天,我闭目在经殿的香雾中,蓦然听见你颂经中的真言;

    那一月,我摇动所有的经筒,不为超度,只为触摸你的指尖;

    那一年,磕长头匍匐在山路,不为觐见,只为贴着你的温暖;

    那一世,转山转水转佛塔,不为修来世,只为途中与你相见。

    那一夜,我听了一宿梵唱,不为参悟,只为寻你的一丝气息;

    那一月,我转过所有经筒,不为超度,只为触摸你的指纹;

    那一年,我磕长头拥抱尘埃,不为朝佛,只为贴着你的温暖;

    那一世,我翻遍十万大山,不为修来世,只为路中能与你相遇;

    只是,就在那一夜,

    我忘却了所有,抛却了信仰,舍弃了轮回,

    只为,那曾在佛前哭泣的玫瑰,

    早已失去旧日的光泽。

    于是佛曰:忘却,忘却。

  • QTP:Debug Viewer相关整理ZT

    2008-08-20 14:20:40

    Debug Viewer

        使用Debug VieWer面板,可以查看、设置、修改Object对象或变量的值。当脚本运行到断点时可以通过Degug VieWer面板查看、设置、修改Object对象或变量的值;或当脚本运行失败时,在Debug弹出窗口中选择“Debug”选项后,也可以通过Degug VieWer面板查看、设置、修改Object对象或变量的值。

        通过 View>Debug viewer或点击Debug Viewer按钮,可以打开Debug Viewer面板。

    Debug viewer面板可以显示变量或对象Object的值。它有3个页签:WatchVariables以及Command

    1.Watch

        通过“Add to Watch”方法将Object或变量加入到Watch页后,就可以查看到Object或变量的当前值。在脚本逐步执行的过程中,如果值发生了改变,QTP会自动进行更新。在脚本运行到断点暂停时你还可以手工对Watch页面的值进行更新。

    Watch页中添加表达式的方法有以下几种:

        1)在脚本中选中表达式,然后选择菜单Debug>Add to Watch

        2)在脚本中选中表达式,然后按Ctrl+T

        3)在脚本中选中表达式,然后选择右键菜单Add to Watch

        4)在Watch页,手工粘贴或输入Object或变量名到“Name”列,然后点击回车,在“Value”列就会显示数值。

        Add to Watch既可以在脚本运行前使用,也可以在脚本运行时使用。在脚本运行时添加时,可以马上查看到它的当前数值。

    2.Variable

        当脚本运行停止或暂停时在Variable页,QTP自动显示所有变量的当前值。脚本在运行过程中,将变量及其值显示在Variable列表中,如果在后续的脚本中变量值发生了改变,则列表中的值也会相应改变。在脚本运行到断点暂停时,你还可以手工修改变量值。

    3.Command

    Command页,用户可以输入并执行脚本命令。此功能帮助用户设置或修改变量值或Object值,当脚本继续运行时,QTP使用修改过的值。

     

    QTP调试器功能的方法 

            QTP的脚本编辑器中默调试器的功能十分有限,调试过程中很多象的属性都不能详细地看到。

            但是如果安装了Visual Studio.NET 2008可以增QTP调试能力,在Debug Viewer中可以看到象的大部分属性。

            可以通安装Visual Studio.NET 2008来增QTP调试能力,也可以不安装,仅仅把其中一个名PDM.DLL的文件拷“C:\Program Files\Common Files\Microsoft Shared\VS7DEBUG中,然后注册一下即可,注册方法是在命令行中“RegSVR32 “C:\Program Files\Common Files\Microsoft Shared\VS7DEBUG\pdm.dll"”

  • 使用QTP的一些方法ZT

    2008-08-20 14:09:38

    1.增强QTP调试器功能的方法 

            QTP的脚本编辑器中默认的调试器的功能十分有限,在调试过程中很多对象的属性都不能详细地看到。

            但是如果安装了Visual Studio.NET 2008,则可以增强QTP的调试能力,在“Debug Viewer”中可以查看到对象的大部分属性。

            可以通过安装Visual Studio.NET 2008来增强QTP调试能力,也可以不安装,仅仅把其中一个名为PDM.DLL的文件拷贝到“C:\Program Files\Common Files\Microsoft Shared\VS7DEBUG”目录中,然后注册一下即可,注册方法是在命令行中输入“RegSVR32 “C:\Program Files\Common Files\Microsoft Shared\VS7DEBUG\pdm.dll"”。

    2.QTP测试脚本批处理运行的两个工具

            在运行多个QTP脚本时,可以选择两个工具来完成,1个是QTP自带的Test Batch Runner,另外一个是Mercury Multi-Test Manager。

            (1)两个工具都能运行Test Batch文件。

            (2)Mercury Multi-Test Manager使用起来会更加灵活,能以HTML格式显示测试执行的状态信息和报告。

            (3)Mercury Multi-Test Manager的运行方式更加灵活,通过在网络计算机上运行脚本,还可以模拟压力测试。

            (4)让脚本执行任务更简单地创建和维护,并且可以发送邮件,告诉项目组测试脚本的运行状态。

            (5)Mercury Multi-Test Manager支持COM访问和调用。

    3.QTP操作注册表

            在QTP中没有提供用于直接操作注册表的测试对象,但是利用Windows脚本的Shell对象,可以对注册表进行增删改等操作,例如下面的脚本:

    Dim WshShell, bKey

    ' 创建Shell对象

    Set WshShell = CreateObject("Wscrīpt.Shell")

    ' 使用Shell对象来读取注册表

    bKey = WshShell.RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Mozilla\Mozilla Firefox 1.5\Extensions\Plugins")

    Msgbox bKey

    ' 修改注册表

    WshShell.RegWrite "HKEY_LOCAL_MACHINE\SOFTWARE\Mozilla\Mozilla Firefox 1.5\Extensions\Plugins", "D:\Program Files\Mozilla Firefox\Plugins", "REG_SZ"

    ' 删除注册表

    WshShell.RegDelete "HKEY_LOCAL_MACHINE\SOFTWARE\Mozilla\Mozilla Firefox 1.5\Extensions\Plugins"

    ' 修改或写入注册表

    WshShell.RegWrite "HKEY_LOCAL_MACHINE\SOFTWARE\Mozilla\Mozilla Firefox 1.5\Extensions\Plugins", "C:\Program Files\Mozilla Firefox\Plugins", "REG_SZ"

  • QTP:DataTable对象相关的方法

    2008-08-15 14:20:30

    filename="C:\Program Files\Mercury Interactive\QuickTest Professional\Tests\**\Default.xls"'DataTable存放路径
    Par=DataTable.GetSheet("Global").AddParameter("Param1","name1").name'运行时向DataTable添加列,并取得该列名称
    print Par
    DataTable.GetSheet("Global").SetNextRow'设置下一行
    m=DataTable.GetSheet("Global").GetParametercount'取得总列数
    DataTable.GetSheet("Global").DeleteParameter ("Param1")'运行时向DataTable删除列
    DataTable.GetSheet("Global").SetPrevRow'设置上一行
    Parname=DataTable.GetSheet("Global").GetParameter("Destination")'取得某列的值
    print Parname
    n=DataTable.GetSheet("Global").GetRowCount'取得总行数
    DataTable.GetSheet("Global").SetCurrentRow(3)'设置当前行为第3行
    DataTable.Value ("Destination", "Global")="New York"'运行时设置某列值
  • QTP:检查网页焦点迁移

    2008-08-13 16:31:53

    Systemutil.Run"iexplore.exe","http://www.baidu.com"
    wait 5
    '------------------------------------------------------------------------------
    Function get_focus_property(name)
        Browser("百度一下,你就知道_2").WinEdit("Edit").click
     Browser("百度一下,你就知道_2").WinEdit("Edit").Type micTab 
     'wait 10
    Execute "value=Browser(""百度一下,你就知道_2"")."&name&".GetROProperty(""focus"")"  '执行获取焦点属性的命令
    '将上面命令是否获取成功的结果输出到report
    If  value="1" Then
     Reporter.ReportEvent micPass,"focus", "The user-defined step failed."
     Else
     Reporter.ReportEvent micFail,"focus", "The user-defined step failed."
    End If
    End Function
    '__________________________________________________
    ncount=DataTable.GetSheet("Action1").GetRowCount
    For i=1 to ncount
     DataTable.GetSheet("Action1").SetCurrentRow(i)
     name1=DataTable(1,"Action1")'从DataTable中取出控件名称
        get_focus_property name1
    Next

  • DataTable导出数据至excel

    2008-08-12 14:01:43

    Dim excelApp,excelSheet,fso,rount,ccount
    Set excelApp = CreateObject("Excel.Application") '创建Excel Application对象
    Set excelSheet =  CreateObject("Excel.sheet") '创建Excel Sheet对象
    Set fso = CreateObject("scrīpting.FileSystemObject") '创建FileSystemObject对象
    filename = "C:\Documents and Settings\yuan wen\Desktop\newcopy\QTP\text.xls" '设定文件路径
    excelApp.Visible = true 'excel可见
    rcount=DataTable.GetSheet("Global").GetRowCount
    ccount=DataTable.GetSheet("Global").GetParameterCount'获取DataTabel中的列数
    '--------------------------------------------------------------------------------------------------------------------------------
     Function output_loop(r,c)
       For i =1 to r
      For s=1 to c
            DataTable.GetSheet(dtGlobalSheet).SetCurrentRow(i)'设置当前行,方便循环
            excelSheet.ActiveSheet.Cells(i,s).Value = DataTable(s,dtGlobalSheet)  '循环读取DataTable1~s列当前行的值
      Next
      Next
    End Function
    '---------------------------------------------------------------------------------------------------------------------------
    If fso.FileExists(filename) Then '检测文件是否存在,如果存在就删除文件然后写入数据
        print "text.xls 文件已经存在"
        fso.DeleteFile(filename)
        output_loop rcount,ccount
    Else  '如果文件不存在,直接写入数据
       print "text.xls 文件不存在"
       output_loop rcount,ccount
    End If
    excelSheet.SaveAs filename '将数据保存到文件中
    excelApp.Quit  '退出Excel
    Set excelSheet = nothing '将sheet对象置为空
    Set fso = nothing '将fso对象置为空

    最后发现有个超简单的方法可以将DataTable导入导出,那就是DataTable中单击鼠标右键,选择File,然后……看见了吧。

    另外,还有语句如下:

    DataTable.ExportSheet "C:\Documents and Settings\yuan wen\Desktop\newcopy\QTP\text.xls","Global"
    DataTable.ImportSheet "C:\Documents and Settings\yuan wen\Desktop\newcopy\QTP\text.xls","Global","Action1"

    这个样子也是可以滴。

    条条大路通罗马阿~

  • 噩梦成真……

    2008-08-01 16:51:40

    话说,某天清晨的时候,姑娘我做了个梦。

    梦见吧,俺们部门测试的头头摇身一变成了无间道里的老大。然后测试组开大会,分配下阶段的工作。然后点了几个人,说是TMS503留下来跟AT.及其不幸的是,那其中有我。然后,老大问,大家还有什么问题没?一帮人举手说事儿,点啊点啊,点到最后才轮到我。我说头儿,能不能不让我跟AT啊,我想进新项目。话没说完就被头坚如磐石地否定了,不行,这是项目组的安排。梦刚到这儿,我就被吓醒了,一身冷汗阿~

    恩,项目延期,本来昨天就可以逃出升天了,然后延到4号,这也就算了吧 ,一个月都熬过来了,反正也就多忍两天。

    结果,刚组长MSN上的一段话让我欲哭无泪。

    Xu Yuanyuan [14:46]:
    袁文,一会儿Ghost回到有516的包的位置,可能会再出一个包,装一下再跑跑看
    Xu Yuanyuan [14:47]:
    或者你到我这儿来试试也可以
    Xu Yuanyuan [14:52]:
    对了,一直觉得你对MR的这个项目上手比较快,而且做事情也挺让人放心的,所以安排你结项之后做ATP的对应,主要负责Other,部分对应stitching。

    神哪,听说MR系统的AT bug都是极其变态的,谁能救救我?!不是都说早上的梦是反的么?这是哪个骗子说的?!

  • 轮回的喃喃自语

    2008-07-03 17:53:56

    安静谧糖果然后来了一只鬼才相信的神话中最帅的那个也不及玄彬彬有礼物你欠我多久九归一天就这样结束缚在你身上的灵异事件人一个你看不到的角落叶衬托不了花的绚烂桃一筐不及甜杏一颗星星眨眼睛光闪闪了腰协不了不爱你的人生如此寂寞然回首月明中学时代的跳马鞍
  • 两天三夜--写给痕

    2008-06-19 13:40:56

    痕,在你离开的这日,写下些许文字与你。

                           --汶

    16日夜

    只是因为一路上,一路上,大雨曾经滂沱,证明你要来了。妞儿,你看,对于我们的再见,老天都喜极而泣。于是当我闭上眼,再睁开眼,便看见你微笑的脸,挥舞的手。

    17日午后

    给你当了一回背影model。你我都是偶尔小恶作剧的姑娘,于是笑着配合了你的搞怪。

    17日黄昏

    我想,一直到我们很老很老的时候,我都会记得,曾经在烟雨迷朦的傍晚,与你一道,泛舟北海,放声歌唱。

    18日夜

    夜车。窗外有点点温暖的灯光,投射在你的侧脸,明明灭灭。才发现,原来与你,可以如此静默着相处,不需要苍白的言语来遮掩内心的局促。

    此刻

    心里竟然开始有舍不得。亲爱的,再见。

  • 紫的流水生活

    2008-01-02 14:02:53

    紫的流水生活

    有日子没上网了,中午的候,在公司的上网机器上翻了下blog。看小船的留言,切地我小紫,久了的温暖的感。我是个很的人,得跑网吧,短信,得都快人了。可是,我知道,无我消失多久,只要我想起一些人,他都会在。(得比如了,大家自觉对号入座吧)

    最近搬了家,和欣一起合租了一小失了不少,但是小日子越意了。新家有电视常两个人台看),有没网的电脑(只能用来看韩剧),有御用厨(可是打下手的那个人是我,洗碗的那个人是我?)。来呢,就是不用天天只着日语书发呆,不用天天吃简单的面条了。杨发短信要来我这边尝我的手,我脸红红地告他,我只会炒青菜,不好意思毒害他的胃。我真是个善良无比的孩子。哥哥打电话跟我炫耀说,他在女朋友家做从来都是一条全包的。然后,被我很不屑地回了句,你女朋友真。哈哈,说话不能太一针见血了。

    诞节候,桂子寄去了答她很久的要她永远记得我的礼物,石头记绿松石手,看的人都是桂子男朋友送的。哈哈,我真是太有成就感了。我跟桂子,要一着,不摘,人在,手在。突然想起来,某欠我圣礼物呢,看来我是太老了。

    2007年的最后一天,趁着打折的当口,在国美了手机。陪我去的欣,居然被我和服务员忽悠了两句,也了一个。我想的是,国美的营业员生猛无比,步步高的手机和的一,二抄起手机就往柜台上摔,不是我们拦着,人家都作直接往地上扔了。恩,手机是件很痛苦的事,因在有限的money内完全不到我想要的。所以,我只好将就地了个阿卡特,据在法国拿了设计,当然是据的。黑色的滑盖,感太棒了,边缘的背面是皮键盘是磨砂的。就第一眼的感,我的大动过滤掉了手机信号好不好,反速度快不快,摔等等一系列很重要的功能问题。你看你看,作测试都快半年了,我是一浅的只看外表的人。最后的最后,骗了一大堆赠品回来,包阿,抱枕阿,手机链阿,充电器阿,食用油阿,手机充值卡阿~欣说,你不是去买手机的,你是去打劫的。窃笑ing~

    2007年最后一天,上的候,和欣了一大堆吃的,用电饭煲涮火朝天的候,就想起和卜和超人一起吃串串的事了,我想知道八里有没有价,继续把那小的可怜的串,再串少一点?可是,知道了又有什用,八里里不会再有我的身影,就像我次路上地环岛哥,却只能感叹为西安的金斯那便宜一赵发短信,元旦了,可是要考了,要是没有考试该多好啊。然后我嘲笑她,真想把好事都占全了。要是没考,我上班的人不是太凄惨了,我是那怀念当年泡图书馆晒太阳的美好光。起考,想起考研的日子快到了,然我不知道是具体哪一天,灵宝宝要加油,就像我短信告你的,平常心就好。

    2008年的第一天,和欣有娟儿一起到西血拼,本来是我要包,娟儿要衣服的。果欣陪客到被我忽悠得最先了包和衣服,孩子气急坏得直脚,非逼着我回家。哈哈,看来我忽悠功夫快到家了。

    日子就这样流水般啦啦地去了,我依然天写写文档,看看电视剧扫扫,什都不用想,这样简单的生活未不是幸福,我知足了,吧?

     

  • 纯洁的人生不需要解释,流氓亦然

    2007-11-26 10:13:28

    [9:12]:

    很深。

      皇宫的寝宫深处,两男一女,三个人影上窜下跳,接着同时跳入一片空地当中。一男

    子手拿拂尘,瞪眼骂道:秃驴!你好大的胆子!竟敢跟贫道抢师太!

      女子急急叫道:哥!你净身入宫多年,我们根本不能做夫妻,你何必苦苦相逼呢!

    说着,紧紧拉住身边的男子:我只爱他!心里也只有他!

      那男子轻轻挣开女子的手,上前一步,低声说道:女儿!退后!看老衲今天杀了这

    臭道士!以报多年前的夺妻之恨!

      只见至爱的两人,以死相拼,女子无奈长叹一声:"你二人别争了,9年前我已有了爷爷的

    骨肉!现任小皇帝是也.我的身体只属于他,你们走吧..."

      此时,一座石狮背后,闪出一衣着华美的少年,叹道:"太后,朕实乃断袖之人,已与和尚爷

    爷有了龙阳之好..."说罢,眼角瞟了眼道士,便低下头去.

      手拿拂尘男子听后,呆立半晌,黯然道:,,,果然天道循环,因果不爽,当年我夺你

    ,如今你抢我心头之肉,枉我挥刀变性,乔为内官,受那自宫之苦

      大和尚却仿佛没听见道士的话,而是沉吟着问女子:女儿,你说陛下是九年前与父亲所出

    ?他如今是死是活?

      哈哈哈哈随着震耳的笑声,一个衣着破烂的喇嘛从天而降,秃驴,夺妻之仇未

    报,本座怎舍得就此西去?!!!

     

     

    估计很多人看不懂啊!~要慢慢的看下 才能看明白

    [9:29]:

    晕了,关系好复杂,可以拿去当高考的阅读理解了

    [9:29]:

    反正是乱伦就对了   乱的超离谱的

    [9:30]:

    你这家伙,净来这些东西,玷污我纯洁的思想

    [9:31]:

    拜托    纯洁的人还怕 玷污阿

    [9:31]:

    这话说的……,那谁怕玷污?

    [9:32]:

    大家都不怕   纯洁的人   再怎么诱惑也玷污不了  像我这种流氓么   都能专门去玷污纯洁的人了  

    [9:33]:

    我要保留证据,等我思想被玷污了之后,我妈问起,我也好找理由

    [9:34]:

    看来你还真不是纯洁的料   随便两下就倒戈了

    [9:34]:

    就是太纯洁了,稍微来点颜色就被玷污

    [9:35]:

    懂不?头脑简单四肢发达的流氓

    [9:35]:

    阿呀呀    你现在已经不纯洁了   已经被我玷污了   hoho

    [9:35]:

    还是有那么一点纯洁的,对比的情况下

    [9:36]:

    不用对比了    还往自己脸上贴金

    [9:36]:

    不用贴,那感和您老比,流氓的祖师爷

    [9:37]:

    我还是比你年轻滴     祖祖师爷

    [9:38]:

    你厉害阿,我白活20年了,功力比你小多了

    [9:38]:

    不要这么谦虚么    我会害羞滴

    [9:38]:

    你还害羞 得了吧

281/212>
Open Toolbar