分享
 
 
 

把Oracle数据库移植到Microsoft SQL Server 7.0(2)

王朝oracle·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

在Oracle中,REFERENCES特权只能授予用户。SQL Server则允许把该特权授予数据库用户和数据库组。INSERT、UPDATE、DELETE和SELECT特权的授予在Oracle和SQL Server中以同样的方式处理。

加强数据完整性和商业规则加强数据完整性确保数据库中数据的质量。规划表时重要的两个步骤是鉴定列中值的有效性和如何加强列中数据的完整性。数据完整性可以分为四类,它们是以不同的方式进行加强的。

完整性类型

如何强制

Entity integrity

PRIMARY KEY constraint

UNIQUE constraint

IDENTITY property

Domain integrity

Domain DEFAULT definition

FOREIGN KEY constraint

CHECK constraint

Nullability

Referential integrity

Domain DEFAULT definition

FOREIGN KEY constraint

CHECK constraint

Nullability

User-defined integrity

All column- and table-level constraints in CREATE TABLE

Stored procedures

Triggers

实体完整性(Entity Integrity)

实体完整性把特定表中的一行作为一个唯一的实体加以定义。实体完整性通过索引、UNIQUE约束、PRIMARY KEY约束或者IDENTITY特性加强表中标识列或者主关键字的完整性,

为约束命名

你总是可以显式的命名你的约束。如果你不这样做,Oracle和Microsoft SQL Server将使用不同的命名惯例来隐式的为约束命名。在命名上的不同会为你的移植带来不必要的麻烦。在删除约束或者使约束失效时将会出现问题,因为约束必须通过名字来删除。显式命名约束的语法在Oracle和SQL Server中是一样的。

CONSTRAINT constraint_name

主键和唯一列

SQL-92标准要求主关键字中的所有值都是唯一的并且该列不允许空值。Oracle和Microsoft SQL Server都是通过自动创建唯一的索引这种方式来强制实现唯一性的,无论是否定义了PRIMARY KEY或者UNIQUE约束。

虽然可以创建一个未分簇的索引,但是SQL Server缺省的为主关键字创建一个分簇的索引。Oracle在主关键字上的索引可以通过删除约束或者使约束失效的方法来清除,而SQL Server的索引只能通过删除约束来实现。

无论在哪种RDBMS中,其他关键字都可以定义一个UNIQUE约束。可以在任何表中定义多个UNIQUE约束。UNIQUE约束列可以为空。在SQL Server中,除非另外说明,否则将缺省的创建一个未分簇的索引

在移植你的应用程序时,重要的是注意到SQL Server只允许完全唯一的关键字(单个或者多个列索引)中有一行是NULL值的,而Oracle则允许完全唯一的关键字中任意行是NULL值。

Oracle

Microsoft SQL

CREATE TABLE DEPT_ADMIN.DEPT

(DEPT VARCHAR2(4) NOT NULL,

DNAME VARCHAR2(30) NOT NULL,

CONSTRAINT DEPT_DEPT_PK

PRIMARY KEY (DEPT)

USING INDEX TABLESPACE

USER_DATA

PCTFREE 0 STORAGE (

INITIAL 10K NEXT 10K

MINEXTENTS 1 MAXEXTENTS UNLIMITED),

CONSTRAINT DEPT_DNAME_UNIQUE

UNIQUE (DNAME)

USING INDEX TABLESPACE USER_DATA

PCTFREE 0 STORAGE (

INITIAL 10K NEXT 10K

MINEXTENTS 1 MAXEXTENTS

UNLIMITED)

)

CREATE TABLE USER_DB.DEPT_ADMIN.DEPT

(DEPTVARCHAR(4) NOT NULL,

DNAMEVARCHAR(30) NOT NULL,

CONSTRAINT DEPT_DEPT_PK

PRIMARY KEY CLUSTERED (DEPT),

CONSTRAINT DEPT_DNAME_UNIQUE

UNIQUE NONCLUSTERED (DNAME)

)

增加和清除约束

使约束失效可以改善数据库性能,并且使数据复制过程更加流畅。例如,当你在一个远程站点上重建或者复制表中的数据时,你不用重复约束检查,因为数据的完整性是在它原来输入数据库时就检查过的。你可以编制Oracle应用程序来使能或者失效约束(除了PRIMARY KEY和UNIQUE)。你可以在Microsoft SQL Server的ALTER TABLE语句中使用CHECK和WITH NOCHECK来达到同样的目的。

下面的插图显示了该过程的比较。

在SQL Server中,你在NOCHECK子句上使用ALL关键字来推迟所有的表的约束。

如果你的Oracle应用程序使用CASCADE选项来失效或者删除PRIMARY KEY或者UNIQUE约束,你也许需要重写某些代码,因为CASCADE选项同时失效或者删除父类和子类的完整性约束。

这是关于语法的示例:

DROP CONSTRAINT DEPT_DEPT_PK CASCADE

SQL Server应用程序必须修改成首先删除子类的约束,然后删除父类的约束。例如,为了删除DEPT表上的PRIMARY KEY约束,STUDENT.MAJOR和CLASS.DEPT相关列的外部关键字必须被删除。这是语法的示例:

ALTER TABLE STUDENT

DROP CONSTRAINT STUDENT_MAJOR_FK

ALTER TABLE CLASS

DROP CONSTRAINT CLASS_DEPT_FK

ALTER TABLE DEPT

DROP CONSTRAINT DEPT_DEPT_PK

ALTER TABLE增加和删除约束的语法在Oracle和SQL Server中的语法是一样的。

生成连续的数字值

如果你的Oracle应用程序使用SEQUENCEs,该选项可以很容易的改变以利用Microsoft SQL Server的IDENTITY特性。

类别

Microsoft SQL Server

语法

CREATE TABLE new_employees

( Empid int IDENTITY (1,1), Employee_Name varchar(60),

CONSTRAINT Emp_PK PRIMARY KEY (Empid)

)

If increment interval is 5:

CREATE TABLE new_employees

( Empid int IDENTITY (1,5), Employee_Name varchar(60),

CONSTRAINT Emp_PK PRIMARY KEY (Empid)

)

每个表拥有的标识列

一个

允许空值

使用缺省约束、值

不能使用.

强制唯一

在INSERT, SELECT INTO 或者bulk copy 语句完成以后,查询最大的当前标识数

@@IDENTITY (function)

返回创建标识列时指定的种子值

IDENT_SEED('table_name')

返回创建标识列时指定的增加值

IDENT_INCR('table_name')

SELECT语法

当在SELECT, INSERT, UPDATE, 和DELETE语句中引用带有IDENTITY属性的列时,可以在列名上使用IDENTOTY关键字

