posts - 9, comments - 4, trackbacks - 0, articles - 9

2011年1月19日

protected void Page_Load(object sender, EventArgs e)
    {
        this.Calendar1.Attributes.Add("style", "display:none;border-width:1px;border-style:solid;border-collapse:collapse;z-index: 100; left: 0px;");
        TextBox1.Attributes.Add("onfocus", "javascript:document.getElementById('Calendar1').style.display=''");
    }
    protected void Calendar1_SelectionChanged(object sender, EventArgs e)
    {
        TextBox1.Text = this.Calendar1.SelectedDate.ToShortDateString();
        Calendar1.Attributes.Add("onblur", "javascript:document.getElementById('Calendar1').style.display='none'");
    }
    protected void Button1_Click(object sender, EventArgs e)
    {
        Console.Write(this.TextBox1.Text);

posted @ 2011-01-19 22:40 xlz 阅读(623) | 评论 (1)编辑 收藏

2009年3月17日

        什么是软交换?在询问这样的问题时,我们经常会得到一系列特征的描述:它是NGN的核心,它具有开放的架构,它能够实现呼叫控制与媒体传输分离……

        思科系统亚太区NGN/VoIP首席技术顾问殷康认为,尽管“软交换”是目前NGN讨论的热点,但是人们对它的概念仍然有些似是而非。他说:“‘软交换’这个术语可以说是从Softswitch翻译而得。Softswitch这一术语借用了传统电信领域PSTN网中的‘硬’交换机‘switch’的概念,所不同的是强调其基于分组网上呼叫控制与媒体传输承载相分离的含义。国内一开始有人将Softswitch译为‘软交换’。但是‘软交换’这个翻译术语含义不够十分明晰,单从字面上看很难使人理解它究竟是设备系统概念还是体系概念。”

        殷康指出,我国电信业历来将名词属性的、设备概念范畴的switch译为“交换机”,而将动名词属性的switching译为“交换”。X25switch译为X25交换机,ATMswitch译为ATM交换机,L2/L3 switch 译为二层/三层交换机。因此他建议,为学术研讨的严肃性, 应该将softswitch更为确切地译为“软交换机”。这只是翻译概念上的问题。不过从某一方面来说,对于软交换概念的模糊,也反映了产业界对于软交换认识上在某些方面依旧存在偏差,存在着过分强调某一方面的能力,或者是过分夸大了软交换功能的情况。甚至可以说在很长的一段时间,软交换被人为地“神话”了,它被认为是一种代表着通信行业的未来,似乎无所不能的技术。

        软交换是一种正在发展的概念,包含许多功能。其核心是一个采用标准化协议和应用编程接口(API)的开放体系结构。这就为第三方开发新应用和新业务敞开了大门。软交换体系结构的其它重要特性还包括应用分离(de-couplingofapplications)、呼叫控制和承载控制。

        软交换是一种功能实体,为下一代网络NGN提供具有实时性要求的业务的呼叫控制和连接控制功能,是下一代网络呼叫与控制的核心。

        简单地看,软交换是实现传统程控交换机的“呼叫控制”功能的实体,但传统的“呼叫控制”功能是和业务结合在一起的,不同的业务所需要的呼叫控制功能不同,而软交换是与业务无关的,这要求软交换提供的呼叫控制功能是各种业务的基本呼叫控制。

posted @ 2009-03-17 09:58 xlz 阅读(443) | 评论 (0)编辑 收藏

        支持大本地网(虚拟MSC)组网 MSCServer集中放置在一个大区域(可以由现网的几个地区构成,每个地区分配一个虚拟的MSC号码)的中心,将MGW拉远,下放到各PSTN本地网(每个地区),采取集中控制、就近接入的方法组建一个大本地网,但提供的业务与现在的多个本地网没有区别,同样支持多区号、各区间漫游及漫游限制以及区间话统及计费,对其它网元来说,完全相当于多个传统的本地网。可以很好地满足“大容量,少局所”的运营要求,有利于提高运维质量,便于移动新业务的开展。   
     
        支持双归属网络容灾 一个或多个MGW同时连接到两个MSCServer上,这两个SERVER互为备份关系,正常情况下两个MSCServer可以是负荷分担的,也可以是完全主备方式提供业务。当其中一个MSCServer故障时,另一个MSCServer能够立即接管故障MSCServer上的话务,能完成人工或自动倒换。从而极大地提高大容量系统容灾的能力。这种双归属网络容灾方案在中国移动T1局获得应用。

posted @ 2009-03-17 09:54 xlz 阅读(508) | 评论 (0)编辑 收藏

2009年3月13日

 

优先级

运算符

名称或含义

使用形式

结合方向

说明

1

[]

数组下标

数组名[常量表达式]

左到右


()

圆括号

(表达式)/函数名(形参表)


.

成员选择(对象)

对象.成员名


->

成员选择(指针)

对象指针->成员名


2

-

负号运算符

-表达式

右到左

单目运算符

(类型)

强制类型转换

(数据类型)表达式


++

自增运算符

++变量名/变量名++

单目运算符

--

自减运算符

--变量名/变量名--

单目运算符

*

取值运算符

*指针变量

单目运算符

&

取地址运算符

&变量名

单目运算符

!

逻辑非运算符

!表达式

单目运算符

~

按位取反运算符

~表达式

单目运算符

sizeof

长度运算符

sizeof(表达式)


3

/

表达式/表达式

左到右

双目运算符

*

表达式*表达式

双目运算符

%

余数(取模)

整型表达式/整型表达式

双目运算符

4

+

表达式+表达式

左到右

双目运算符

-

表达式-表达式

双目运算符

5

<<

左移

变量<<表达式

左到右

双目运算符

>>

右移

变量>>表达式

双目运算符

6

>

大于

表达式>表达式

左到右

双目运算符

>=

大于等于

表达式>=表达式

双目运算符

<

小于

表达式<表达式

双目运算符

<=

小于等于

表达式<=表达式

双目运算符

7

==

等于

表达式==表达式

左到右

双目运算符

!=

不等于

表达式!= 表达式

双目运算符

8

&

按位与

表达式&表达式

左到右

双目运算符

9

^

按位异或

表达式^表达式

左到右

双目运算符

10

|

按位或

表达式|表达式

左到右

双目运算符

11

&&

逻辑与

表达式&&表达式

左到右

双目运算符

12

||

逻辑或

表达式||表达式

左到右

双目运算符

13

?:

条件运算符

表达式1? 表达式2: 表达式3

右到左

三目运算符

14

=

赋值运算符

变量=表达式

右到左


/=

除后赋值

变量/=表达式


*=

乘后赋值

变量*=表达式


%=

取模后赋值

变量%=表达式


+=

加后赋值

变量+=表达式


-=

减后赋值

变量-=表达式


<<=

左移后赋值

变量<<=表达式


>>=

右移后赋值

变量>>=表达式


&=

按位与后赋值

变量&=表达式


^=

按位异或后赋值

变量^=表达式


|=

按位或后赋值

变量|=表达式


15

,

逗号运算符

表达式,表达式,…

左到右

从左向右顺序运算

说明:

同一优先级的运算符,运算次序由结合方向所决定。

posted @ 2009-03-13 13:27 xlz 阅读(277) | 评论 (0)编辑 收藏

2009年3月11日

 

memest原型 (please type "man memset" in your shell) 

 void *memset(void *s,  int c, size_t n); 

memset:作用是在一段内存块中填充某个给定的值,它对较大的结构体或数组进行清零操作的一种最快方法。

常见的三种错误

第一: 搞反了c 和 n的位置. 

一定要记住 如果要把一个char a[20]清零, 一定是 memset(a, 0, 20) 
而不是 memset(a, 20,  0) 

第二: 过度使用memset, 我想这些程序员可能有某种心理阴影, 他们惧怕未经初始化的内存, 所以他们会写出这样的代码: 

char buffer[20]; 

memset(buffer, 0, sizeof((char)*20)); 
strcpy(buffer, "123"); 

这里的memset是多余的. 因为这块内存马上就被覆盖了, 清零没有意义. 

第三: 其实这个错误严格来讲不能算用错memset, 但是它经常在使用memset的场合出现 

int some_func(struct something *a){ 
 … 
 … 
 memset(a, 0, sizeof(a)); 
 … 

:为何要用memset置零?memset( &Address, 0, sizeof(Address));经常看到这样的用法,其实不用的话,分配数据的时候,剩余的空间也会置零的。

答:1.如果不清空,可能会在测试当中出现野值。 你做下面的试验看看结果() 

char buf[5]; 

CString str,str1; //memset(buf,0,sizeof(buf)); for(int i = 0;i<5;i++) { str.Format(“%d “,buf[i]); str1 +=str ; } TRACE(“%s\r\n“,str1)

2.其实不然!特别是对于字符指针类型的,剩余的部分通常是不会为0的,不妨作一个试验,定义一个字符数组,并输入一串字符,如果不用memset实现清零,使用MessageBox显示出来就会有乱码(0表示NULL,如果有,就默认字符结束,不会输出后面的乱码)

问:

如下demo是可以的,能把数组中的元素值都设置成字符1
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
    char a[5];
    memset(a,'1',5);
    for(int i = 0;i < 5;i++)
      cout<<a[i]<<"  ";
    system("pause");
    return 0;
}
而,如下程序想吧数组中的元素值设置成1,却是不可行的
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
    int a[5];
    memset(a,1,5);//这里改成memset(a,1,5 *sizeof(int))也是不可以的
    for(int i = 0;i < 5;i++)
      cout<<a[i]<<"  ";
    system("pause");
    return 0;
}
问题是:

