安装和配置Microsoft SQL Server
了解了Oracle和SQL Server之间基本结构上的差异以后,你就可以开始进行移植过程的第一步了。SQL Server
Query Analyzer将用来运行下面的脚本:
使用Windows NT基于软件的RAID或者基于硬件的RAID第五级来创建一个足够放下你的所有数据的逻辑驱动器。
对空间的估算可以通过计算被Oracle系统、临时文件以及应用程序表空间占用的文件空间大小来进行。
使用Windows NT基于软件的RAID或者基于硬件的RAID第一级创建一个第二逻辑驱动器来放事务日志。该驱动
器的大小起码应该和在线恢复以及后滚表空间的总的大小一致。
使用SQL Server Enterprise Manager创建一个和Oracle应用程序表空间名字一样的数据库。(示例应用程
序使用的数据库名字叫做USER_DB)标明文件位置,使它们分别和你在第一步以及第二步中为数据和事务创
建的磁盘位置一致。如果你使用多个Oracle表空间,不需要也建议你不要创建多个SQL Server数据库,RAID
会自动为你分配的。
创建SQL Server登录账号: USE MASTER
EXEC SP_ADDLOGIN STUDENT_ADMIN, STUDENT_ADMIN
EXEC SP_ADDLOGIN DEPT_ADMIN, DEPT_ADMIN
EXEC SP_ADDLOGIN ENDUSER1, ENDUSER1
GO
为数据库添加角色: USE USER_DB
EXEC SP_ADDROLE DATA_ADMIN
EXEC SP_ADDROLE USER_LOGON
GO
为角色授予许可: GRANT CREATE TABLE, CREATE TRIGGER, CREATE VIEW,
CREATE PROCEDURE TO DATA_ADMIN
GO
增加作为数据库用户账号的登录账号:
EXEC SP_ADDUSER ENDUSER1, ENDUSER1, USER_LOGON
EXEC SP_ADDUSER DEPT_ADMIN, DEPT_ADMIN, DATA_ADMIN
EXEC SP_ADDUSER STUDENT_ADMIN, STUDENT_ADMIN, DATA_ADMIN
GO
定义数据库对象
Oracle数据库对象(表、视图和索引)可以很容易的移植到Microsoft SQL Server上,这是因为两个数据
库都基本遵循SQL-92标准,该标准承认对象定义。把Oracle SQL的表、索引和视图的定义转换为SQL Server
的表、索引和视图的定义只需要做相对简单的语法改变。下表指出了Oracle和Microsoft SQL Server之间的
数据库对象的某些不同之处。
类别 Microsoft SQL Server Oracle
列数 1024 254
行尺寸 8060 byte, 外加16 byte用来指向每一个text或者image列 无限制 (每行只允许有一个long或者long
raw)
最大行数 无限制 无限制
BLOB类型存储 行中存储一个16-byte 指针。数据存储在其他数据页。 每表一个long或者long raw。 必须在
行的结尾。数据存储在行的同一个块里。
分簇表索引 每表一个 每表一个(index-organized tables)
未分簇的表索引 每表249 无限制
在单一索引中的最大索引列数 16 16
索引中列值的最大长度 900 bytes ? block
表名约定 [[[server.]database.]owner.]
table_name [schema.]table_name
视图名约定 [[[server.]database.]owner.]
table_name [schema.]table_name
索引名约定 [[[server.]database.]owner.]
table_name [schema.]table_name
假设你是从一个Oracle脚本或者程序开始的,该脚本或者程序用来创建你的数据库对象。拷贝你的脚本或
者程序并且进行如下修改。这些修改将在本部分的其他地方加以讨论。该例子是从示例应用程序脚本
Oratable.sql和Sstable.sql中截取的:
确保数据库对象标识遵循Microsoft SQL Server命名法则。你可能只需要修改索引的名字。
修改数据存储参数使之能在SQL Server下工作。如果你使用RAID,就不需要任何存储参数了。
修改Oracle约束定义使之能在SQL Server中工作。如果需要的话,创建一个触发器以支持外部键DELETE
CASCADE语句。如果表跨数据库的话,使用触发器来增强外部键的关系。
修改CREATE INDEX语句以利用分簇的索引。
使用数据转换服务来创建新的CREATE TABLE语句。回顾该语句,注意Oracle数据类型是如何映射到SQL
Server数据类型上的。
清除所有的CREATE SEQUENCE语句。在CREATE TABLE或者ALTER TABLE语句中使用同等列来替换顺序的使用。
如果需要的话,修改CREATE VIEW语句。
清除所有对同义字的引用。
评估对Microsoft SQL Server临时表的使用和其在你的应用程序中的用处。
把所有的Oracle的CREATE TABLE…AS SELECT命令改为SQL Server的SELECT…INTO语句。
评估潜在的对用户定义规则、数据类型和缺省的使用。
数据对象标识符
下表比较了Oracle和Microsoft SQL Server是如何处理对象标识符的。在许多情况下,当移植到SQL
Server上时,你不需要改变对象的名字。
Oracle Microsoft SQL
1-30 字符长度。
数据库名称:最多8个字符长度。
数据库连接名称:最多128个字符长度。 1-128 Unicode字符长度。
临时表名称:最多116个字符。
标识符的名称必须用:字母、包含文字数字的字符、或者字符_, $, 和 #开头 标识符名称可以用:字母
数字字符、或者_开头,实际上可以用任何字符开头。
如果标识符用空格开头,或者包含了不是_、@、#、或者$的字符,你必须用[](定界符)包围标识符名称
如果一个对象用下面这些字符开头:
@ 则表明该对象是一个本地变量。
# 则该对象是一个本地临时对象。
## 则该对象是一个全局临时对象
表空间名必须唯一. 数据库名必须唯一
标识符名在用户账号(计划,Schema)范围内必须唯一。 标识符名在数据库用户账号范围内必须唯一
列名在表和视图范围内必须唯一。 列名在表和视图范围内必须唯一。
索引名在用户账号(Schema)范围内必须唯一。 索引名在数据库表名范围内必须唯一
修饰表名
当访问存在于你的用户账号中的表时,该表可以简单的通过未经限制的表名来选中。访问其他Oracle计划
中的表就需要把该计划的名字作为前缀加到表名上,两者之间用点号(.)隔开。Oracle同义字可以提供
更高的位置透明度。
涉及到表时,Microsoft SQL Server采用一种不同的方法。因为一个SQL Server登录账号可以在多个数据
库中用同一个名字创建一个表,所以采用下面的方法来访问表和视图:[[数据库名字]所有者名字]表名]
用……访问一个表 Oracle Microsoft SQL Server
你的用户账号 SELECT *
FROM STUDENT SELECT * FROM USER_DB.STUDENT_
ADMIN.STUDENT
其他模式(schema) SELECT * FROM STUDENT_ADMIN.STUDENT SELECT * FROM OTHER_DB.STUDENT_
ADMIN.STUDENT
这是一些为Microsoft SQL Server表和视图命名的指导方针:
使用数据库名字和用户名字是可选的。如果一个表只通过名字加以引用(例如,STUDENT),SQL Server在
当前数据库中以当前用户帐号搜索该表。如果没有找到,就在数据库中寻找由dbo的保留用户名拥有的具有
同样名字的对象。表名在同一个数据库中的同一个用户帐号下必须是唯一的。
同一个SQL Server登录账号可以在多个数据库中拥有同样名字的表。例如,ENDUSER1账号拥有下列数据库对
象:USER_DB.ENDUSER1.STUDENT和OTHER_DB.ENDUSER1.STUDENT。这里所加的限制是数据库用户名而不是SQL
Server登录名,因为两者不一定要一样。
同时,这些数据库的其他用户可以有同样名字的对象:
USER_DB.DBO.STUDENT
USER_DB.DEPT_ADMIN.STUDENT
USER_DB.STUDENT_ADMIN.STUDENT
OTHER_DB.DBO.STUDENT
因此,建议你在引用数据库对象时包含所有者的名字。如果应用程序有多个数据库,建议你再把数据库名字
也包含在引用中。如果查询跨越多个服务器,还要包括服务器名。
SQL Server的每个连接都有一个当前数据库上下文,这是在登录时用USE语句设置的。例如,假设有下面的场
景:
一个用户,使用ENDUSER1账号,登录到USER_DB数据库上。用户请求STUDENT表。SQL Server就查询ENDUSER1.
STUDENT表。如果找到,SQL Server就在USER_DB.ENDUSER1.STUDENT表上做要求的数据库操作。如果在
ENDUSER1数据库账号下没有找到该表,SQL Server就为该数据库以dbo账号搜寻USER_DB.DBO.STUDENT。如果
还是找不到该表,SQL Server就返回一个错误消息,指出该表不存在。
如果另一个用户,例如DEPT_ADMIN拥有该表,则该表必须以数据库用户名作为前缀(DEPT_ADMIN.STUDENT)。
另外,数据库名字缺省为在当前上下文中的数据库名字。
如果被引用的表在另一个数据库中,则数据库名必须作为引用的一部分。例如,要访问在OTHERDB数据库中由
ENDUSER1拥有的表STUDENT,就需要用OTHER_DB.ENDUSER1.STUDENT来引用。
可以在数据库和表名之间加两个点号来省略对象的所有者名。例如,如果应用程序引用STUDENT_DB..STUDENT
,SQL Server就做如下搜
查看本文来源
索引
Microsoft SQL Server提供了分簇和未分簇的索引结构。这些索引是由来自于一个叫做B-tree的树型结构中
的页构成的(同Oracle中的B-tree索引结构相似)。起始页(“根”级)说明了表中值的范围。“根”级页
中的每一个范围指向其他页(判断节点),该节点包含了表中值的更小的范围。以此类推,该节点又可以指
向其他的判断节点,这样就缩小了搜索的范围。树型结构的最后一级叫做“叶”级。
分簇的索引
分簇的索引在Oracle中是以索引组织表的形式实现的。一个分簇的索引是一个物理的包含在一个表中的索引。
表和索引分享同一块存储空间。分簇的索引按索引顺序物理的重排数据行,建立起中间判断节点。索引的
“叶”页包含了真实的表数据。这个结构允许每个表只有一个分簇的索引。Microsoft SQL Server为表自动
的创建一个分簇的索引,无论该表设置了PRIMARY KEY还是UNIQUE约束。分簇的索引对下面这些是有用的:
主键(Primary keys)
不能被更新的列。
返回一个值的范围的查询,使用诸如BETWEEN、>、>=、<、以及<=这样的操作符,例如:
SELECT * FROM STUDENT WHERE GRAD_DATE
BETWEEN '1/1/97' AND '12/31/97'
返回一个大的结果集合的查询:
SELECT * FROM STUDENT WHERE LNAME = 'SMITH'
被用做排序操作的列(ORDER BY、GROUP BY)
例如,在STUDENT表上,在ssn的主键上包含一个未分簇的索引是很有用的,而分簇的索引可以在lname、
fname(last name、first name)上创建,因为这是一种常用的区分学生的方法。
分布表上的更新行为可以防止出现“热点”。热点通常是由于多个用户向一个有上升键的表中填充而引起
的。这样的情景经常导致行级别的锁定。
删除和重建一个分簇的索引在SQL Server中是一种很普通的重新组织表的技术。这是一种确保数据页在磁
盘上是连续的以及重建表中的一些可用空间的简单的方法。这同Oracle中导出、删除以及导入一个表是很
相似的。
一个SQL Server分簇的索引与Oracle的簇在根本上是不一样的。一个Oracle的簇。一个Oracle的簇是两个
或者更多的表的物理集合,它们分享同一个数据块,使用一个公共的列来作为簇键。SQL Server没有与
Oracle簇相似的结构。
作为一个普遍的原则,在表上定义一个分簇的索引将提高SQL Server的性能并且加强空间管理。如果你
不知道对于给定表的查询和更新模式,你可以在主键上创建一个分簇的索引。
下表摘录自示例应用程序的源代码。请注意SQL Server“簇”化索引的使用。
Oracle Microsoft SQL
CREATE TABLE STUDENT_ADMIN.GRADE (
SSNCHAR(9) NOT NULL,
CCODEVARCHAR2(4) NOT NULL,
GRADEVARCHAR2(2) NULL,
CONSTRAINT GRADE_SSN_CCODE_PK
PRIMARY KEY (SSN, CCODE)
CONSTRAINT GRADE_SSN_FK
FOREIGN KEY (SSN) REFERENCES
STUDENT_ADMIN.STUDENT (SSN),
CONSTRAINT GRADE_CCODE_FK
FOREIGN KEY (CCODE) REFERENCES
DEPT_ADMIN.CLASS (CCODE)
) CREATE TABLE STUDENT_ADMIN.GRADE (
SSNCHAR(9) NOT NULL,
CCODEVARCHAR(4) NOT NULL,
GRADEVARCHAR(2) NULL,
CONSTRAINT
GRADE_SSN_CCODE_PK
PRIMARY KEY CLUSTERED (SSN, CCODE),
CONSTRAINT GRADE_SSN_FK
FOREIGN KEY (SSN) REFERENCES
STUDENT_ADMIN.STUDENT (SSN),
CONSTRAINT GRADE_CCODE_FK
FOREIGN KEY (CCODE) REFERENCES
DEPT_ADMIN.CLASS (CCODE)
)
未分簇的索引
在未分簇的索引中,索引数据和表数据在物理上是分开的,并且表中的行并不是按顺序存储在索引中的。
你可以把Oracle索引定义移植到Microsoft SQL Server未分簇的索引定义上(就像在下表中显示的一样)。
可是,考虑到性能的缘故,你可能希望选择表的其中一个索引把它创建为分簇的索引。
Oracle Microsoft SQL
CREATE INDEX
STUDENT_ADMIN.STUDENT_
MAJOR_IDX
ON STUDENT_ADMIN.STUDENT (MAJOR)
TABLESPACE USER_DATA
PCTFREE 0
STORAGE (INITIAL 10K NEXT 10K
MINEXTENTS 1 MAXEXTENTS
UNLIMITED) CREATE NONCLUSTERED INDEX
STUDENT_MAJOR_IDX
ON USER_DB.STUDENT_
ADMIN.STUDENT (MAJOR)
索引语法和命名
在Oracle中,一个索引的名字在一个用户账号中是唯一的。在In Microsoft SQL Server,一个索引的名
字在一个表名中必须是唯一的,但是不必在用户名和数据库名中唯一。因此,在SQL Server中创建或者删
除索引时,你必须说明表名和索引名。另外,SQL Server的DROP INDEX语句可以一次删除多个索引。
Oracle Microsoft SQL
CREATE [UNIQUE] INDEX [schema].index_name
ON [schema.]table_name (column_name
[, column_name]...)
[INITRANS n]
[MAXTRANS n]
[TABLESPACE tablespace_name]
[STORAGE storage_parameters]
[PCTFREE n]
[NOSORT]
DROP INDEX ABC;
CREATE [UNIQUE] [CLUSTERED | NONCLUSTERED]
INDEX index_name ON table (column [,…n])
[WITH
[PAD_INDEX]
[[,] FILLFACTOR = fillfactor]
[[,] IGNORE_DUP_KEY]
[[,] DROP_EXISTING]
[[,] STATISTICS_NORECOMPUTE]
]
[ON filegroup]
DROP INDEX USER_DB.STUDENT.DEMO_IDX, USER_DB.GRADE.DEMO_IDX
索引数据存储参数
Microsoft SQL Server功能选项中的FILLFACTOR选项在很多方面与Oracle中的PCTFREE变量相似。当表的
尺寸增加的时候,索引页也相应改变以容纳新的数据。索引必须自己进行重新组合以容纳新的数据。只有
在创建索引的时候,才使用填充参数百分比,而且在这之后也不加以维护。
FILLFACTOR选项(0~100)控制着在创建索引时应该留下多少空间。如果没有表明参数,就使用缺省
参数,该参数是0,表示将完全填充索引的“叶”页,并且在每个判断节点为至少一个条目留下空间(如
果有两个条目,则表示是一个不唯一的“簇”化索引)。
一个较低的填充因数将会减少索引页的分裂,但是会增加B-tree结构的层数。较高的填充因数能更有效的
使用索引页空间,只需要较少的磁盘I/O来访问索引数据,并且将会减少B-tree结构的层数。
PAD_INDEX选项表示,填充因数也将应用到判断节点页上,就象要用在索引的数据页上一样。
虽然在 Oracle中可能需要调整PCTFREE参数以优化性能。但是在CREATE INDEX语句中很少使用FILLFACTOR
参数。填充因数是为性能优化而提供的。但是它仅仅在一个表上为已有数据创建索引时才有用,并且只有在
你能精确的预测数据在未来的变化时才有用。
如果你将Oracle中的PCTFREE参数设为0,可以考虑将它设为100。这在表中不会发生数据输入和修改(
只读表)时是很有用的。如果填充因数设为100,服务器将创建这样一个索引,它的每一页都是完全填满
的。
忽略重复的关键字
无论在Oracle还是在Microsoft SQL Server中,用户都不能在一个或者一些唯一索引的列中输入重复的值。
这样做将会产生一个错误消息。然而,SQL Server允许开发人员选择INSERT或者UPDATE语句将如何处理这个
错误。
如果在CREATE INDEX语句中使用了IGNORE_DUP_KEY,并且执行了一个创建重复的关键字的INSERT或者UPDATE
语句,SQL Server将给出一个警告信息,并且忽略重复行。如果没有使用IGNORE_DUP_KEY,SQL Server将给
出一个错误信息,并且后滚整个INSERT语句。如果需要了解关于这个选项的更多信息,请参看SQL Server联
机手册。
使用临时表
一个Oracle应用程序也许必须创建一个暂时存在的表。应用程序必须确保在某个时候删除所有为此目的创建
的表。如果应用程序不这样做,那么表空间将很快变得混乱,难以管理。
Microsoft SQL Server提供了临时表数据库对象,这个表就是为上面提到的目的创建的。这样的表总是在
tempdb数据库中创建的。表的名字决定了该表在tempdb数据库中要存在多长时间。
表名 描述
#table_name 这个本地临时表只在用户会话或者创建它的过程的生命期内存在。在用户退出登录或者创建
它的过程完成以后,该表自动删除。该表不能在多个用户之间共享。其它数据库用户不能访问该表。在该
表上不能赋予或者撤消许可。
##table_name 该表也典型的存在于用户会话或者创建它的过程的生命期内。但该表可以被多个用户共享。
在最后一个引用它的
查看本文来源
引用完整性
下表提供了一个用来定义referential完整性约束的语法比较。
约束 Oracle Microsoft SQL Server
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 ; {@parameter data_type} [VARYING] [= default] [OUTPUT]
触发器(Triggers)
Oracle和Microsoft SQL Server都有触发器,但它们在执行上有些不同。
查看本文来源