虽然IDENTITY特性使一个表中的行记数自动化,但是不同的表,如果每一个都有自己的标识列,可以产生同样的值。这是因为IDENTITY特性只能在使用它的表上被担保为唯一的。如果一个应用程序必须生成一个在整个数据库,或者全世界每一台联网计算机上的每一个数据库中唯一的标识列,可以使用ROWGUIDCOL特性,uniqueidentifier数据类型,以及NEWID函数。SQL Server使用全局独立的标识列来并入复制,确保该行在所有该表的拷贝中是唯一的标识。

如果需要了解关于创建和修改标识列的更多信息,请参看SQL Server联机手册。

域完整性

域完整性约束对给定列的有效入口。域完整性是通过限制类型(通过数据类型),格式(通过CHECK约束),或者可能值的范围(通过REFERENCE和CHECK约束)来实现的。

DEFAULT和CHECK约束

Oracle把缺省(default)当作一个列属性来对待,而Microsoft SQL Server把缺省当作一个约束来对待。SQL Server的DEFAULT约束可以包含整型值,内建的不带参数的函数(niladic函数),或者NULL。

要很方便的移植Oracle的DEFAULT列属性,你应该在SQL Server中定义列级别的不使用约束名字的DEFAULT约束。SQL Server为每一个DEFAULT约束生成一个唯一的名字。

用来定义CHECK约束的语法在Oracle和SQL Server中是一样的。搜索条件应该用布尔表达式来表示而且不能包含子查询。列级别的约束只能用在被约束列上,表级别的约束只能用在被约束的表中的列上。可以为一个表定义多个CHECK约束。SQL Server语法允许在一个CREATE TABLE语句中只创建一个列级别的CHECK约束,并且该约束可以有多个条件。

测试你修改过的CREATE TABLE语句的最好方式是使用SQL Server中的SQL Server Query Analyzer,并且只分析语法。输出结果将会指出任何错误。如果需要了解关于约束语法的更多信息,请参看SQL Server联机手册。

Oracle

Microsoft SQL