1,第一个程序为什么可以,而第二个不行,
2,不想要用for,或是while循环来初始化int a[5];能做到吗?(有没有一个像memset()这样的函数初始化)

答:

1.因为第一个程序的数组a是字符型的,字符型占据内存大小是1Byte,而memset函数也是以字节为单位进行赋值的,所以你输出没有问题。而第二个程序a是整型的,使用memset还是按字节赋值,这样赋值完以后,每个数组元素的值实际上是0x01010101即十进制的16843009。你看看你输出结果是否这样? 

2.如果用memset(a,1,20);
就是对a指向的内存的20个字节进行赋值,每个都用ASCII为1的字符去填充,转为二进制后,1就是00000001,占一个字节。一个INT元素是4字节,合一起就是1000000010000000100000001,就等于16843009,就完成了对一个INT元素的赋值了。

 

posted @ 2009-03-11 00:14 xlz 阅读(258) | 评论 (0)编辑 收藏

2009年3月10日

     摘要: 1、   用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)     #define  SECONDS_PER_YEAR  (60 * 60 * 24 * 365)UL     1) #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等) ...  阅读全文

posted @ 2009-03-10 21:35 xlz 阅读(235) | 评论 (0)编辑 收藏

2009年2月11日

#include<stdio.h>
int atoi(const char *str)
{
    int value=0;
    bool b_plus=true; //判断符号

    switch(*str) //过滤符号

    {
    case '+':
        str++;
        break;
    case '-':
        b_plus=false;
        str++;
        break;
    default:
        break;
    }

    while('\0' != *str)
    {
        value = (value*10)+(*str-'0');
        str++;
    }
    if(!b_plus)
        value=-value;
    return value;
}

