|
SQL语言支持
本章节概括介绍了Transact-SQL与SPL两种语法之间的共性和区别,并提供了两者之间的转换策略。
SELECT和数据操作语句
请在将Informix SQL语句和SPL程序迁移至SQL Server时采用下列方法。
1.
检验所有SELECT、INSERT、UPDATE和DELETE语句的语法结构是否有效,并进行必要修改。
2.
根据SQL-92标准外部联接语法对所有外部联接进行修改。
3.
将Informix函数替换为适当的SQL Server函数。
4.
检查所有比较运算符。
5.
将字符串连接运算符“||”替换成“+”。
6.
将SPL程序替换为Transact-SQL程序。
7.
将所有SPL游标参数修改成不含游标的SELECT语句或Transact-SQL游标。
8.
将SPL过程、函数和软件包替换为Transact-SQL过程。
9.
将SPL触发器转换成Transact-SQL触发器。
10.
使用SET SHOWPLAN语句调节查询性能。
SELECT语句
Informix和Microsoft SQL Server所使用的SELECT语法大同小异。
Informix
Microsoft SQL Server
SELECT [ALL | DISTINCT]
[optimizer directives]
select_list
[FROM
{table_name | view_name | select_statement}]
[WHERE clause]
[GROUP BY group_by_expression]
[HAVING search_condition]
[{UNION | UNION ALL } SELECT …]
[ORDER BY clause]
[FOR UPDATE { OF column } |
FOR READ ONLY]
[INTO {TEMP | SCRATCH} table_name]
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不支持以成本为基础的Informix专用优化程序指令,因此,必须将它们删除。我们建议使用以成本为基础的SQL Server优化技术。如需了解更多相关信息,请参阅本章稍后为您呈献的“调节SQL语句”。
INSERT语句
Informix和Microsoft SQL Server所使用的INSERT语法大同小异。
Informix
Microsoft SQL Server
INSERT INTO
{table_name | view_name }
[(column_list)]
VALUES
{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语言不支持Informix的PUT语句,因此,应将所有出现该语句的片断替换成INSERT语句。
Informix
Microsoft SQL Server
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参数提供了Informix无法支持的SQL-92标准关键字DEFAULT。这个关键字指定了执行插入操作时所使用的数据列缺省值。如果缺省值并不针对指定列而存在,被插入的就会是NULL值。如果数据列不允许输入NULL值,系统将返回一条出错消息。如果数据列被定义成timestamp(时间戳)数据类型,系统就会插入下一个顺序值。
DEFAULT关键字无法与标识列配合使用。如需生成下一个顺序值,便不得将具有IDENTITY属性的列纳入column_list或values_clause。您不必使用DEFAULT关键字为某一数据列获取缺省值。就像在Informix中那样,如果数据列虽未在column_list中接受引用,但却具备缺省值,那么,缺省值将被置入该数据列。这就是迁移执行过程中最具兼容性的方法。
一个有用的Transact-SQL选项(EXECute procedure_name)会执行某一过程,并将结果输出到目标表或视图。而Informix却不支持上述功能。
UPDATE语句
由于Transact-SQL可为Informix UPDATE指令使用的大多数语法提供支持,因此,只需对其进行最微小的调整。
Informix
Microsoft SQL Server
UPDATE
[optimizer directives]
{table_name | view_name | synonym_name }
SET [column_name(s) = {constant_value | expression | select_statement | column_list |
variable_list]
[ {where_statement} |
{WHERE CURRENT OF cursor_id}]
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] )]
SQL Server不支持以成本为基础的Informix专用优化程序指令,因此,必须将这些指令删除。我们建议使用以成本为基础的SQL Server优化技术。如需了解更多相关信息,请参阅本章稍后为您呈献的“调节Tuning SQL语句”。
Informix UPDATE指令只能使用来自SPL语句块的程序变量。Transact-SQL语言并不需要语句块调用者使用程序变量。
Informix
Microsoft SQL Server
DEFINE VAR1 NUMBER(10,2);
BEGIN
LET 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
关键字DEFAULT可供用来在SQL Server中将数据列设定为缺省值。您无法借助Informix的UPDATE指令将数据列设定为缺省值。
Transact-SQL和Informix SQL可支持在UPDATE语句中使用子查询。当然,Transact-SQL FROM子句还可被用来在连接基础上生成UPDATE语句。这种功能有助于提高UPDATE语法的易读性,并在某些情况下改善性能表现。
Informix
Microsoft SQL Server
UPDATE STUDENT_ADMIN.STUDENT S
SET TUITION_TOTAL = 1500
WHERE SSN IN (SELECT SSN
FROM GRADE G
WHERE G.SSN = S.SSN
AND G.CCODE = '1234')
子查询:
UPDATE STUDENT_ADMIN.STUDENT S
SET TUITION_TOTAL = 1500
WHERE SSN IN (SELECT SSN
FROM GRADE G
WHERE G.SSN = S.SSN
AND G.CCODE = '1234')
FROM clause:
UPDATE STUDENT_ADMIN.STUDENT S
SET TUITION_TOTAL = 1500
FROM GRADE G
WHERE S.SSN = G.SSN
AND G.CCODE = '1234'
DELETE语句
您在大多数情况下均无需对DELETE语句进行调整。
Transact-SQL既可为子查询在WHERE子句中的使用提供支持,又可为FROM子句中的联接提供支持。后者还可生成更为高效的语句。请参阅“UPDATE语句”中的示例。
SQL Server不支持以成本为基础的Informix专用优化程序指令,因此,必须将这些指令删除。我们建议使用以成本为基础的SQL Server优化技术。如需了解更多相关信息,请参阅本章稍后为您呈献的“调节Tuning SQL语句”。
Informix
Microsoft SQL Server
DELETE [optimizer directives] [FROM]
{table_name | view_name | synonym_name}
[ {WHERE clause} |
{ WHERE CURRENT OF cursor_id} ]
DELETE
[FROM ]
{
table_name [ [AS] table_alias] WITH ( <table_hint_limited> […n])
| view_name [ [AS] table_alias]
| rowset_function_limited
}
[ FROM {<table_source>} [, …n] ]
[WHERE
{ <search_condition>
| { [ CURRENT OF
{
{ [ GLOBAL ] cursor_name }
| cursor_variable_name
}
]
}
]
[OPTION (<query_hint> [,…n])]
TRUNCATE TABLE Statement
Informix和Microsoft SQL Server所使用的TRUNCATE TABLE语法完全相同。TRUNCATE TABLE可供用来将所有数据行从表中删除,并且无法实现回滚。表结构和全部索引将继续存在。DELETE触发器将不会得到执行。如果数据表正由FOREIGN KEY约束引用,则不能被截断。
Informix
Microsoft SQL Server
TRUNCATE TABLE table_name
TRUNCATE TABLE table_name
在SQL Server中,只有表所有者才能发出上述语句指令。而在Informix中,只要您具备表所有者身份或拥有DBA系统权限,即可发出上述指令。
Informix的TRUNCATE TABLE指令不会释放由表中数据行占据的存储空间。而SQL Server的TRUNCATE TABLE指令却总能回收由表数据及相关索引占据的存储空间。
在标识列和时间戳列内执行数据操作
Informix的序列数据类型与SQL Server的IDENTITY列较为相似。如果将0(零)值插入Informix序列数据列,下一个序列值就会被使用。最近插入的序列值将以SQLCA记录组成部分的形式返回。只要序列值不违反与之相关的唯一性约束,Informix就允许直接插入并更新序列值。Informix将在表创建过程中设定序列种子。Informix中并不存在与SQL Server TIMESTAMP列相当的对象。然而,在Microsoft SQL Server标识列中,数值将不能得到更新,DEFAULT关键字也无法接受使用。
在缺省状态下,数据不能被直接插入标识列。标识列将为刚被插入表中的每个新数据行自动生成唯一的顺序编号。您可利用下列SET语句对这种缺省值加以替换:
SET IDENTITY_INSERT table_name ON
在IDENTITY_INSERT已被设定为ON的情况下,用户可将任何数值插入新增行的标识列。为防止输入重复编号,系统将针对标识列生成具有唯一性的索引。这个语句的用途就是允许用户为偶然被删除的数据行重新生成数值。@@IDENTITY函数可被用来获取最近的标识值。
TRUNCATE TABLE语句可将标识列重新设定为初始SEED值。如果您不需要为数据列重新设定标识值,则应以不带有WHERE子句的DELETE语句替换TRUNCATE TABLE语句。由于Informix的SERIAL种子值不会在TRUNCATE TABLE指令发出后得到重置,因此,您必须就其对Informix迁移所产生的影响做出评估。
您可在使用timestamp数据列的过程中,仅仅执行插入或删除操作。如果您试图对timestamp列进行更新,则会收到下列出错消息:
Msg 272, Level 16, State 1 Can't update a TIMESTAMP column.
锁定被请求的行
Informix使用FOR UPDATE子句对SELECT语句中指定的数据行加锁。但这在Microsoft SQL Server中则是缺省行为方式,因此,您不必在Microsoft SQL Server中使用具有相关功能的子句。
行聚合与计算子句
SQL Server的COMPUTE子句可供用来生成行聚合函数(SUM、AVG、MIN、MAX和COUNT),这看上去更像是在查询结果中又加了一行。该子句允许您在结果集内查看细节信息与求和行。您可计算与分组数据相对应的求和数值,并使用多个聚合函数对同一组数据进行计算。
Informix的SELECT指令语法无法为COMPUTE子句提供支持。
联接子句
Microsoft SQL Server 2000允许使用联接子句将最多不超过256个数据表联接起来(既包括临时表,又包括固定表)。虽然Informix中并不存在联接限制,但所有用户打开的数据表却不得超过33,000个——这实际上相当于限定了联接所包含的表数量。
当您在Informix中使用外部联接时,关键字OUTER一般被置于并未接受强制联接的数据表之后(通常被称为辅助表)。在使用SQL Server的情况下,您将可对外部联接操作符*=和=*加以利用。“*”在这里被用来标识具有更多唯一值的数据列。如果子(外键)列不允许出现空值,那么,“*”将被置于等号(=)的父(PRIMARY KEY或UNIQUE约束)列一端。“*”的位置在Informix中恰好相反。您不能将“*”同时置于等号(=)两端。
*= and =*通常被视为旧版联接操作符。SQL Server还可为下列SQL-92标准联接操作符提供支持。我们建议您使用这种语法。与“* ”操作符相比,SQL-92标准语法的功能更强,限制更少。
联接操作 描述
CROSS JOIN
这是两个表的矢量积。它所返回的数据行与不包含WHERE子句的老式联接操作返回的数据行完全相同。这种联接在Informix中被称作笛卡尔联接。
INNER
这种联接操作要求将内部行全部返回。不符合要求的任何数据行都将被删除。这相当于标准的Informix表联接。
LEFT [OUTER]
这种联接操作要求将左侧表的外部行全部返回——即使未发现符合要求的数据列。这相当于Informix的外部联接。
RIGHT [OUTER]
这种联接操作要求将左侧表的外部行全部返回——即使未发现符合要求的数据列。这相当于Informix的外部联接。
FULL [OUTER]
如果来自任一数据表的某一行不符合选择条件,则要求将该行纳入结果集,并将与其它表相对应的输出列设定为NULL值。Informix不具备直接等同于全面外部联接的指令。
以下示例代码将返回全体学生所属班级清单。外部联接将在允许显示全体学生(甚至包括那些不属于任何班级的学生)的学生与年级数据表之间得到定义。外部联接还将被添加至班级数据表,以便返回班级名称。如果外部联接未被添加到班级数据表,那些不属于任何班级的生员记录就会因其学号(CCODE)为空而无法被返回。
Informix
Microsoft SQL Server
SELECT S.SSN AS SSN,
FNAME, LNAME
FROM STUDENT S,
OUTER CLASS C, OUTER GRADE G
WHERE S.SSN = G.SSN
AND G.CCODE = C.CCODE
SELECT S.SSN AS SSN,
FNAME, LNAME
FROM STUDENT_ADMIN.GRADE G
RIGHT OUTER JOIN
STUDENT_ADMIN.STUDENT S
ON G.SSN = S.SSN
LEFT OUTER JOIN
DEPT_ADMIN.CLASS C
ON G.CCODE = C.CCODE
将SELECT语句用作表名
Microsoft SQL Server和Informix可在执行查询时支持将SELECT语句当作表数据源加以使用。SQL Server要求提供别名;而别名的使用在Informix中却是可选项。
Informix
Microsoft SQL Server
SELECT SSN, LNAME, FNAME,
TUITION_PAID, SUM_PAID
FROM STUDENT,
(SELECT SUM(TUITION_PAID) SUM_PAID
FROM STUDENT)
SELECT SSN, LNAME, FNAME,
TUITION_PAID, SUM_PAID
FROM STUDENT_ADMIN.STUDENT,
(SELECT SUM(TUITION_PAID) SUM_PAID
FROM STUDENT_ADMIN.STUDENT) SUM_STUDENT
读取并修改BLOBs
Microsoft SQL Server可在text和image型数据列中将二进制大对象(BLOBs)付诸实现。Informix实现BLOBs的方式为,针对二进制数据使用BLOB或BYTE列,针对文本数据使用CLOB或TEXT列。在Informix中,SELECT指令可对BLOB和CLOB列内数据进行查询。
您可在SQL Server中使用标准Transact-SQL语句或专用READTEXT语句从text和image列读取数据。READTEXT语句允许您读取text或image列的局部片断。Informix并未提供具备相当功能的语句。SQL Server也不具备相当于Informix FILETOBLOB、LOTOFILE和LOCOPY等BLOBs操控函数的语句。
READTEXT语句将就可借助TEXTPTR函数获取的text_pointer对象加以利用。TEXTPTR函数将返回一个指针,该指针即可指向特定行中的text或image数据列,又可在查询操作返回一个以上数据行的情况下指向由查询返回的最后一行中的text或image数据列。由于TEXTPTR函数将返回一个长达16字节的二进制字串,因此,最好声明一个用来存放文本指针的本地变量,并借助READTEXT语句对该变量加以使用。
READTEXT语句可指定将被返回的字节数。@@TEXTSIZE函数中的赋值表示将被返回的字符或字节数量限制。如果这个函数值小于针对READTEXT设定的值,就会取代由READTEXT语句指定的大小。
SET语句能够与TEXTSIZE参数配合使用,这样一来,就能以字节为单位指定由SELECT语句返回的文本数据容量。如果您将TEXTSIZE参数设定为0,那么,可被返回的文本数据容量就会重新设定为缺省值(4 KB)。针对TEXTSIZE参数加以设定的做法将影响到@@TEXTSIZE函数。SQL Server ODBC驱动程序可在SQL_MAX_LENGTH语句选项发生变化时自动设定TEXTSIZE参数。
在Informix中,UPDATE和INSERT指令可供用来修改BLOB、CLOB、TEXT和BYTE列内数值。而在SQL Server中,您既可使用标准UPDATE和INSERT语句,又可使用UPDATETEXT和WRITETEXT语句。UPDATETEXT和WRITETEXT语句都允许使用不支持日志的选项,而UPDATETEXT语句则可实现text或image数据列的局部更新。
UPDATETEXT语句可供用来替换现有数据、删除现有数据或插入新数据。新近插入的数据可以是常量、表名、列名或文本指针。
WRITETEXT语句可对受其影响列中的任何现有数据进行重写。您可借助WRITETEXT语句替换文本数据,或使用UPDATETEXT语句修改文本数据。由于UPDATETEXT语句只对image值的部分文本(而非全部文本)进行修改,因而,具有较强的灵活性。
如需了解更多相关信息,请参阅SQL Server联机丛书。
函数
本章所列表格展现了Informix与SQL Server标量值及聚合函数之间的关系。虽然两种数据管理系统所配备的函数名称可能完全相同,但却在参数个数和类型上存在差异——这一点非常重要。鉴于本文档立足于简化现有Informix应用迁移,因此,本章并未介绍仅由Microsoft SQL Server提供的函数。Informix所不支持的典型函数包括:度量函数(DEGREES)、PI函数(PI)和随机函数(RAND)。
数字/数学函数
下表列示了可由Informix提供支持的数字/数学函数以及Microsoft SQL Server中与它们相对应的函数。
函数 Informix Microsoft SQL Server
绝对值
ABS
相同
反余弦
ACOS
相同
反正弦
ASIN
相同
n的反正切
ATAN
相同
n和m的反正切
ATAN2
ATN2
余弦
COS
相同
指数值
EXP
相同
十六进制值
HEX
无
自然对数
LOGN
LOG
10的对数
LOG10
相同
取模(余数)
MOD
USE MODULO (%) OPERATOR
求幂
POW
POWER
求根
ROOT
无
四舍五入
ROUND
相同
数字符号
无
SIGN
正弦
SIN
相同
平方根
SQRT
相同
正切
TAN
相同
舍位
TRUNC
无
字符函数
下表列示了可由Informix提供支持的字符函数以及Microsoft SQL Server中与它们相对应的函数。
函数 Informix Microsoft SQL Server
将字符转换成小写形式(LOWER)
LOWER
相同
将字符转换成大写形式(LOWER)
UPPER
相同
填充字符串左侧
LPAD
无
删除前导空格
TRIM
LTRIM
删除尾部空格
TRIM
RTRIM
多次重复字符串
RPAD
REPLICATE
重复空格的字符串
RPAD
SPACE
取子串
SUBSTR
SUBSTRING
SUBSTRING
字符替换
REPLACE
STUFF
将字串中每个单词的首写字母转换成大写形式
INITCAP
无
字符串长度
LENGTH
CHAR_LENGTH
CHARACTER_LENGTH
DATALENGTH或LEN
包括空格在内的字符列字节数
OCTET_LENGTH
无
日期函数
下表列示了可由Informix提供支持的日期函数以及Microsoft SQL Server中与它们相对应的函数。
函数 Informix Microsoft SQL Server
日期添加
date column +/- INTERVAL(value)
或
date column +/- DATETIME(value)
或
date column +/- value UNITS datetime unit
DATEADD
日期差距
date column +/- DATETIME(value)
或
date column +/- DATE(value)
DATEDIFF
当前日期和时间
CURRENT
TODAY
GETDATE()
日期的字符串表示形式
DATETIME(value)
DATENAME
日期的整数表示形式
无
DATEPART
日期的四舍五入
DATETIME(value) datetime unit TO datetime unit
CAST
日期截断
DATETIME(value) datetime unit TO datetime unit
CAST
将字符串转变为日期
DATETIME(value)
或
DATE(value)
CAST
将空值转换成日期
无
ISNULL
转换函数
下表列示了可由Informix提供支持的转换函数以及Microsoft SQL Server中与它们相对应的函数。
函数 Informix Microsoft SQL Server
从数字型到字符型
隐含
CONVERT
从字符型到数字型
隐含(在未执行计算的情况下报错)
CONVERT
从日期型到字符型
隐含
CONVERT
从字符型到日期型
隐含(在未执行计算的情况下报错)
CONVERT
从十六进制到二进制
无
CONVERT
从二进制到十六进制
无
CONVERT
其它行级函数
下表列示了可由Informix提供支持的其它行级函数以及Microsoft SQL Server中与它们相对应的函数。
函数 Informix Microsoft SQL Server
返回第一个非空表达式
DECODE
COALESCE
如果exp1 = exp2,则返回空值
DECODE
NULLIF
用户登录ID编号
无
SUSER_ID
用户登录名
USER
SUSER_NAME
用户数据库ID编号
无
USER_ID
用户数据库名
USER
USER_NAME
当前用户
USER
CURRENT_USER
聚合函数
下表列示了可由Informix提供支持的聚合函数以及Microsoft SQL Server中与它们相对应的函数。
函数 Informix Microsoft SQL Server
平均值
AVG
相同
计数
COUNT
相同
最大值
MAX
相同
最小值
MIN
相同
标准差
STDDEV
STDEV或STDEVP
求和
SUM
相同
方差
VARIANCE
VAR或VARP
全距
RANGE
无
条件检验
Informix的DECODE和CASE语句以及Microsoft SQL Server的CASE语句均可执行条件检验。如果test_value变量值与下列表达式相匹配,系统就会返回相关值。如果系统未发现匹配值,则将返回default_value。如果default_value未被指定,DECODE和CASE语句都将在未发现匹配值的情况下返回NULL值。下表展示了两种数据库管理系统的相关语法,并提供了已经转换的DECODE指令示例。
Informix
Microsoft SQL Server
DECODE (test_value,
expression1, value1
[[,expression2, value2] […]]
[,default_value]
)
CASE test_value
WHEN expression1 THEN value1
[[WHEN expression2 THEN value2] [...]]
[ELSE default_value]
END
CREATE VIEW STUDENT_GPA
(SSN, GPA)
AS SELECT SSN, ROUND(AVG(DECODE(grade
,'A', 4
,'A+', 4.3
,'A-', 3.7
,'B', 3
,'B+', 3.3
,'B-', 2.7
,'C', 2
,'C+', 2.3
,'C-', 1.7
,'D', 1
,'D+', 1.3
,'D-', 0.7
,0)),2)
FROM GRADE
GROUP BY SSN
或
CREATE VIEW STUDENT_GPA
(SSN, GPA)
AS SELECT SSN,
ROUND(AVG(CASE grade
WHEN 'A' THEN 4
WHEN 'A+' THEN 4.3
WHEN 'A-' THEN 3.7
WHEN 'B' THEN 3
WHEN 'B+' THEN 3.3
WHEN 'B-' THEN 2.7
WHEN 'C' THEN 2
WHEN 'C+' THEN 2.3
WHEN 'C-' THEN 1.7
WHEN 'D' THEN 1
WHEN 'D+' THEN 1.3
WHEN 'D-' THEN 0.7
ELSE 0
END),2)
FROM GRADE
GROUP BY SSN
CASE test_value
WHEN expression1 THEN value1
[[WHEN expression2 THEN value2] [...]]
[ELSE default_value]
END
CREATE VIEW STUDENT_ADMIN.STUDENT_GPA
(SSN, GPA)
AS SELECT SSN, ROUND(AVG(CASE grade
WHEN 'A' THEN 4
WHEN 'A+' THEN 4.3
WHEN 'A-' THEN 3.7
WHEN 'B' THEN 3
WHEN 'B+' THEN 3.3
WHEN 'B-' THEN 2.7
WHEN 'C' THEN 2
WHEN 'C+' THEN 2.3
WHEN 'C-' THEN 1.7
WHEN 'D' THEN 1
WHEN 'D+' THEN 1.3
WHEN 'D-' THEN 0.7
ELSE 0
END),2)
FROM STUDENT_ADMIN.GRADE
GROUP BY SSN
SQL Server的CASE表达式可支持使用SELECT语句执行布尔测试,而这恰恰是Informix DECODE和CASE指令所不具备的功能。如需了解有关CASE表达式的更多信息,请参阅SQL Server联机丛书。 |
|