CREATE TABLE STUDENT_ADMIN.STUDENT (

SSN CHAR(9) NOT NULL,

FNAME VARCHAR2(12) NULL,

LNAME VARCHAR2(20) NOT NULL,

GENDER CHAR(1) NOT NULL

CONSTRAINT

STUDENT_GENDER_CK

CHECK (GENDER IN ('M','F')),

MAJOR VARCHAR2(4)

DEFAULT 'Undc' NOT NULL,

BIRTH_DATE DATE NULL,

TUITION_PAID NUMBER(12,2) NULL,

TUITION_TOTAL NUMBER(12,2) NULL,

START_DATE DATE NULL,

GRAD_DATE DATE NULL,

LOAN_AMOUNT NUMBER(12,2) NULL,

DEGREE_PROGRAM CHAR(1)

DEFAULT 'U' NOT NULL

CONSTRAINT

STUDENT_DEGREE_CK CHECK

(DEGREE_PROGRAM IN ('U', 'M', 'P', 'D')),

...

CREATE TABLE USER_DB.STUDENT

_ADMIN.STUDENT (

SSN CHAR(9) NOT NULL,

FNAME VARCHAR(12) NULL,

LNAME VARCHAR(20) NOT NULL,

GENDER CHAR(1) NOT NULL

CONSTRAINT STUDENT_GENDER_CK

CHECK (GENDER IN ('M','F')),

MAJOR VARCHAR(4)

DEFAULT 'Undc' NOT NULL,

BIRTH_DATE DATETIME NULL,

TUITION_PAID NUMERIC(12,2) NULL,

TUITION_TOTAL NUMERIC(12,2) NULL,

START_DATE DATETIME NULL,

GRAD_DATE DATETIME NULL,

LOAN_AMOUNT NUMERIC(12,2) NULL,

DEGREE_PROGRAM CHAR(1)

DEFAULT 'U' NOT NULL

CONSTRAINT STUDENT_DEGREE_CK

CHECK

(DEGREE_PROGRAM IN ('U', 'M',

'P','D')),

...

关于用户定义规则和缺省(default)要注意:关于Microsoft SQL Server规则和缺省的语法是考虑了向后兼容的,但是建议把CHECK约束和DEFAULT约束用在新的开发中。如果需要了解更多的信息,请参看SQL Server联机手册。

Nullability

Microsoft SQL Server和Oracle创建列约束来强制nullability。在Oracle的CREATE TABLE和ALTER TABLE语句中,列缺省是NULL,而不是NOT NULL。在Microsoft SQL Server,数据库和会话的设置可以越过在列定义中使用的数据类型的nullability。

你的所有的SQL脚本(无论是Oracle还是SQL Server),都必须显明的给出每一列的NULL和NOT NULL定义。要了解这个策略是如何实现的,请参看Oracle.sql和Sstable.sql这两个示例的表创建脚本。如果没有显明的定义,则列的nullability遵循如下的规则。

Null settings

Description

列是用一个用户定义数据类型定义的

SQLServer 使用在创建数据类型时指定的空值性。使用sp_help 系统存储过程来获取数据类型的缺省的空值性

列是用一个系统提供的数据类型定义的

如果系统提供的数据类型只有一个选项,则优先使用该选项。当前, bit数据类型只能被定义为NOT NULL。

如果任何会话设置为ON (用SET打开), 则:

如果ANSI_NULL_DFLT_ON是ON, 则指定为NULL.

如果ANSI_NULL_DFLT_OFF是ON, 则指定为NOT NULL.

如果任何数据库设置被修改过(用sp_dboption 系统存储过程修改), 则:

如果ANSI null default是true, 则指定为NULL.

如果ANSI null default是false, 则指定为NOT NULL

NULL/NOT NULL

没有定义

当没有显明的定义时(ANSI_NULL_DFLT选项一个都没有设定),会话将被修改,并且数据库被设定为缺省(ANSI null default是false),然后SQLServer指定它为NOT NULL。

引用完整性

下表提供了一个用来定义referential完整性约束的语法比较。

约束

Oracle

Microsoft SQLServer

PRIMARY KEY

[CONSTRAINT constraint_name]

PRIMARY KEY (col_name [, col_name2 [..., col_name16]])

[USING INDEX storage_parameters]

[CONSTRAINT constraint_name]

PRIMARY KEY [CLUSTERED | NONCLUSTERED] (col_name [, col_name2 [..., col_name16]])

[ON segment_name]

[NOT FOR REPLICATION]

UNIQUE

[CONSTRAINT constraint_name]

UNIQUE (col_name [, col_name2 [..., col_name16]])

[USING INDEX storage_parameters]

[CONSTRAINT constraint_name]

UNIQUE [CLUSTERED | NONCLUSTERED](col_name [, col_name2 [..., col_name16]])

[ON segment_name]

[NOT FOR REPLICATION]

FOREIGN KEY

[CONSTRAINT constraint_name]

[FOREIGN KEY (col_name [, col_name2 [..., col_name16]])]

REFERENCES [owner.]ref_table [(ref_col [, ref_col2 [..., ref_col16]])]

[ON DELETE CASCADE]

[CONSTRAINT constraint_name]

[FOREIGN KEY (col_name [, col_name2 [..., col_name16]])]

REFERENCES [owner.]ref_table [(ref_col [, ref_col2 [..., ref_col16]])]

[NOT FOR REPLICATION]

DEFAULT

Column property, not a constraint

DEFAULT (constant_expression)

[CONSTRAINT constraint_name]

DEFAULT {constant_expression | niladic-function | NULL}

[FOR col_name]

[NOT FOR REPLICATION]

CHECK

[CONSTRAINT constraint_name]

CHECK (expression)

[CONSTRAINT constraint_name]

CHECK [NOT FOR REPLICATION] (expression)

NOT FOR REPLICATION子句用来在复制过程中挂起列级别,FOREIGN KEY,以及CHECK约束。

外部键

定义外部关键字的语法在各种RDBMS中都是相似的。在外部关键字中标明的列数和每一列的数据类型必须和REFERENCES子句相匹配。一个输入到列中的非空的值必须在REFERENCES子句中定义表和列中存在,并且被提及的表的列必须有一个PRIMARY KEY或者UNIQUE约束。

Microsoft SQL Server约束提供了在同一个数据库中引用表的能力。要实现在数据库范围的应用完整性,可以使用基于表的触发器。

Oracle和SQL Server都支持自引用表,这种表中有对同一个表的一列或几列的引用。例如,CLASS表中的prereq列可以引用CLASS表中的ccode列以确保一个有效的课程编号是作为一个子句的先决条件输入的。

在Oracle中实现层叠式的删除和修改是使用CASCADE DELETE子句,而SQL Server用表触发器来实现同样的功能。如果需要了解更多的信息,请参看本章后面的“SQL语言支持”部分 。

用户定义的完整性

用户定义的完整性允许你定义特定的商业规则,该规则不属于其他完整性的范畴。

存储过程

Microsoft SQL Server存储程序用CREATE PROCEDURE语句来接受或者返回用户提供的参数。除临时存储程序以外,存储程序是在当前数据库中创建的。下表显示了Oracle和SQL Server的语法。

Oracle

Microsoft SQL

CREATE OR REPLACE PROCEDURE [user.]procedure

[(argument [IN | OUT] datatype

[, argument [IN | OUT] datatype]

{IS | AS} block

CREATE PROC[EDURE] procedure_name [;number]

[

{@parameter data_type} [VARYING] [= default] [OUTPUT]

]

[,…n]

[WITH

{RECOMPILE | ENCRYPTION |

RECOMPILE, ENCRYPTION} ]

[FOR REPLICATION]

AS

sql_statement […n]

在SQL Server中,临时存储程序是在tempdb数据库中通过在procedure_name前加上数字标记来创建的。加一个数字标记(#procedure_name)表示是一个本地临时存储程序,加两个数字标记(##procedure_name)表示是一个全局临时程序。

一个本地临时程序只能被创建它的用户使用。执行本地临时程序的许可不能授予其他用户。本地临时程序在用户会话结束时自动删除。

一个全局的临时程序可以被所有的SQL Server用户使用。如果一个全局临时程序被创建了,所有的用户都可以访问它,并且不能显式的撤回许可。全局临时程序在最后一个用户会话结束的时候自动删除。

SQL Server存储程序可以有最多32级嵌套。嵌套层数在被调用的程序开始执行时增加,在被调用的程序结束运行时减少。

下面的例子说明了怎样用一个Transact-SQL存储程序来代替一个Oracle的PL/SQL封装函数。Transact-SQL的版本更简单一些,因为SQL Server的返回结果的能力是在一个存储程序中直接用SELECT语句设置的,不需要使用游标。

Oracle

Microsoft SQL

CREATE OR REPLACE PACKAGE STUDENT_ADMIN.P1 AS ROWCOUNT NUMBER :=0;

CURSOR C1 RETURN STUDENT%ROWTYPE;

FUNCTION SHOW_RELUCTANT_STUDENTS

(WORKVAR OUT VARCHAR2) RETURN NUMBER;

END P1;

/

CREATE OR REPLACE PACKAGE BODY STUDENT_ADMIN.P1 AS CURSOR C1 RETURN STUDENT%ROWTYPE IS

SELECT * FROM STUDENT_ADMIN.STUDENT

WHERE NOT EXISTS

(SELECT 'X' FROM STUDENT_ADMIN.GRADE

WHERE GRADE.SSN=STUDENT.SSN)ORDER BY SSN;

FUNCTION SHOW_RELUCTANT_STUDENTS

(WORKVAR OUT VARCHAR2) RETURN NUMBER IS

WORKREC STUDENT%ROWTYPE;

BEGIN

IF NOT C1%ISOPEN THEN OPEN C1;

ROWCOUNT :=0;

ENDIF;

FETCH C1 INTO WORKREC;

IF (C1%NOTFOUND) THEN

CLOSE C1;

ROWCOUNT :=0;

ELSE

WORKVAR := WORKREC.FNAME||' '||WORKREC.LNAME||

', social security number '||WORKREC.SSN||' is not enrolled

in any classes!';

ROWCOUNT := ROWCOUNT + 1;

ENDIF;

RETURN(ROWCOUNT);

CREATE PROCEDURE

STUDENT_ADMIN.SHOW_

RELUCTANT_STUDENTS

AS SELECT FNAME+'' +LNAME+', social security number'+ SSN+' is not enrolled in any classes!'

FROM STUDENT_ADMIN.STUDENT S

WHERE NOT EXISTS

(SELECT 'X' FROM STUDENT_ADMIN.GRADE G

WHERE G.SSN=S.SSN)

ORDER BY SSN

RETURN@@ROWCOUNT

GO

EXCEPTION

WHEN OTHERS THEN

IF C1%ISOPEN THEN CLOSE C1;

ROWCOUNT :=0;

ENDIF;

RAISE_APPLICATION_ERROR(-20001,SQLERRM);

END SHOW_RELUCTANT_STUDENTS;

END P1;

/

SQL Server不支持与Oracle包或者函数相似的构造,也不支持在创建存储程序时的CREATE OR REPLACE选项。

延迟存储过程的执行

Microsoft SQL Server提供了WAITFOR,允许开发人员给定一个时间,时间段,或者事件来触发一个语句块、存储程序或者事务的执行。这是Transact-SQL对于Oracle中dbms_lock_sleep的等价。

WAITFOR {DELAY 'time' | TIME 'time'}

指示Microsoft SQL Server等待直到给定的时间过去以后再执行,最多可以到24小时。

在这里

DELAY

指示Microsoft SQL Server等待,直到给定数量的时间过去以后才执行,最多可以设置到24小时。

'time'

需要等待的时间,时间可以是任何可接受的datetime数据类型的格式,或者可以作为一个本地变量给出。但是,不能指定datetime值的日期部分。

TIME

指示SQL Server等到指定的时间

例如:

BEGIN

WAITFOR TIME '22:20'

EXECUTE update_all_stats

END

指定存储程序中的参数

要在一个存储程序中指定一个参数,可以使用下面给出的语法。

Oracle

Microsoft SQL

Varname datatype

DEFAULT <value>;

{@parameter data_type} [VARYING]

[= default] [OUTPUT]

触发器(Triggers)

Oracle和Microsoft SQL Server都有触发器,但它们在执行上有些不同。

描述

Oracle

Microsoft SQLServer

每表可以有的触发器数

无限制

无限制

在INSERT, UPDATE, DELETE之前执行触发器

在INSERT, UPDATE, DELETE之后执行触发器

语句级触发器

行级触发器

在执行之前检查约束

是,除非触发器被取消

是。另外,这是DTS(Data Transformation Services)中的一个选项

在一个UPDATE或者DELETE触发器中提交旧的或者以前的值

:old

DELETED.column

在INSERT触发器中提交新值

:new

INSERTED.column

取消触发器

ALTER TRIGGER

DTS中的选项

DELETED和INSERTED是SQL Server为触发器创建的概念上的表。该表在结构上同触发器定义于其上的表相似,并且保存了可能被用户的行动改变的旧的或者新的行中的值。该表将跟踪在Transact-SQL中的行一级的变化。这些表提供了与Oracle中的行级别的触发器同样的功能。当一个INSERT、UPDATE、或者DELETE语句在SQL Server中执行的时候,行被加入到触发器表中,而且是同时加入到INSERTED和DELETED表中。

INSERTED和DELETED表同触发器表是一样的。它们有同样的列名和数据类型。例如,如果在GRADE表中放置一个触发器,那么INSERTED和DELETED就有这样的结构。

GRADE

INSERTED

DELETED

SSN CHAR(9)

CCODE VARCHAR(4)

GRADE VARCHAR(2)

SSN CHAR(9)

CCODE VARCHAR(4)

GRADE VARCHAR(2)

SSN CHAR(9)

CCODE VARCHAR(4)

GRADE VARCHAR(2)

INSERTED和DELETED表可以被触发器检查以确定要执行什么样的触发器行动。INSERTED表同INSERT和UPDATE语句一起使用。DELETED表则和DELETE以及UPDATE语句一起使用。

UPDATE语句使用INSERTED和DELETED表,这是因为进行UPDATE操作时,SQL Server总是要删除旧的行,填入新的行。因此,执行UPDATE时,INSERTED表中的行总是DELETED表中的行的副本。

下面的例子使用INSERTED和DELETED表来代替PL/SQL中的行级别的触发器。一个完全的外部接合点被用来查询任意表中的所有行。

Oracle

Microsoft SQLServer

CREATE TRIGGER STUDENT_ADMIN.TRACK_GRADES

AFTER

INSERT OR UPDATE OR DELETE

ON STUDENT_ADMIN.GRADE

FOR EACH ROW

BEGIN

INSERT INTO GRADE_HISTORY(

TABLE_USER, ACTION_DATE,

OLD_SSN, OLD_CCODE,

OLD_GRADE, NEW_SSN,

NEW_CCODE, NEW_GRADE)

VALUES (USER, SYSDATE,

:OLD.SSN, :OLD.CCODE,

:OLD.GRADE, :NEW.SSN,

:NEW.CCODE, :NEW.GRADE),

END;

CREATE TRIGGER STUDENT_ADMIN.TRACK_GRADES

ON STUDENT_ADMIN.GRADE

FOR INSERT, UPDATE, DELETE

AS

INSERT INTO GRADE_HISTORY(

TABLE_USER, ACTION_DATE,

OLD_SSN, OLD_CCODE, OLD_GRADE

NEW_SSN, NEW_CCODE, NEW_GRADE)

SELECT USER, GETDATE(),

OLD.SSN, OLD.CCODE, OLD.GRADE,

NEW.SSN, NEW.CCODE, NEW.GRADE

FROM INSERTED NEW FULL OUTER JOIN

DELETED OLD ON NEW.SSN = OLD.SSN

你可以只在当前数据库中创建一个触发器,你也可以引用当前数据库之外的对象。如果你使用所有者名称来修饰触发器,那么就用同样的方法来修饰表名。

触发器可以最多嵌套32级。如果一个触发器改变了某个表,而该表有另外一个触发器,则第二个触发器是活动的,可以调用第三个触发器,如此类推。如果链上的任何触发器引起了死循环,则嵌套级别溢出,该触发器被取消。此外,如果某表结果上的一行上的一个更新触发器同时是另一行的更新,那么更新触发器将只执行一次。

Microsoft SQL Server的公布引用完整性(declarative referential integrity,DRI)没有提供跨数据库的引用完整性定义。如果需要跨数据库的完整性,可以使用触发器。

下面的语句在Transact-SQL触发器中是不被允许的。

CREATE 语句(DATABASE, TABLE, INDEX, PROCEDURE, DEFAULT, RULE, TRIGGER, SCHEMA, 和VIEW)

DROP 语句(TRIGGER, INDEX, TABLE, PROCEDURE, DATABASE, VIEW, DEFAULT, RULE)

ALTER 语句(DATABASE, TABLE, VIEW, PROCEDURE, TRIGGER)

TRUNCATE TABLE

GRANT, REVOKE, DENY

UPDATE STATISTICS

RECONFIGURE

UPDATE STATISTICS

RESTORE DATABASE, RESTORE LOG

LOAD LOG, DATABASE

DISK语句

SELECT INTO (因为它创建一个表)

如果需要了解关于触发器的更多信息,请参看SQL Server联机手册。

事务、锁定和并行本部分解释了在Oracle和Microsoft SQL Server事务是如何执行的,并且提供了所有数据库类型中锁定过程和并行问题之间的区别。

事务

在Oracle中,执行插入、更新或者删除操作时自动开始事务。一个应用程序必须给出一个COMMIT命令来保存数据库的所有修改。如果没有执行COMMIT,所有的修改都将后滚或者自动变成未完成的。

缺省情况下,Microsoft SQL Server在每次插入、更新或者删除操作之后自动执行一个COMMIT语句。因为数据是自动保存的,你不能后滚任何改变。你可以使用隐式的或者显式的事务模式来改变这个缺省行为。

隐式的事务模式允许SQL Server像Oracle一样运转,这种模式是用SET IMPLICIT_TRANSACTIONS ON语句激活的。如果该选项是ON并且当前没有突出的事务,则每一个SQL语句自动开始一个事务。如果有一个打开的事务,则不会有任何新的事务开始。打开的事务必须由用户用COMMIT TRANSACTION语句来显明的承诺,以使所有的改变生效并且释放所有的锁定。

一个显明的事务是一组由下述事务分隔符包围的SQL语句:

BEGIN TRANSACTION [transaction_name]

COMMIT TRANSACTION [transaction_name]

ROLLBACK TRANSACTION [transaction_name | savepoint_name]

在下面这个例子中,英语系被改变为文学系。请注意BEGIN TRANSACTION和COMMIT TRANSACTION语句的用法。

Oracle

Microsoft SQL

INSERT INTO DEPT_ADMIN.DEPT (DEPT, DNAME)

VALUES ('LIT', 'Literature')

/

UPDATE DEPT_ADMIN.CLASS

SET MAJOR = 'LIT'

WHERE MAJOR = 'ENG'

/

UPDATE STUDENT_ADMIN.STUDENT

SET MAJOR = 'LIT'

WHERE MAJOR = 'ENG'

/

DELETE FROM DEPT_ADMIN.DEPT

WHERE DEPT = 'ENG'

/

COMMIT

/

BEGIN TRANSACTION

INSERT INTO DEPT_ADMIN.DEPT (DEPT, DNAME)

VALUES ('LIT', 'Literature')

UPDATE DEPT_ADMIN.CLASS

SET DEPT = 'LIT'

WHERE DEPT = 'ENG'

UPDATE STUDENT_ADMIN.STUDENT

SET MAJOR = 'LIT'

WHERE MAJOR = 'ENG'

DELETE FROM DEPT_ADMIN.DEPT

WHERE DEPT = 'ENG'

COMMIT TRANSACTION

GO

所有显明的事务必须用BEGIN TRANSACTION...COMMIT TRANSACTION语句封闭。SAVE TRANSACTION语句的功能同Oracle中的SAVEPOINT命令是一样的,在事务中设置一个保存点,这样就可以进行部分后滚(roll back)了。

事务可以嵌套。如果出现了这种情况,最外层的一对创建并提交事务,内部的对跟踪嵌套层。当遇到一个嵌套的事务时,@@TRANCOUNT函数就增加。通常,这种显然的事务嵌套发生在存储程序或者有BEGIN…COMMIT对互相调用的触发器中。尽管事务可以嵌套,但是对ROLLBACK TRANSACTION语句的行为的影响是很小的。

在存储过程和触发器中,BEGIN TRANSACTION语句的个数必须和COMMIT TRANSACTION语句的个数相匹配。包含不匹配的BEGIN TRANSACTION和COMMIT TRANSACTION语句的存储过程和触发器在运行的时候会产生一个错误消息。语法允许在一个事务中调用包含BEGIN TRANSACTION和COMMIT TRANSACTION语句对的存储过程和触发器。

只要情况许可,就应该把一个大的事务分成几个较小的事务。确保每个事务都在一个单独的batch中有完整的定义。为了把可能的并行冲突减到最小,事务既不应该跨越多个batch,也不应该等待用户输入。把多个事务组合到一个运行时间较长的事务中会给恢复时间带来消极的影响,并且还会造成并行问题。

在使用ODBC编程的时候,你可以通过使用SQLSetConnectOption函数来选择显式或者隐式的事务模式。究竟该选择哪种模式要视AUTOCOMMIT连接选项的情况而定。如果AUTOCOMMIT是ON(缺省的),你就是在显式模式中。如果AUTOCOMMIT是OFF,则在隐式模式下。

如果你通过SQL Server Query Analyzer或者其他查询工具使用脚本,你可以显式的包括一个上面提到的BEGIN TRANSACTION语句,也可以利用SET IMPLICIT_TRANSACTIONS ON语句来开始脚本。BEGIN TRANSACTION的方法更灵活一些,而隐式的方法更适合Oracle。

锁定和事务孤立

Oracle和Microsoft SQL Server有着很不一样的锁定和孤立策略。当你把Oracle应用程序转化为SQL Server应用程序的时候,你必须考虑到这些不同以确保应用程序的可伸缩性。

Oracle对所有读数据的SQL语句隐式或者显式的使用一种多版本一致模型(multiversion consistency model)。在这种模型中,数据读者在读数据行以前,缺省的既不获得一个锁定也不等待其他的锁定解开。当读者需要一个已经改变但别的写入者还没有提交的数据时,Oracle通过使用后滚段来重建一个数据行的快照的方法来重新创建旧的数据。

Oracle中的数据写入者在更新、删除或者插入数据时要请求锁定。锁定将一直维持到事务结束,并且禁止别的用户覆盖尚未提交的修改。

Microsoft SQL Server使用多粒度锁定,该锁定允许用事务来锁定不同类型的资源。为了把锁定的开销降到最低,SQL Server自动在与任务相配的层次上锁定资源。以较小的间隔尺寸锁定,例如行,增强了并行,但是管理开销较大,因为如果有许多行锁定,就必须维持多个锁定。以较大的间隔尺寸锁定,例如表,在并行方面是昂贵的,因为对整个表的锁定限制了其他事务对表中任何一部分的访问,但是管理开销却比较小,因为只要维持少数几个锁定。SQL Server可以锁定这些资源(按照间隔尺寸递增的顺序排列)。

资源

描述

RID

行标识符。用于一个单行表的独立锁定。

Key

键;索引中的一个行锁定。用于在一个可串行化的事务中保护键范围。

Page

8-KB数据页或者索引页。

Extent

相邻的八个数据页或者索引页的组。

Table

整个表,包括所有数据和索引。

DB

数据库。

SQL Server使用不同的锁定模式锁定资源,使用哪种模式决定了当前事务访问如何访问资源。

锁定模式

描述

Shared (S)

用于那些不修改或者更新数据的操作(只读操作),例如一个SELECT语句。

Update (U)

用于那些可以被更新的资源。防止当多个会话被读入、锁定,然后潜在的更新资源时发生一个公共形式的死锁。

Exclusive (X)

用于数据修改操作,例如UPDATE、INSERT、或者DELETE。确保不会同时发生对同一个资源的多个修改操作。

Intent

用于建立一个锁定层次。

Schema

在一个依靠表的模式的操作执行时使用。有两种类型的模式锁定:schema stability (Sch-S)和schema modification (Sch-M)。

对于任何RDBMS都很重要的一点是,快速释放锁定以提供最大的并行性。你可以通过尽可能短的保持一个事务来确保快速释放锁定。如果可能的话,事务不应该跨越多个往返行程到服务器,也不应该包括用户“思考”的时间。如果你使用游标,你也应该使你的应用程序很快提取数据,因为未提取数据的扫描将在服务器上占据共享锁定,因此将阻碍更新。欲了解更多信息,请参看本章后面的“使用ODBC”部分。

改变缺省的锁定行为

Microsoft SQL Server和Oracle都允许开发人员使用非缺省的锁定和孤立行为。在Oracle中,最普通的机制是SELECT 命令的FOR UPDATE子句,SET TRANSACTION READ ONLY命令,以及显式的LOCK TABLE命令。

因为两者的锁定和孤立策略如此不同,所以很难在Oracle和SQL Server之间直接映射锁定选择。要更好的理解这一过程,重要的一点是理解SQL Server提供的修改缺省锁定行为的选择。

在SQL Server中,修改缺省锁定行为最常用的机制是SET TRANSACTION ISOLATION LEVEL语句和在SELECT和UPDATE语句中支持的锁定暗示。SET TRANSACTION ISOLATION LEVEL语句为一个用户会话的持续时间设定事务孤立级别。除非在一个SQL语句的FROM子句中标明了表级别的锁定暗示,否则这将变成该会话的缺省行为。事务孤立是这样设定的:

SET TRANSACTION ISOLATION LEVEL

{

READ COMMITTED

| READ UNCOMMITTED

| REPEATABLE READ

| SERIALIZABLE

}

READ COMMITTED

缺省的SQL Server孤立级别。如果你使用这种选择,你的应用程序将不能读取其他事务还没有提交的数据。在这种模式下,一旦数据从页上读出,仍然要释放共享锁定。如果应用程序在同一个事务中重新读取同一个的数据区,将会看到别的用户做的修改。

SERIALIZABLE

如果设定了这种选择,事务将同其他事务孤立起来。如果你不希望在查询中看到其他用户做的修改,你可以设置事务的孤立级别为SERIALIZABLE。SQL Server将占据所有的共享锁定,直到事务结束。你可以通过在SELECT语句中表名的后面使用HOLDLOCK暗示来在一个更小的级别上取得同样的效果。

READ UNCOMMITTED

如果设定为这种选择,SQL Server读者将不会受到阻塞,就像在Oracle中一样。该选择实现了污损读取或者说是孤立级别为0的锁定,这意味着不使用任何共享锁定并且也不使用任何独占的锁定。当这个选项选定后,有可能会读到未提交的或者污损的数据;在事务结束以前,数据可能会改变,数据集中的行可能出现也可能消失。这个选项同一个事务中在所有SELECT语句中设定所有的表为NOLOCK的效果是一样的。这是四种孤立级别中限制性最小的一种。只有在你已经彻底的搞清楚了它将对你的应用程序结果的精确度有什么样的影响的前提下才能使用这种选择。

SQL Server有两种方法实现Oracle中的READ ONLY功能:

如果一个应用程序中的事务需要可重复读取的行为,你也许需要使用SQL Server提供的SERIALIZABLE孤立级别。

如果所有的数据库访问都是只读的,你可以设置SQL Server数据库选项为READ ONLY来提高性能。

SELECT…FOR UPDATE

当一个应用程序利用WHERE CURRENT OF 语法来在一个游标上实现定位更新或者删除时,首先使用Oracle中的SELECT…FOR UPDATE语句。在这种情况下,可以随意去掉FOR UPDATE子句,因为Microsoft SQL Server游标的缺省行为是“可更新的”。

缺省情况下,SQL Server游标在提取行下不占据锁定。SQL Server使用一种乐观的并行策略(optimistic concurrency strategy)来防止更新时相互之间的覆盖。如果一个用户试图更新或者删除一个读入游标后已经被修改过的行,SQL Server将给出一个错误消息。应用程序可以捕获该消息,并且重新进行适当的更新或者删除。要改变这个行为,开发人员可以在游标声明中使用SCROLL_LOCKS。

通常情况下,乐观的并行策略支持较高的并行性,所谓通常情况是指更新器之间冲突很少的情况。如果你的应用程序确实需要保证一行在被提取以后不会被修改,你可以在SELECT语句中使用UPDLOCK暗示。这个暗示不会阻碍别的读者,但是它禁止其他潜在的写入者也获得该数据的更新锁定。使用ODBC时,你可以通过使用SQLSETSTMTOPTION (…,SQL_CONCURRENCY)= SQL_CONCUR_LOCK来达到同样的目的。但是,其他的任何选择都将减少并行性。

表级别的锁定

Microsoft SQL Server可以用SELECT…table_name (TABLOCK)语句来锁定整个表。这和Oracle的 LOCK TABLE…IN SHARE MODE语句是一样的。该锁定允许其他人读取一个表,但是禁止他们修改该表。缺省情况下,锁定将维持到语句的结束。如果你同时加上了HOLDLOCK关键字(SELECT…table_name (TABLOCK HOLDLOCK)),表的锁定将一直维持到事务的结束。

可以用SELECT…table_name (TABLOCKX)语句在一个SQL Server表上设置一个独占的锁定。该语句请求一个表上的独占锁定。该锁定禁止其他人读取和修改该表,并且将一直维持到命令或者事务结束。这同Oracle中TABLE…IN EXCLUSIVE MODE语句的功能是一样的。

SQL Server没有为显式的锁定请求提供NOWAIT选项。

锁定升级

当一个查询向表请求行时,Microsoft SQL Server自动生成一个页级别的锁定。但是,如果查询请求表中的大部分行时,SQL Server将把锁定从页级别升级到表级别。这个过程叫做锁定升级。

锁定增加使那些产生较大结果集的表的扫描和操作更加有效,因为它减少了锁定的管理开销。缺少WHERE子句的SQL语句一般都要造成锁定增加。

在读取操作中,如果一个共享页级别的锁定增加为一个表锁定时,将应用一个共享表锁定(TABLOCK)。在下列情况下应用共享的表级别的锁定:

使用了HOLDLOCK或者SET TRANSACTION ISOLATION LEVEL SERIALIZABLE语句。

优化器选择了一个表的扫描。

表中积累的共享锁定的数目超过锁定升级的极限。

表中缺省的锁定升级的极限是200页,但是该极限可以用最小和最大范围定制为依赖于表尺寸的一个百分比。欲了解关于锁定升级极限的更多信息,请参看SQL Server联机手册。

在一个写操作中,当一个UPDATE锁定被升级为一个表锁定时,应用一个独占表锁定(TABLOCKX)。独占表锁定在下列情况下使用:

更新或者删除操作无索引可用。

表中有独占锁定的页的数目超过锁定升级上限。

创建了一个分簇的索引。

Oracle不能升级行级别的锁定,这将导致一些包含了FOR UPDATE子句的查询出问题。例如,假设STUDENT表有100,000行数据,并且一个Oracle用户给出下列语句:

SELECT * FROM STUDENT FOR UPDATE

这个语句强制Oracle RDBMS依次锁定STUDENT表的一行;这将花去一段时间。它永远也不会要求升级锁定到整个表。

在SQL Server同样的查询是:

SELECT * FROM STUDENT (UPDLOCK)

当这个查询运行的时候,页级别的锁定升级为表级别的锁定,后者更加有效并且明显要快一些。

死锁当一个进程锁定了另一个进程需要的页或者表的时候,而第二个进程又锁定了第一个进程需要的一页,这个时候就会发生死锁。死锁也叫抱死。SQL Server自动探测和解决死锁。如果找到一个死锁,服务器将终止完成了抱死的用户进程。

在每次数据修改之后,你的程序代码需要检查1205号消息,这个消息指出一个死锁。如果返回这个消息,就说明发生了一个死锁并且事务已经后滚。在这种情况下,你的应用程序必须重新开始这个事务。

死锁一般可以通过一些简单的技术加以避免:

在你的应用程序的各部分以同样的顺序访问表。

在每个表上使用分簇的索引以强制一个显式的行顺序。

使事务简短。

欲了解详细信息,请参阅Microsoft Knowledge Base文章“Detecting and Avoiding Deadlocks in Microsoft SQL Server”

远程事务

在Oracle中执行远程事务,你必须通过一个数据库连接访问远程数据库节点。在SQL Server中,你必须访问一个远程服务器。远程服务器是一台运行SQL Server的服务器,用户可以用他们的本地服务器访问该服务器。当某个服务器被设置为远程服务器,用户就可以在其上使用系统过程和存储过程而不需要显式的登录到上面。

远程服务器是成对设置的。你必须配置两台服务器,使它们互相把对方当作远程服务器。每台服务器的名字都必须用sp_addlinkedserver系统存储过程或者SQL Server Enterprise Manager加到伙伴服务器上。

设置完远程服务器以后,你可以用sp_addremotelogin系统存储过程或者SQL Server Enterprise Manager来为那些必须访问远程服务器的用户设置远程登录账号。在这一步完成以后,你还必须赋予他们执行存储过程的权限。

然后用EXECUTE语句来在远程服务器上执行过程。这个例子在远程服务器STUDSVR1上执行了validate_student存储过程,并且将指明成功或者失败的返回情况存储在@retvalue1中:

DECLARE @retvalue1 int

EXECUTE @retvalue = STUDSVR1.student_db.student_admin.validate_student '111111111'

欲了解详细信息,请参看SQL Server联机手册。

分布事务

如果修改两个或者更多的数据库节点上的表,Oracle就自动初始化一个分布式事务。SQL Server分布式事务使用包含在SQL Server中的微软分布事务协调器(Microsoft Distributed Transaction Coordinator,MS DTC)中的两步提交服务(two-phase commit services)。

缺省情况下,SQL Server必须被通知参与分布事务。SQL Server参与一个MS DTC事务可以用下面方式中的任一种来存储:

BEGIN DISTRIBUTED TRANSACTION语句。该语句开始一个新的MS DTC事务。

一个客户端应用程序直接调用DTC事务接口。

在下例中,注意对本地表GRADE和远程表CLASS的分布式更新(使用一个class_name过程):

BEGIN DISTRIBUTED TRANSACTION

UPDATE STUDENT_ADMIN.GRADE

SET GRADE = 'B+' WHERE SSN = '111111111' AND CCODE = '1234'

DECLARE @retvalue1 int

EXECUTE @retvalue1 = CLASS_SVR1.dept_db.dept_admin.class_name '1234', 'Basketweaving'

COMMIT TRANSACTION

GO

如果程序不能完成事务,则通过ROLLBACK TRANSACTION语句终止该事务。如果程序失败或者参与的资源管理器失败,MS DTC终止该事务。MS DTC不支持分布式的存储点或者是SAVE TRANSACTION语句。如果一个MS DTC事务失败或者后滚,则整个事务退回到分布式事务的起点,而不理会任何存储点。

两步提交处理

Oracle和MS DTC两步提交机制在操作上是相似的。在SQL Server两步提交的第一步,事务管理器请求每一个参与的资源管理器准备提交。如果有任何资源管理器没有准备好,事务管理器就向与事务相关的所有成员广播一个异常中断决定。

如果所有的资源管理器都能成功的准备,事务管理器就广播一个提交决定。这是提交处理的第二步。当一个资源管理器准备好后,事务究竟是提交了还是失败了,这一点还是拿不准。MS DTC维持了一个连续的日志,因此它的提交或者中断决定都是持久的。如果某个资源管理器或者事务管理器失败了,则当它们重新连接上的时候,就能在那个拿不准的事务上协调了。

SQL语言支持本部分简要介绍了Transact-SQL和PL/SQL语言语法上的相似和不同之处,并且给出了转换策略。

SELECT和数据操作声明

当你把Oracle DML语句和PL/SQL程序移植到SQL Server上时,请按下列步骤进行:

检查所有SELECT、INSERT、UPDATE、和DELETE语句是否有效。做任何需要的修改。

把所有的外部节点改为SQL-92外部节点语法

用适当的SQL Server函数代替Oracle函数

检查所有的比较操作符

用“+”代替“||”做字符串串联操作符。

用Transact-SQL程序代替PL/SQL程序

把所有的PL/SQL游标改为无游标SELECT语句或者Transact-SQL游标。

用Transact-SQL过程代替PL/SQL过程、函数和封装。

把PL/SQL触发器转换为Transact-SQL触发器。

使用SET SHOWPLAN语句来调试你的查询以获得高的性能。

SELECT statements语句

Oracle和Microsoft SQL Server用的SELECT语句的语法是类似的。

Oracle

Microsoft SQL

SELECT [/*+ optimizer_hints*/]

[ALL | DISTINCT] select_list

[FROM

{table_name | view_name | select_statement}]

[WHERE clause]

[GROUP BY group_by_expression]

[HAVING search_condition]

[START WITH … CONNECT BY]

[{UNION | UNION ALL | INTERSECT |

MINUS} SELECT …]

[ORDER BY clause]

[FOR UPDATE]

SELECT select_list

[INTO new_table_]

FROM table_source

[WHERE search_condition]

[ GROUP BY [ALL] group_by_expression [,…n]

[ WITH { CUBE | ROLLUP } ]

[HAVING search_condition]

[ORDER BY order_expression [ASC | DESC] ]

In addition:

UNION Operator

COMPUTE Clause

FOR BROWSE Clause

OPTION Clause

SQL Server不支持面向Oracle的基于开销的优化器暗示,必须把这些暗示清除掉。建议使用SQL Server的基于开销的优化器。欲了解详细信息,请参阅本章后面的“调试SQL语句”部分。

SQL Server不支持Oracle的START WITH…CONNECT BY子句。在SQL Server中,你可以用创建一个执行同样任务的存储过程来代替。

SQL Server不支持Oracle的INTERSECT和MINUS集合。SQL Server的EXISTS和NOT EXISTS子句可以完成同样的任务。

下面的例子使用INTERSECT操作符来为所有有学生的班级找到课程代码和课程名称。注意EXISTS操作符是怎样代替INTERSECT操作符的。两者返回的数据是一样的。

Oracle

Microsoft SQL

SELECT CCODE, CNAME

FROM DEPT_ADMIN.CLASS

INTERSECT

SELECT C.CCODE, C.CNAME

FROM STUDENT_ADMIN.GRADE G,

DEPT_ADMIN.CLASS C

WHERE C.CCODE = G.CCODE

SELECT CCODE, CNAME

FROM DEPT_ADMIN.CLASS C

WHERE EXISTS

(SELECT 'X' FROM STUDENT_ADMIN.GRADE G

WHERE C.CCODE = G.CCODE)

下例使用MINUS操作符来找出那些没有学生的班级。

Oracle

Microsoft SQL

SELECT CCODE, CNAME

FROM DEPT_ADMIN.CLASS

MINUS

SELECT C.CCODE, C.CNAME

FROM STUDENT_ADMIN.GRADE G,

DEPT_ADMIN.CLASS C

WHERE C.CCODE = G.CCODE

SELECT CCODE, CNAME

FROM DEPT_ADMIN.CLASSC

WHERE NOT EXISTS

(SELECT 'X' FROM STUDENT_ADMIN.GRADE G

WHERE C.CCODE = G.CCODE)

INSERT语句

Oracle和Microsoft SQL Server用的INSERT语句的语法是类似的。

Oracle

Microsoft SQL

INSERT INTO

{table_name | view_name | select_statement} [(column_list)]

{values_list | select_statement}

INSERT [INTO]

{

table_name [ [AS] table_alias] WITH ( <table_hint_limited> […n])

| view_name [ [AS] table_alias]

| rowset_function_limited

}

{[(column_list)]

{ VALUES ( {DEFAULT

|NULL

|expression

}[,…n]

)

| derived_table

| execute_statement

}

}

| DEFAULT VALUES

Transact-SQL语言支持插入表和视图,但是不支持SELECT语句中的INSERT操作。如果你的Oracle程序这么做了,则必须修改。

Oracle

Microsoft SQL

INSERT INTO (SELECT SSN, CCODE, GRADE FROM GRADE)

VALUES ('111111111', '1111',NULL)

INSERT INTO GRADE (SSN, CCODE, GRADE)

VALUES ('111111111', '1111',NULL)

Transact-SQL的values_list参数提供了SQL-92标准的关键字DEFAULT,但这个在Oracle中是不支持的。当执行插入操作的时候,这个关键字给出了要用到的列的缺省值。如果给定的列没有缺省值,则插入一个NULL。如果该列不允许NULL,则返回一个错误消息。如果该列是作为一个时间片数据类型定义的,则插入下一个连续值。

关键字DEFAULT不能用于标识列。要产生下一个连续值,则有IDENTITY属性的列一定不能列入column_list或者values_clause。你不一定非要用DEFAUL关键字来获得一列的缺省值。在Oracle中,如果该列没有被column_list引用并且它有一个缺省值,则缺省值将放入列中。这是执行移植时最兼容的方法。

一个有用的Transact-SQL选项(EXECute procedure_name)是执行一个过程并且用管道把它的输出值输出到一个目标表或者视图。Oracle不允许你这样做。

UPDATE语句

因为Transact-SQL支持Oracle的UPDATE绝大多数语法,所以只需要很小的修改。

Oracle

Microsoft SQL

UPDATE

{table_name | view_name | select_statement}

SET [column_name(s) = {constant_value | expression | select_statement | column_list |

variable_list}

{where_statement}

UPDATE

{

table_name [ [AS] table_alias] WITH ( <table_hint_limited> […n])

view_name [ [AS] table_alias]

| rowset_function_limited

}

SET

{column_name = {expression | DEFAULT | NULL}

| @variable = expression

| @variable = column = expression } [,…n]

{{[FROM {<table_source>} [,…n] ]

[WHERE

<search_condition>] }

|

[WHERE CURRENT OF

{ { [GLOBAL] cursor_name } | cursor_variable_name}

] }

[OPTION (<query_hint> [,…n] )]

Transact-SQL的UPDATE语句不支持依赖SELECT语句的更新操作。如果你的Oracle程序这样做了,你可以把SELECT语句变成一个视图,然后在SQL Server的UPDATE语句中使用这个视图名字。请参看前面“INSERT”语句中的例子。

Oracle的UPDATE命令只能使用一个PL/SQL块中的程序变量。Transact-SQL语言不要求在使用变量时使用块。

Oracle

Microsoft SQL

DECLARE

VAR1 NUMBER(10,2);

BEGIN

VAR1 := 2500;

UPDATE STUDENT_ADMIN.STUDENT

SET TUITION_TOTAL = VAR1;

END;

DECLARE

@VAR1 NUMERIC(10,2)

SELECT @VAR1 = 2500

UPDATE STUDENT_ADMIN.STUDENT

SET TUITION_TOTAL=@VAR1

第一頁    上一頁    第2頁/共4頁    下一頁    最後頁
第01頁 第02頁 第03頁 第04頁 
 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有