void main()
{
    char str[]="-999";
    int value=atoi(str);
    printf("The result is:%d\n",value);
}

 

(2)itoa的实现:

#include<stdio.h>
void itoa(int value, char *str)
{
    if (value < 0) //如果是负数,则str[0]='-',并把value取反(变成正整数)

    {
        str[0] = '-';
        value = 0-value;
    }
    int i,j;
    for(i=1; value > 0; i++,value/=10) //从value[1]开始存放value的数字字符,不过是逆序,等下再反序过来

        str[i] = value%10+'0'; //将数字加上0的ASCII值(即'0')就得到该数字的ASCII值

    for(j=i-1,i=1; j-i>=1; j--,i++) //将数字字符反序存放

    {
        str[i] = str[i]^str[j];
        str[j] = str[i]^str[j];
        str[i] = str[i]^str[j];
    }
    if(str[0] != '-') //如果不是负数,则需要把数字字符下标左移一位,即减1

    {
        for(i=0; str[i+1]!='\0'; i++)
            str[i] = str[i+1];
        str[i] = '\0';
    }
}

void main()
{
    int value = -1212345;
    char str[10] = {'\0'}; //记得把str全填充为'\0'

    itoa(value, str);
    printf("The result is:%s\n", str);
}

posted @ 2009-02-11 16:22 xlz 阅读(3195) | 评论 (1)编辑 收藏

题目:
    已知strcpy函数的原型是:
        char * strcpy(char * strDest,const char * strSrc);
    1.不调用库函数,实现strcpy函数。
    2.解释为什么要返回char *。

    解说:
    1.strcpy的实现代码


        char * strcpy(char * strDest,const char * strSrc)
        {
                if ((strDest==NULL)||(strsrc="/=NULL")) //[1]
                        throw "Invalid argument(s)"; //[2]
                char * strDestCopy=strDest;  //[3]
                while ((*strDest++=*strSrc++)!='\0'); //[4]
                return strDestCopy;
        }

    错误的做法:
    [1]
    (A)不检查指针的有效性,说明答题者不注重代码的健壮性。
    (B)检查指针的有效性时使用((!strDest)||(!strSrc))或(!(strDest&&strSrc)),说明答题者对C语言中类型的隐式转换没有深刻认识。在本例中char *转换为bool即是类型隐式转换,这种功能虽然灵活,但更多的是导致出错概率增大和维护成本升高。所以C++专门增加了bool、true、false三个关键字以提供更安全的条件表达式。
    (C)检查指针的有效性时使用((strDest==0)||(strsrc="/=0")),说明答题者不知道使用常量的好处。直接使用字面常量(如本例中的0)会减少程序的可维护性。0虽然简单,但程序中可能出现很多处对指针的检查,万一出现笔误,编译器不能发现,生成的程序内含逻辑错误,很难排除。而使用NULL代替0,如果出现拼写错误,编译器就会检查出来。
    [2]
    (A)return new string("Invalid argument(s)");,说明答题者根本不知道返回值的用途,并且他对内存泄漏也没有警惕心。从函数中返回函数体内分配的内存是十分危险的做法,他把释放内存的义务抛给不知情的调用者,绝大多数情况下,调用者不会释放内存,这导致内存泄漏。
    (B)return 0;,说明答题者没有掌握异常机制。调用者有可能忘记检查返回值,调用者还可能无法检查返回值(见后面的链式表达式)。妄想让返回值肩负返回正确值和异常值的双重功能,其结果往往是两种功能都失效。应该以抛出异常来代替返回值,这样可以减轻调用者的负担、使错误不会被忽略、增强程序的可维护性。
    [3]
    (A)忘记保存原始的strDest值,说明答题者逻辑思维不严密。
    [4]
    (A)循环写成while (*strDest++=*strSrc++);,同[1](B)。
    (B)循环写成while (*strSrc!='\0') *strDest++=*strSrc++;,说明答题者对边界条件的检查不力。循环体结束后,strDest字符串的末尾没有正确地加上'\0'。

    2.返回strDest的原始值使函数能够支持链式表达式,增加了函数的“附加值”。同样功能的函数,如果能合理地提高的可用性,自然就更加理想。
    链式表达式的形式如:
        int iLength=strlen(strcpy(strA,strB));
    又如:
        char * strA=strcpy(new char[10],strB);
    返回strSrc的原始值是错误的。其一,源字符串肯定是已知的,返回它没有意义。其二,不能支持形如第二例的表达式。其三,为了保护源字符串,形参用const限定strSrc所指的内容,把const char *作为char *返回,类型不符,编译报错。

posted @ 2009-02-11 14:10 xlz 阅读(8608) | 评论 (2)编辑 收藏

2009年1月4日

摘 要:本文讨论了Oracle和SQL Server的在事务处理上的区别,并分析了其实现机制的差异。

关键词:Oracle;SQL Server;事务;事务隔离级别;DDL。


事务处理是所有大型数据库产品的一个关键问题,各数据库厂商都在这个方面花费了很大精力,不同的事务处理方式会导致数据库性能和功能上的巨大差异。

事务处理也是数据库管理员与数据库应用程序开发人员必须深刻理解的一个问题,对这个问题的疏忽可能会导致应用程序逻辑错误以及效率低下。

下面我们针对Oracle及SQL Server这两种当前广泛使用的大型数据库产品,探讨一下它们在事务处理方面的一些差异。如没有特殊说明,本文内容适用的数据库产品版本为Oracle9i及SQL Server 2000,其中的示例SQL语句,对于Oracle是在SQL*Plus中执行,而对于SQL Server 2000是在osql中执行。
一.事务的概念

事务可以看作是由对数据库的若干操作组成的一个单元,这些操作要么都完成,要么都取消,从而保证数据满足一致性的要求。事务的一个典型例子是银行中的转帐操作,帐户A把一定数量的款项转到帐户B上,这个操作包括两个步骤,一个是从帐户A上把存款减去一定数量,二是在帐户B上把存款加上相同的数量。这两个步骤显然要么都完成,要么都取消,否则银行就会受损失。显然,这个转帐操作中的两个步骤就构成一个事务。

数据库中的事务还有如下ACID特征。

ACID分别是四个英文单词的首写字母,这四个英文单词是Atomicity、Consistency、Isolation、Durability,分别翻译为原子性、一致性、隔离性、持久性。

原子性:指事务中的操作,或者都完成,或者都取消。

一致性:指事务中的操作保证数据库中的数据不会出现逻辑上不一致的情况,一致性一般会隐含的包括在其他属性之中。

隔离性:指当前的事务与其他未完成的事务是隔离的。在不同的隔离级别下,事务的读取操作,可以得到的结果是不同的。

持久性:指对事务发出COMMIT命令后,即使这时发生系统故障,事务的效果也被持久化了。与此相反的是,当在事务执行过程中,系统发生故障,则事务的操作都被回滚,即数据库回到事务开始之前的状态。

对数据库中的数据修改都是在内存中完成的,这些修改的结果可能已经写到硬盘也可能没有写到硬盘,如果在操作过程中,发生断电或系统错误等故障,数据库可以保证未结束的事务对数据库的数据修改结果即使已经写入磁盘,在下次数据库启动后也会被全部撤销;而对于结束的事务,即使其修改的结果还未写入磁盘,在数据库下次启动后会通过事务日志中的记录进行“重做”,即把丢失的数据修改结果重新生成,并写入磁盘,从而保证结束事务对数据修改的永久化。这样也保证了事务中的操作要么全部完成,要么全部撤销。

二.事务设置及类型的区别

在SQL Server中有三种事务类型,分别是:隐式事务、显式事务、自动提交事务,缺省为自动提交。

自动提交,是指对于用户发出的每条SQL语句,SQL Server都会自动开始一个事务,并且在执行后自动进行提交操作来完成这个事务,也可以说在这种事务模式下,一个SQL语句就是一个事务。

显式事务,是指在自动提交模式下以Begin Transaction开始一个事务,以Commit或Rollback结束一个事务,以Commit结束事务是把事务中的修改永久化,即使这时发生断电这样的故障。例如下面是SQL Server中的一个显式事务的例子。

Begin Tran

Update emp Set ename=’Smith’ Where empno=7369

Insert Into dept Values(60,’HR’,’GZh’)

Commit

隐式事务,是指在当前会话中用Set Implicit_Transactions On命令设置的事务类型,这时任何DML语句(Delete、Update、Insert)都会开始一个事务,而事务的结束也是用Commit或Rollback。

在Oracle中没有SQL Server的这些事务类型,缺省情况下任何一个DML语句都会开始一个事务,直到用户发出Commit或Rollback操作,这个事务才会结束,这与SQL Server的隐式事务模式相似。

三.事务隔离级别

在SQL92标准中,事务隔离级别分为四种,分别为:Read Uncommitted、Read Committed、Read Repeatable、Serializable,其中Read Uncommitted与Read Committed为语句级别的,而Read Repeatable与Serializable是针对事务级别的。

在Oracle和SQL Server中设置事务隔离级别的语句是相同的,都使用SQL92标准语法,即:

Set Transaction Isolation Level Read Committed

上面示例中的Read Committed可以被替换为其他三种隔离级别中的任意一种。

1.SQL Server中的隔离级别及实现机制

在SQL Server中提供了所有这四种隔离级别。

下面我们讨论在SQL Server中,这几种隔离级别的含义及其实现方式。

Read Uncommitted:一个会话可以读取其他事务未提交的更新结果,如果这个事务最后以回滚结束,这时的读取结果就可能是错误的,所以多数的数据库应用都不会使用这种隔离级别。

Read Committed:这是SQL Server的缺省隔离级别,设置为这种隔离级别的事务只能读取其他事务已经提交的更新结果,否则,发生等待,但是其他会话可以修改这个事务中被读取的记录,而不必等待事务结束,显然,在这种隔离级别下,一个事务中的两个相同的读取操作,其结果可能不同。

Read Repeatable:在一个事务中,如果在两次相同条件的读取操作之间没有添加记录的操作,也没有其他更新操作导致在这个查询条件下记录数增多,则两次读取结果相同。换句话说,就是在一个事务中第一次读取的记录保证不会在这个事务期间发生改变。SQL Server是通过在整个事务期间给读取的记录加锁实现这种隔离级别的,这样,在这个事务结束前,其他会话不能修改事务中读取的记录,而只能等待事务结束,但是SQL Server不会阻碍其他会话向表中添加记录,也不阻碍其他会话修改其他记录。

Serializable:在一个事务中,读取操作的结果是在这个事务开始之前其他事务就已经提交的记录,SQL Server通过在整个事务期间给表加锁实现这种隔离级别。在这种隔离级别下,对这个表的所有DML操作都是不允许的,即要等待事务结束,这样就保证了在一个事务中的两次读取操作的结果肯定是相同的。

2.Oracle中的隔离级别及实现机制

在Oracle中,没有Read Uncommitted及Repeatable Read隔离级别,这样在Oracle中不允许一个会话读取其他事务未提交的数据修改结果,从而避免了由于事务回滚发生的读取错误。Oracle中的Read Committed和Serializable级别,其含义与SQL Server类似,但是实现方式却大不一样。

在Oracle中,存在所谓的回滚段(Oracle9i之前版本)或撤销段(Oracle9i版本),Oracle在修改数据记录时,会把这些记录被修改之前的结果存入回滚段或撤销段中,就是因为这种机制,Oracle对于事务隔离级别的实现与SQL Server截然不同。在Oracle中,读取操作不会阻碍更新操作,更新操作也不会阻碍读取操作,这样在Oracle中的各种隔离级别下,读取操作都不会等待更新事务结束,更新操作也不会因为另一个事务中的读取操作而发生等待,这也是Oracle事务处理的一个优势所在。

Oracle缺省的设置是Read Committed隔离级别(也称为语句级别的隔离),在这种隔离级别下,如果一个事务正在对某个表进行DML操作,而这时另外一个会话对这个表的记录进行读取操作,则Oracle会去读取回滚段或撤销段中存放的更新之前的记录,而不会象SQL Server一样等待更新事务的结束。

在Serializable隔离级别(也称为事务级别的隔离),事务中的读取操作只能读取这个事务开始之前已经提交的数据结果。如果在读取时,其他事务正在对记录进行修改,则Oracle就会在回滚段或撤销段中去寻找对应的原来未经更改的记录(而且是在读取操作所在的事务开始之前存放于回滚段或撤销段的记录),这时读取操作也不会因为相应记录被更新而等待。

四.DDL语句对事务的影响

1.Oracle中DDL语句对事务的影响

在Oracle中,执行DDL语句(如Create Table、Create View等)时,会在执行之前自动发出一个Commit命令,并在随后发出一个Commit或者Rollback命令,也就是说,DDL会象如下伪码一样执行:

Commit;

DDL_Statement;

If (Error) then

Rollback;

Else

Commit;

End if;

我们通过分析下面例子来看Oracle中,DDL语句对事务的影响:

Insert into some_table values(‘Before’);

Creaate table T(x int);

Insert into some_table values(‘After’);

Rollback;

由于在Oracle执行Create table语句之前进行了提交,而在Create table执行后也会自动发出Commit命令,所以只有插入After的行被回滚,而插入Before的行不会被回滚,Create table命令的结果也不会被回滚,即使Create table语句失败,所进行的Before插入也会被提交。如果最后发出Commit命令,因为插入Before及Create table的操作结果已经在之前提交,所以Commit命令影响的只有插入After的操作。

2.SQL Server中DDL语句对事务的影响

在SQL Server中,DDL语句对事务的影响与其他DML语句相同,也就是说,在DML语句发出之前或之后,都不会自动发出Commit命令。

在SQL Server 2000中,对于与上面Oracle同样的例子,最后发出Rollback后,数据库会回滚到插入Before之前的状态,即插入Before和After的行都会被回滚,数据表T也不会被创建。

如果最后发出Commit操作,则会把三个操作的结果全部提交。

五.用户断开数据库连接对事务的影响

另外,对应于Oracle的管理客户端工具SQL*Plus,在SQL Server 2000中是osql,两种管理工具都是命令行工具,使用方式及作用也类似,但是在SQL*Plus中,用户退出连接时,会自动先发出Commit命令,然后再退出,而在osql中,如果用户退出连接,会自动发出Rollback命令,这对于SQL Server的自动提交模式没有什么影响,但如果处于隐式事务模式,其影响是显而易见的。对于两种数据库产品的其他客户端管理工具也有类似的不同之处。

posted @ 2009-01-04 01:11 xlz 阅读(371) | 评论 (0)编辑 收藏