函数无法定位程序输入点于动态链接库

无法定位程序输入点于动态链接库  时间:2021-03-01  阅读:()
系统管理指南第二卷SybaseIQ15.
3文档ID:DC01144-01-1530-02最后修订日期:2011年10月版权所有2011Sybase,Inc.
保留所有权利.
除非新版本或技术声明中另有说明,否则本出版物适用于Sybase软件及所有后续版本.
本文档中的信息如有更改,恕不另行通知.
本出版物中描述的软件按许可证协议提供,其使用或复制必须符合协议条款.
要订购其它文档,美国和加拿大的客户请拨打客户服务部门电话(800)685-8225或发传真至(617)229-9845.
持有美国许可证协议的其它国家/地区的客户可通过上述传真号码与客户服务部门联系.
所有其它国际客户请与Sybase子公司或当地分销商联系.
仅在软件的定期发布日期提供升级内容.
未经Sybase,Inc.
的事先书面许可,不得以任何形式、任何手段(电子的、机械的、手工的、光学的或其它手段)复制、传播或翻译本出版物的任何部分.
可在http://www.
sybase.
com/detailid=1011207上的Sybase商标页中查看Sybase商标.
Sybase和列出的标记均是Sybase,Inc.
的商标.
表示已在美国注册.
SAP和此处提及的其它SAP产品与服务及其各自的徽标是SAPAG在德国和世界各地其它几个国家/地区的商标或注册商标.
Java和基于Java的所有标记都是SunMicrosystems,Inc.
在美国和其它国家/地区的商标或注册商标.
Unicode和Unicode徽标是Unicode,Inc.
的注册商标.
本书中提到的所有其它公司和产品名均可能是与之相关的相应公司的商标.
Use,duplication,ordisclosurebythegovernmentissubjecttotherestrictionssetforthinsubparagraph(c)(1)(ii)ofDFARS52.
227-7013fortheDODandassetforthinFAR52.
227-19(a)-(d)forcivilianagencies.
Sybase,Inc.
,OneSybaseDrive,Dublin,CA94568.
目录读者1使用过程和批处理3过程概述3过程的优点3过程简介3创建过程4更改过程4调用过程5在SybaseCentral中复制过程5删除过程5执行过程的权限5在参数中返回过程结果6在结果集中返回过程结果6用户定义的函数简介7创建用户定义的函数7调用用户定义的函数7删除用户定义的函数7执行用户定义的函数的权限7批处理简介8控制语句8使用复合语句9复合语句中的声明9原子复合语句9过程的结构9过程中允许的SQL语句10为过程声明参数10将参数传递给过程10将参数传递给函数11过程结果11使用RETURN语句返回值11作为过程参数返回结果11系统管理指南第二卷iii从过程返回结果集11从过程返回多个结果集12从过程返回可变结果集12过程中的游标12游标管理概述12游标定位12过程中的游标和SELECT语句13过程中的错误和警告13过程中缺省的错误处理13使用ONEXCEPTIONRESUME处理错误13过程中错误和警告的缺省处理13在过程中使用异常处理程序14嵌套的复合语句和异常处理程序14在过程中使用EXECUTEIMMEDIATE语句14过程中的事务和保存点14隐藏过程、函数和视图的内容15批处理中允许的语句15在批处理中使用SELECT语句15使用IQUTILITIES创建自己的存储过程16IQ如何使用IQUTILITIES命令17选择要调用的过程17IQUTILITIES使用的数字17过程测试18使用OLAP19关于OLAP19OLAP优点20OLAP计算20GROUPBY子句扩展21GroupbyROLLUP和GroupbyCUBE22分析函数33简单集合函数33窗口化33数值函数56OLAP规则和限制58目录ivSybaseIQ其它OLAP示例59示例:查询中的窗口函数59示例:含多个函数的窗口60示例:计算累计总和61示例:计算移动平均值61示例:ORDERBY结果62示例:查询中的多个集合函数62示例:对ROWS和RANGE进行比较的窗口构架63示例:不包括当前行的窗口构架64示例:RANGE的窗口构架64示例:Unboundedprecedingandunboundedfollowing65示例:RANGE的缺省窗口构架66OLAP函数的BNF语法67SybaseIQ作为数据服务器75SybaseIQ的客户端/服务器接口75使用iqdsedit配置IQ服务器75Sybase应用程序和SybaseIQ77OpenClient应用程序和SybaseIQ78SybaseIQ作为OpenServer78系统要求79将数据库服务器作为OpenServer启动79配置数据库以与OpenClient一起使用79OpenClient和jConnect连接的特性80具有多个数据库的服务器80访问远程数据83SybaseIQ和远程数据83访问远程数据的要求83远程服务器83外部登录88代理表89示例:两个远程表之间的连接90多个本地数据库91目录系统管理指南第二卷v将本机语句发送到远程服务器91远程过程调用(RPC)91事务管理和远程数据91远程事务管理概述91事务管理的限制92内部操作92查询分析92查询规范化92查询预处理92服务器功能93语句的完整直通93语句的部分直通93远程数据访问故障排除93不支持远程数据的功能93区分大小写94连接问题94查询的一般问题94管理远程数据访问连接94用于进行远程数据访问的服务器类95服务器类概述95基于JDBC的服务器类95JDBC类的配置说明95服务器类sajdbc95服务器类asejdbc96基于ODBC的服务器类97ODBC外部服务器97服务器类saodbc97服务器类aseodbc98服务器类db2odbc98服务器类oraodbc98服务器类mssodbc101服务器类odbc101使用日程表和事件自动完成任务103调度和事件处理简介103目录viSybaseIQ日程表103定义日程表103事件104选择系统事件104定义事件的触发器状态104事件处理程序105开发事件处理程序105日程表和事件深入解析105数据库服务器如何检查系统事件105数据库服务器如何检查预定时间105事件处理程序是如何执行的106调度和事件处理任务106将日程表或事件添加到数据库中106将手动触发的事件添加到数据库中106触发事件处理程序106调试事件处理程序107检索有关事件或日程表的信息107使用JDBC访问数据109JDBC概述109选择JDBC驱动程序110JDBC程序结构110服务器端JDBC功能111客户端与服务器端JDBC连接的区别113建立JDBC连接113使用jConnect从JDBC客户端应用程序建立连接114从服务器端的JDBC类建立连接117使用JDBC访问数据120安装JDBCExamples类120使用JDBC执行插入、更新和删除121向Java方法传递参数122使用JDBC的查询123使用预准备语句进行更有效的访问124插入和检索对象125目录系统管理指南第二卷viiSybasejConnectJDBC驱动程序126SybaseIQ随附的jConnect的版本126jConnect驱动程序文件127在数据库中安装jConnect系统对象127提供服务器的URL128分布式应用程序129Serializable接口130在客户端导入类131分布式应用程序示例131调试数据库中的逻辑133调试数据库简介133调试工具的功能133使用调试工具的要求133教程1:调试工具快速入门133第1课:连接到数据库并启动调试工具134教程2:调试存储过程134教程3:调试Java类134演示数据库Java示例类134在调试工具中显示Java源代码135设置断点135运行方法135单步执行源代码136检查和修改变量136断点137查看和编辑变量行为137编写调试工具脚本137sybase.
asa.
procdebug.
DebugScript类138sybase.
asa.
procdebug.
IDebugAPI接口138sybase.
asa.
procdebug.
IDebugWindow接口.
.
.
.
.
141索引143目录viiiSybaseIQ读者本指南的目标读者是访问SybaseIQ数据库中数据的应用程序的开发人员.
他们熟悉关系数据库系统并具有SybaseIQ产品的入门级用户经验.
请将本指南与文档集内的其它手册结合使用.
读者系统管理指南第二卷1读者2SybaseIQ使用过程和批处理创建与SybaseIQ一起使用的过程和批处理.
过程在数据库中存储过程SQL语句,以供所有应用程序使用.
它们增强了数据库的安全性,提高了效率并促进了标准化.
用户定义的函数是一种类型的过程,它们将值返回到调用环境中,以供查询和其它SQL语句使用.
出于多种目的,服务器端JDBC提供比SQL存储过程更灵活的方法来将逻辑内置于数据库中.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-编程">"SQLAnywhere数据访问API">"SQLAnywhereJDBC驱动程序">"JDBC简介".
批处理是作为一组提交到数据库服务器的SQL语句的集合.
在过程中提供的许多功能(例如控制语句)在批处理中也提供.
过程概述过程在数据库中存储过程SQL语句,以供所有应用程序使用.
它们包括允许SQL语句的重复执行(LOOP语句)和条件执行(IF语句和CASE语句)的控制语句.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"过程和触发器概述".
注意:SybaseIQ不支持触发器.
可以忽略SQLAnywhere文档中有关触发器的信息.
过程的优点过程的定义在数据库中提供,与任何一个数据库应用程序相分离.
这一分离具有许多优点.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"过程和触发器的优点".
过程简介本节讨论可用的过程及其功能.
在使用存储过程时,有两个系统存储过程非常有用:sp_iqprocedure和sp_iqprocparm.
sp_iqprocedure存储过程显示数据库中与系统过程和用户定义过程有关的信息.
sp_iqprocparm存储过程显示有关存储过程参数的信息,包括以下列:proc_name使用过程和批处理系统管理指南第二卷3proc_ownerparm_nameparm_typeparm_modedomain_namewidth,scaledefault另请参见过程结果(第11页)创建过程过程是用CREATEPROCEDURE语句创建的.
您必须具有资源权限才能创建过程.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"过程简介">"创建过程".
SybaseIQ示例注意:例如,使用SybaseIQ演示数据库iqdemo.
db.
CREATEPROCEDUREnew_dept(INidINT,INnameCHAR(35),INhead_idINT)BEGININSERTINTOGROUPO.
departments(DepartmentID,DepartmentName,DepartmentHeadID)values(id,name,head_id);END注意:要在IQ中创建远程过程,必须使用CREATEPROCEDURE的ATlocation-stringSQL语法来创建代理存储过程.
此功能目前仅在Windows和SunSolaris上得到认证.
SybaseCentral中的"创建远程过程向导"(CreateRemoteProcedureWizard)仅适用于远程服务器.
更改过程您可以使用SybaseCentral或InteractiveSQL修改现有过程.
您必须具有DBA权限或是过程的所有者.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"过程简介">"更改过程".
有关更改数据库对象属性的信息,请参见《SybaseIQ简介》>"管理数据库">"管理过程".
有关授予或撤消过程权限的信息,请参见《系统管理指南第一卷》>"管理用户ID和权限">"管理单个用户ID和权限">"在InteractiveSQL中授予针对过程的权限"使用过程和批处理4SybaseIQ以及《系统管理指南第一卷》>"管理用户ID和权限">"管理单个用户ID和权限">"在InteractiveSQL中撤消用户权限".
您还可以使用ALTERPROCEDURE语句来修改过程.
调用过程CALL语句可调用过程.
过程可由应用程序调用,也可以由其它过程调用.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"过程简介">"调用过程".
另请参见执行过程的权限(第5页)在SybaseCentral中复制过程您可以将一个数据库中的过程代码复制到另一个连接的数据库.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"过程简介">"在SybaseCentral中复制过程".
删除过程在创建了过程后,该过程将一直保留在数据库中,直到它被显式删除.
只有该过程的所有者或具有DBA权限的用户才可以从数据库中删除该过程.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"过程简介">"删除过程".
执行过程的权限过程由创建它的用户拥有,即使没有权限,该用户也可以执行它.
可以使用GRANTEXECUTE命令为其他用户授予执行过程的权限.
例如,new_dept过程的所有者可以通过以下语句允许another_user执行new_dept:GRANTEXECUTEONnew_deptTOanother_user以下语句撤消该过程的执行权限:REVOKEEXECUTEONnew_deptFROManother_user请参见《系统管理指南第一卷》>"管理用户ID和权限">"管理单个用户ID和权限">"在InteractiveSQL中授予针对过程的权限".
另请参见调用过程(第5页)使用过程和批处理系统管理指南第二卷5在参数中返回过程结果过程将结果返回到调用环境中.
过程通过以下方式之一返回结果:单独的值作为OUT或INOUT参数返回.
可返回结果集.
可以使用RETURN语句返回单个结果.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"过程简介">"在参数中返回过程结果".
SybaseIQ示例注意:例如,使用SybaseIQ演示数据库iqdemo.
db.
CREATEPROCEDURESalaryList(INdepartment_idINT)RESULT("EmployeeID"INT,"Salary"NUMERIC(20,3))BEGINSELECTEmployeeID,SalaryFROMEmployeesWHEREEmployees.
DepartmentID=department_id;END在结果集中返回过程结果除了在单独参数中将结果返回到调用环境中之外,过程可以在结果集内返回信息.
结果集通常是查询的结果.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"过程简介">"在结果集中返回过程结果".
创建临时表并从中进行选择如果某个过程在存储过程中动态创建临时表并随后选择该表,您必须使用EXECUTEIMMEDIATEWITHRESULTSETON语法来避免出现"未找到列"错误.
例如:CREATEPROCEDUREp1(IN@tvarchar(30))BEGINEXECUTEIMMEDIATE'SELECT*INTO#resultSetFROM'||@t;EXECUTEIMMEDIATEWITHRESULTSETON'SELECT*FROM#resultSet';END使用过程和批处理6SybaseIQ用户定义的函数简介用户定义的函数是一种过程,此类函数将单个值返回到调用环境中.
本节介绍如何创建、使用和删除用户定义的函数.
创建用户定义的函数您可以使用CREATEFUNCTION语句来创建用户定义的函数.
但是,您必须具有RESOURCE授权.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"用户定义的函数简介">"创建用户定义的函数".
有关CREATEFUNCTION语法的完整说明(包括性能注意事项以及SQLAnywhere和IQ之间的区别),请参见《参考:语句和选项》>"SQL语句">"CREATEFUNCTION语句".
调用用户定义的函数在您要使用内置的非集合函数的任何位置,都可以根据权限使用用户定义的函数.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"用户定义的函数简介">"调用用户定义的函数".
SybaseIQ示例注意:例如,使用SybaseIQ演示数据库iqdemo.
db.
SELECTfullname(GivenName,SurName)FROMEmployees;fullname(GivenName,SurName)FranWhitneyMatthewCobbPhilipChin……删除用户定义的函数用户定义的函数一经创建,便会保留在数据库中,直到它被显式删除.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"用户定义的函数简介">"删除用户定义的函数".
执行用户定义的函数的权限用户定义的函数由创建它的用户拥有,即使没有权限,该用户也可以执行它.
用户定义的函数的所有者可以使用GRANTEXECUTE命令向其他用户授予权限.
使用过程和批处理系统管理指南第二卷7例如,fullname函数的创建者可以通过以下语句允许another_user使用fullname:GRANTEXECUTEONfullnameTOanother_user以下语句撤消使用该函数的权限:REVOKEEXECUTEONfullnameFROManother_user请参见《系统管理指南第一卷》>"管理用户ID和权限">"管理单个用户ID和权限">"在InteractiveSQL中授予针对过程的权限".
批处理简介简单的批处理由一组用分号隔开的SQL语句组成.
例如,下面的一组语句构成一个批处理,该批处理创建EasternSales部门并将所有销售代表从Massachusetts(MA)转移到该部门.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"批处理简介".
SybaseIQ示例注意:例如,使用SybaseIQ演示数据库iqdemo.
db.
INSERTINTODepartments(DepartmentID,DepartmentName)VALUES(220,'EasternSales');UPDATEEmployeesSETDepartmentID=220WHEREDepartmentID=200ANDstate='GA';COMMIT;控制语句在过程的主体或在批处理中,有多种用于逻辑流和决策的控制语句.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"控制语句".
有关每个控制语句的完整说明,请参见《参考:语句和选项》>"SQL语句"中的条目.
使用过程和批处理8SybaseIQ使用复合语句复合语句可被嵌套,并且可以与其它控制语句合并在一起,以定义过程中或批处理中的执行流.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"控制语句">"使用复合语句".
另请参见过程中允许的SQL语句(第10页)过程的结构(第9页)过程中的事务和保存点(第14页)复合语句中的声明复合语句中的局部声明紧随在BEGIN关键字之后.
这些局部声明只存在于复合语句内.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"控制语句">"复合语句中的声明".
原子复合语句原子语句是完全执行或根本不执行的语句.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"控制语句">"原子复合语句".
过程的结构过程的主体由复合语句组成.
复合语句由BEGIN和END组成,它们将一组SQL语句括起来,用分号分隔每一语句.
另请参见过程中允许的SQL语句(第10页)过程中的事务和保存点(第14页)使用复合语句(第9页)使用过程和批处理系统管理指南第二卷9过程中允许的SQL语句您可以在过程内使用几乎所有的SQL语句,包括以下各种语句:SELECT、UPDATE、DELETE、INSERT和SETVARIABLE用来执行其它过程的CALL语句控制语句游标语句异常处理语句EXECUTEIMMEDIATE语句下面是一些不能在过程中使用的SQL语句:CONNECT语句DISCONNECT语句可以在过程中使用COMMIT、ROLLBACK和SAVEPOINT语句,但有一些限制.
请参见《参考:语句和选项》>"SQL语句"中每个语句的"用法"一节.
另请参见过程的结构(第9页)过程中的事务和保存点(第14页)使用复合语句(第9页)为过程声明参数过程参数在CREATEPROCEDURE语句中以列表形式出现.
参数名必须符合其它数据库标识符(如列名)的规则.
它们必须具有有效的数据类型,而且必须用关键字IN、OUT或INOUT之一作为前缀.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"过程和触发器的结构">"为过程声明参数".
将参数传递给过程您可以通过CALL语句的两种形式之一,利用存储过程参数的缺省值.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"过程和触发器的结构">"将参数传递给过程".
使用过程和批处理10SybaseIQ将参数传递给函数UDF不通过CALL语句进行调用,而是采用与内置函数同样的方式使用.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"过程和触发器的结构">"将参数传递给函数".
过程结果过程能够以单行数据或多行数据的形式返回结果.
由单行数据组成的结果可作为参数传递回过程.
由多行数据组成的结果作为结果集传递回过程.
过程也可以返回在RETURN语句中给定的单个值.
有关如何从过程返回结果的简单示例,请参见"过程简介".
有关详细信息,请参见以下各节.
另请参见过程简介(第3页)使用RETURN语句返回值RETURN语句将单个整数值返回到调用环境中,并且导致立即从过程退出.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"从过程返回结果">"使用RETURN语句返回值".
作为过程参数返回结果过程可以将结果作为该过程的参数返回到调用环境中.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"从过程返回结果">"作为过程参数返回结果".
从过程返回结果集结果集允许过程将多行结果返回到调用环境中.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"从过程返回结果">"从过程返回结果集".
使用过程和批处理系统管理指南第二卷11从过程返回多个结果集过程可以将多个结果集返回到调用环境中.
dbisql和dbisqlc用来返回多个结果集的方法不同.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"从过程返回结果">"从过程返回多个结果集".
从过程返回可变结果集RESULT子句在过程中是可选的.
通过省略RESULT子句,您可以编写返回不同结果集的过程,结果集内具有不同数目或类型的列,具体情况取决于执行它们的方式.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"从过程返回结果">"从过程返回可变结果集".
过程中的游标游标在其结果集内从具有多行的查询或存储过程中一次检索一行.
游标是查询或过程的句柄或标识符,也是结果集内的当前位置的句柄或标识符.
游标管理概述管理游标类似于通过编程语言管理文件.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"在过程和触发器中使用游标">"游标管理概述".
sp_iqcursorinfo存储过程可显示有关在服务器上当前打开的游标的信息.
有关详细信息,请参见《参考:构件块、表和过程》>"系统过程">"sp_iqcursorinfo过程".
游标定位游标定位极其灵活.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-编程">"使用SQLAnywhere编程简介">"在应用程序中使用SQL">"使用游标">"游标定位".
注意:SybaseIQ从结果集的开头处理FIRST、LAST和ABSOLUTE选项.
它将行计数为负值的RELATIVE视为从当前位置开始.
使用过程和批处理12SybaseIQ过程中的游标和SELECT语句TopCustomerValue过程在SELECT语句上使用游标并基于ListCustomerValue过程中使用的同一查询.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"在过程和触发器中使用游标">"在过程中在SELECT语句上使用游标".
过程中的错误和警告在应用程序执行SQL语句后,它可以检查返回码(或状态码)以了解是否有错误.
返回码指示所执行的语句是成功还是失败,并给出失败的原因.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"过程和触发器中的错误和警告".
注意:SybaseIQ不支持触发器.
可以忽略SQLAnywhere文档中有关触发器的信息.
过程中缺省的错误处理SybaseIQ会处理过程执行期间发生的错误.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"过程和触发器中的错误和警告">"过程和触发器中缺省的错误处理".
注意:SybaseIQ不支持触发器.
可以忽略SQLAnywhere文档中有关触发器的信息.
使用ONEXCEPTIONRESUME处理错误ONEXCEPTIONRESUME子句包括在CREATEPROCEDURE语句中.
发生错误时,过程会检查语句.
如果该语句处理错误,则在发生错误时该过程不返回对调用环境的控制.
相反它继续执行,在导致错误的语句处继续执行.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"过程和触发器中的错误和警告">"使用ONEXCEPTIONRESUME处理错误".
过程中错误和警告的缺省处理在过程中,系统对错误和警告的处理方式不同.
对错误的缺省操作是为SQLSTATE和SQLCODE变量设置值,并且在遇到错误时将控制返回到调用环境;对警告的缺省操作是设置SQLSTATE和SQLCODE值,并且继续执行过程.
使用过程和批处理系统管理指南第二卷13请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"过程和触发器中的错误和警告">"过程和触发器中警告的缺省错误处理".
注意:SybaseIQ不支持触发器.
您可以忽略SQLAnywhere文档中有关触发器的信息.
在过程中使用异常处理程序您可以在过程内截取并处理某些类型的错误,而不是将错误传递回调用环境.
上述操作是通过使用异常处理程序执行的.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"过程和触发器中的错误和警告">"在过程和触发器中使用异常处理程序".
注意:SybaseIQ不支持触发器.
可以忽略SQLAnywhere文档中有关触发器的信息.
嵌套的复合语句和异常处理程序嵌套的复合语句可用于增强用户相关控制,以控制哪些语句在出现错误之后仍执行,哪些语句不执行.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"过程和触发器中的错误和警告">"嵌套的复合语句和异常处理程序".
在过程中使用EXECUTEIMMEDIATE语句EXECUTEIMMEDIATE语句允许使用文字字符串(在引号中)和变量的组合,在过程内编译语句.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"在过程中使用EXECUTEIMMEDIATE语句".
过程中的事务和保存点过程或触发器中的SQL语句是当前事务的一部分.
您可以在一个事务内调用若干过程,或在一个过程中具有若干事务.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"过程和触发器中的事务和保存点".
注意:SybaseIQ不支持触发器.
可以忽略SQLAnywhere文档中有关触发器的信息.
使用过程和批处理14SybaseIQ有关详细信息,请参见《系统管理指南第一卷》>"事务和版本控制">"事务内的保存点".
另请参见过程中允许的SQL语句(第10页)过程的结构(第9页)使用复合语句(第9页)隐藏过程、函数和视图的内容在某些情况下,当您分发应用程序和数据库时,可能不希望公开过程、函数、触发器和视图中包含的逻辑.
作为附加的安全手段,您可以使用ALTERPROCEDURE、ALTERFUNCTION和ALTERVIEW语句的SETHIDDEN子句来隐藏这些对象的内容.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"隐藏过程、函数、触发器和视图的内容".
注意:SybaseIQ不支持触发器.
可以忽略SQLAnywhere文档中有关触发器的信息.
有关详细信息,请参见《参考:语句和选项》中的ALTERFUNCTION语句、ALTERPROCEDURE语句和ALTERVIEW语句.
批处理中允许的语句批处理中可以接受大多数SQL语句,但也有一些例外.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"过程、触发器、事件和批处理中允许的语句".
注意:SybaseIQ不支持触发器.
可以忽略SQLAnywhere文档中有关触发器的信息.
在批处理中使用SELECT语句可以在批处理中包括一个或多个SELECT语句.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"使用过程、触发器和批处理">"过程、触发器、事件和批处理中允许的语句">"在批处理中使用SELECT语句".
SybaseIQ示例注意:例如,使用SybaseIQ演示数据库iqdemo.
db.
使用过程和批处理系统管理指南第二卷15IFEXISTS(SELECT*FROMSYSTABWHEREtable_name='Employees')THENSELECTSurnameASLastName,GivenNameASFirstNameFROMEmployees;SELECTSurname,GivenNameFROMCustomers;SELECTSurname,GivenNameFROMContacts;ELSEMESSAGE'TheEmployeestabledoesnotexist'TOCLIENT;ENDIF使用IQUTILITIES创建自己的存储过程SybaseIQ中提供的系统存储过程可以在SQL中,借助于本章其余部分介绍的方法来实现.
您必须按照与系统存储过程完全相同的方式使用本地临时表和IQUTILITIES语句:警告!
违反这些规则可能会导致IQ服务器或数据库出现严重问题.
过程的所有SQL代码均会被加密并编译到共享库libiqscripts15_r.
so文件(在Unix上)和iqscripts15.
dll文件(在Windows上)中.
您可以使用SybaseCentral或在InteractiveSQL中输入sp_helptext'owner.
procname'来查看存储过程代码.
IQUTILITIES的语法为:IQUTILITIESMAININTOlocal-temp-table-namearguments《参考:语句和选项》中仅记录了针对IQ监视器的IQUTILITIES命令,这是由于该命令的使用要求非常严格,如果使用不当,会使系统运行面临风险.
您可能希望为其中某些过程创建自己的变体.
下面是一些具体操作方法:1.
创建一个调用系统存储过程的过程.
2.
创建一个与系统存储过程无关但是执行类似功能的过程.
3.
创建一个与系统存储过程使用相同结构但是提供其它功能的过程.
例如,您可能希望在前端工具或浏览器中以图形(而不是文本)方式显示过程结果.
4.
如果您选择第二个或第三个选项,则需要了解IQUTILITIES语句以及使用该语句而需要满足的严格要求.
使用过程和批处理16SybaseIQIQ如何使用IQUTILITIES命令IQUTILITIES是基础语句,它会在您运行大多数IQ系统过程时执行.
在大多数情况下,用户并不知道IQUTILITIES正在执行.
用户仅在运行IQ缓冲区高速缓存监视器时才会直接发出IQUTILITIES.
IQUTILITIES提供一种系统方法来收集和报告IQ系统表中所维护的信息.
没有通用的用户界面,您只能按照与现有系统过程相同的方法来使用IQUTILITIES.
系统过程声明用来存储信息的本地临时表.
它们执行IQUTILITIES来从系统表获得信息并将这些信息存储在本地临时表中.
系统过程可以只是报告本地临时表中的信息,也可以执行其它处理.
在某些系统过程中,IQUTILITIES语句包括一个预定义的数字作为它的某个参数.
这个数字执行特定的函数,例如,从系统表中的信息派生值.
有关可用作IQUTILITIES参数的数字列表,请参见"表1".
选择要调用的过程您可以安全地使用IQUTILITIES来基于所说明的系统过程创建自己的版本,并用其报告数据库中的信息.
例如,sp_iqspaceused显示有关IQ主存储和IQ临时存储中已用空间和可用空间的信息.
检查您基于系统存储过程所创建过程的所有者,确保您所创建版本的过程具有正确的所有者.
请勿基于系统过程创建用来控制IQ操作的过程.
修改用来控制IQ操作的过程可能会导致严重问题.
IQUTILITIES使用的数字下表列出了在IQUTILITIES命令中用作参数的数字以及使用每个数字的系统过程.
有关这些过程的功能的信息,请参见《参考:构件块、表和过程》>"系统过程".
表1.
系统过程中使用的IQUTILITIES值数字过程注释10000sp_iqtransaction20000sp_iqconnection和sp_iqmpxcountdbremote30000sp_iqspaceused40000sp_iqspaceinfo50000sp_iqlocks60000sp_iqmpxversionfetch不使用使用过程和批处理系统管理指南第二卷17数字过程注释70000sp_iqmpxdumptlvlog80000sp_iqcontext100000sp_iqindexfragmentation110000sp_iqrowdensity过程测试请始终首先在开发环境中测试您的过程.
在生产环境中运行过程之前首先对过程进行测试有助于维护IQ服务器和数据库的稳定性.
使用过程和批处理18SybaseIQ使用OLAPOLAP(联机分析处理)是对存储在关系数据库中的信息执行数据分析的有效方法.
使用OLAP,可以基于不同的维度对数据进行分析,获取含小计行的结果集,以及将数据组织成多维CUBE,所有这些操作均可通过一个SQL查询完成.
您也可以使用过滤器深入分析数据,从而快速返回结果集.
本章介绍了SybaseIQ支持的SQL/OLAP功能.
注意:OLAP示例中显示的表位于iqdemo数据库中.
关于OLAP这些分析函数(使用它们,可以通过一个SQL语句执行复杂数据分析)通过一种名为"联机分析处理"(OLAP)的软件技术来执行.
以下列表中显示了此类函数:GROUPBY子句扩展-CUBE和ROLLUP分析函数:简单集合-AVG、COUNT、MAX、MIN、SUM、STDDEV和VARIANCE注意:您可以将除Grouping()以外的简单集合函数与OLAP窗口函数结合使用.
窗口函数:窗口化集合-AVG、COUNT、MAX、MIN和SUM排名函数-RANK、DENSE_RANK、PERCENT_RANK和NTILE统计函数-STDDEV、STDDEV_SAMP、STDDEV_POP、VARIANCE、VAR_POP、VAR_SAMP、REGR_AVGX、REGR_AVGY、REGR_COUNT、REGR_INTERCEPT、REGR_R2、REGR_SLOPE、REGR_SXX、REGR_SXY、REGR_SYY、CORR、COVAR_POP、COVAR_SAMP、CUME_DIST、EXP_WEIGHTED_AVG和WEIGHTED_AVG.
分布函数-PERCENTILE_CONT和PERCENTILE_DISC数值函数-WIDTH_BUCKET、CEIL、LN、EXP、POWER、SQRT和FLOOR已经对1999SQL标准进行了修订,即引入了包括复杂数据分析的ANSISQL标准扩展.
SybaseIQ中加入了这些SQL增强中的部分内容,可针对扩展提供其它全面支持.
有些数据库产品会提供一个单独的OLAP模块,您在分析数据之前需要先将数据从数据库移至该OLAP模块中.
与此不同,SybaseIQ将OLAP功能内置在数据库本身当中,从而使您可以轻松而无缝地进行部署以及与其它数据库功能(如存储过程)集成.
使用OLAP系统管理指南第二卷19OLAP优点OLAP函数与GROUPING、CUBE和ROLLUP扩展组合使用时,具有以下两大优点.
首先,利用它们,可以执行多维数据分析、数据采集、时序分析、趋势分析、成本分配、目标寻求、即席多维结构更改、非过程建模,以及异常警告,执行这些操作时通常是利用一个SQL语句.
其次,窗口集合函数和报告聚合函数使用一个名为window的关系运算符,与使用自连接或相关子查询的同语义查询相比,该运算符可以更有效地执行.
使用OLAP获得的结果集可以包含小计行,并且可以组织成多维CUBE.
请参见"窗口化".
可计算各种区间的移动平均值和移动总和,在所选列值改变时重置集合和秩,以及使用简单的术语来表示复杂的比值.
在一个查询表达式的范围内,您可以定义多个不同的OLAP函数,每个函数都有它自己的分区规则.
另请参见分布函数(第53页)OLAP计算(第20页)排名函数(第43页)统计集合函数(第49页)窗口化(第33页)窗口化集合函数(第47页)OLAP函数的BNF语法(第67页)OLAP计算OLAP计算可概念化为多个查询执行阶段,这些阶段共同配合来生成最终结果.
您可以通过查询中的相关子句来标识执行的OLAP阶段.
例如,如果SQL查询规范包含窗口函数,则会首先处理WHERE、JOIN、GROUPBY和HAVING子句.
分区是在GROUPBY子句中定义组之后、对查询的ORDERBY子句中的最终SELECT列表进行计算之前创建的.
为了进行分组,将所有空值视为属于同一组,即使空值彼此不相等也是如此.
HAVING子句充当过滤器(与WHERE子句非常相似),用于过滤GROUPBY子句的结果.
请考虑涉及ANSISQL标准中的SQL语句和子句(SELECT、FROM、WHERE、GROUPBY和HAVING)的简单查询规范的语义:1.
查询生成一组满足FROM子句中存在的表表达式的行.
2.
WHERE子句中的谓词应用到表中的行.
不满足WHERE子句条件的行(不等于True)将被拒绝.
3.
除集合函数外,系统还会为其余每一行计算SELECT列表和GROUPBY子句中的表达式.
使用OLAP20SybaseIQ4.
结果行根据GROUPBY子句中表达式的不同的值组合在一起,并将空值视为每个域中的特殊值.
如果存在PARTITIONBY子句,则GROUPBY子句中的表达式充当分区键.
5.
对于每个分区,系统将计算SELECT列表或HAVING子句中存在的集合函数.
单个表行一旦集合在一起,便无法再显示在中间结果集中.
新结果集包含GROUPBY表达式以及为每个分区计算的集合函数的值.
6.
HAVING子句中的条件应用到结果组.
不满足HAVING子句的组将被删除.
7.
结果根据PARTITIONBY子句中定义的边界进行分区.
系统将为结果窗口计算OLAP窗口函数(秩和集合).
图1:对OLAP的SQL处理请参见"语法规则2".
另请参见"OLAP函数的BNF语法".
另请参见分布函数(第53页)OLAP优点(第20页)排名函数(第43页)统计集合函数(第49页)窗口化(第33页)窗口化集合函数(第47页)OLAP函数的BNF语法(第67页)GROUPBY子句扩展使用GROUPBY子句的扩展,应用程序开发人员可以编写用于执行以下操作的复杂SQL语句:将输入行以多维形式分区,并将结果组的多个子集合并.
创建"数据CUBE",从而提供稀疏的多维结果集以进行数据采集分析.
创建包含原始组(并且也可包含小计和总计行)的结果集.
OLAPGrouping()操作(如ROLLUP和CUBE)可概念化为前缀和小计行.
前缀前缀列表是为任何包含GROUPBY子句的查询而构造的.
前缀是GROUPBY子句中项的子集,并且是通过从查询的GROUPBY子句中的项中排除最右侧的一个或多个项构造而成的.
排除后所剩余的列称为前缀列.
使用OLAP系统管理指南第二卷21ROLLUP示例1-在以下ROLLUP示例查询中,GROUPBY列表包括Year和Quarter这两个变量:SELECTyear(OrderDate)ASYear,quarter(OrderDate)ASQuarter,COUNT(*)OrdersFROMSalesOrdersGROUPBYROLLUP(Year,Quarter)ORDERBYYear,Quarter查询的两个前缀是:ExcludeQuarter-前缀列的集包含一个列Year.
ExcludebothQuarterandYear–不存在前缀列.
注意:GROUPBY列表包含与项数量相同的前缀.
GroupbyROLLUP和GroupbyCUBEROLLUP和CUBE是指定常见分组前缀的语法快捷方式.
GroupbyROLLUPROLLUP运算符要求以参数的方式提供分组表达式的有序列表.
ROLLUP语法.
SELECT…[GROUPING(column-name)…]…GROUPBY[expression[,…]|ROLLUP(expressionGROUPING采用列名作为参数,并返回下表中所列的布尔值:表2.
使用ROLLUP运算符时GROUPING返回的值如果结果值是GROUPING将返回由ROLLUP运算创建的空值1(TRUE)指示该行是小计所在行的空值1(TRUE)并非由ROLLUP运算创建0(FALSE)使用OLAP22SybaseIQ如果结果值是GROUPING将返回存储的空值0(FALSE)ROLLUP首先计算GROUPBY子句中指定的标准集合值.
然后,ROLLUP在整个分组列的列表中从右侧移到左侧,并以累积方式创建更高级别的小计.
在结尾处创建总计.
如果n代表分组列数,则ROLLUP会创建n+1个级别的小计.
此SQL语法.
.
.
定义以下集.
.
.
GROUPBYROLLUP(A,B,C);(A,B,C)(A,B)(A)()ROLLUP和小计行ROLLUP等同于一组GROUPBY查询的UNION.
以下查询的结果集是相同的.
GROUPBY(A,B)的结果集包括所有那些A和B保持不变的行的小计.
要实现联合,可为列C分配空值.
此ROLLUP查询.
.
.
等同于未进行ROLLUP的此查询.
.
.
selectyear(orderdate)asyear,quarter(orderdate)asQuarter,count(*)OrdersfromSalesOrdersgroupbyRollup(year,quarter)orderbyyear,quarterSelectnull,null,count(*)OrdersfromSalesOrdersunionallSELECTyear(orderdate)ASYEAR,NULL,count(*)OrdersfromSalesOrdersGROUPBYyear(orderdate)unionallSELECTyear(orderdate)asYEAR,quarter(orderdate)asQUATER,count(*)OrdersfromSalesOrdersGROUPBYyear(orderdate),quarter(orderdate)小计行可以帮助您分析数据,尤其是在以下情况下:有大量数据、数据有不同的维数、数据包含在不同的表甚至完全不同的数据库中.
例如,一名销售经理可能会发现按销售代表、区域和季度进行分类的有关销售数据的报告对于了解销售模式十分有用.
数据小计可让销售经理从不同的角度了解总体销售情况.
如果根据销售经理要比较的条件提供了摘要信息,分析此数据就会更加容易.
使用OLAP,用户看不到分析和计算行和列小计的过程.
使用OLAP系统管理指南第二卷23图2:小计1.
此步骤生成尚未考虑ROLLUP的中间结果集.
2.
计算小计并将其附加到结果集中.
3.
行根据查询中的ORDERBY子句排列.
空值和小计行当GROUPBY运算的输入行包含空值时,可能会将由ROLLUP或CUBE运算添加的小计行与包含的空值属于原始输入数据的行混淆.
Grouping()函数通过以下方法将小计行与其它行区分开:采用GROUPBY列表中的列作为它的参数,并在该列为空值时(因为行是小计行)返回1,在该列不为空值时返回0.
下面的示例在结果集中包括Grouping()列.
包含空值作为输入数据结果的行突出显示,小计行则不会.
Grouping()列会突出显示.
查询是Employees表和SalesOrders表之间的外连接.
查询选择居住在德克萨斯、纽约或加利福尼亚的女雇员.
空值会显示在与不是销售代表(因而没有销售额)的那些女雇员相对应的列中.
注意:例如,使用SybaseIQ演示数据库iqdemo.
db.
SELECTEmployees.
EmployeeIDasEMP,year(OrderDate)asYEAR,count(*)asORDERS,grouping(EMP)asGE,grouping(YEAR)asGYFROMEmployeesLEFTOUTERJOINSalesOrdersonEmployees.
EmployeeID=SalesOrders.
SalesRepresentativeWHEREEmployees.
SexIN('F')ANDEmployees.
StateIN('TX','CA','NY')GROUPBYROLLUP(YEAR,EMP)ORDERBYYEAR,EMP前面的查询返回:EMPYEARORDERSGEGYNULLNULL510NULLNULL16911102NULL100309NULL1001062NULL1001090NULL1001507NULL100NULL200098106672000340094920003100使用OLAP24SybaseIQ114220003300NULL200166106672001200094920012200114220012400对于每个前缀,小计行是对应于所有那些前缀列具有相同值的行而构建的.
为了说明ROLLUP结果,请再看一下示例查询:SELECTyear(OrderDate)ASYear,quarter(OrderDate)ASQuarter,COUNT(*)OrdersFROMSalesOrdersGROUPBYROLLUP(Year,Quarter)ORDERBYYear,Quarter在此查询中,包含Year列的前缀位于Year=2000的汇总行和Year=2001的汇总行前面.
前缀的单一汇总行不包括列,该行是中间结果集中所有行的小计.
小计行中每一列的值如下:前缀中包括的列-列的值.
例如,在上一查询中Year=2000的行的小计中,Year列的值为2000.
从前缀中排除的列–空值.
例如,对于由包含Year列的前缀生成的小计行,Quarter列中的值为空值.
集合函数–所排除的列的值的集合.
小计值是针对基础数据中的行而不是集合行而计算的.
在许多情况下,例如,使用SUM或COUNT时,结果都是相同的,但是,在使用AVG、STDDEV和VARIANCE这样的统计函数时,结果是不同的,因而这时差别就很重要.
对ROLLUP运算符的限制如下:ROLLUP运算符支持除COUNTDISTINCT和SUMDISTINCT以外所有可用于GROUPBY子句的集合函数.
ROLLUP只能用在SELECT语句中;子查询中无法使用ROLLUP.
当前不支持将多个ROLLUP、CUBE和GROUPBY列组合在同一个GROUPBY子句中的分组规范.
不支持以常量表达式作为GROUPBY键.
有关表达式的一般格式,请参见《参考:构件块、表和过程》>"表达式"以及《参考:构件块、表和过程》>"SQL语言元素".
ROLLUP示例2-以下示例说明了ROLLUP和GROUPING的用法并显示了由GROUPING创建的一组掩码列.
显示在列S、N和C中的数字0和1是由GROUPING返回的值,表示ROLLUP结果的值.
程序可通过使用掩码"011"标识小计行,使用"111"标识总计行来分析此查询的结果.
SELECTsize,name,color,SUM(quantity),GROUPING(size)ASS,GROUPING(name)ASN,GROUPING(color)ASCFROMProducts使用OLAP系统管理指南第二卷25GROUPBYROLLUP(size,name,color)HAVING(S=1orN=1orC=1)ORDERBYsize,name,color;前面的查询返回:sizenamecolorSUMSNC(NULL)(NULL)(NULL)496111Large(NULL)(NULL)71011LargeSweatshirt(NULL)71001Medium(NULL)(NULL)134011MediumShorts(NULL)80001MediumTeeShirt(NULL)54001Onesizefitsall(NULL)(NULL)263011OnesizefitsallBaseballCap(NULL)124001OnesizefitsallTeeShirt(NULL)75001OnesizefitsallVisor(NULL)64001Small(NULL)(NULL)28011SmallTeeShirt(NULL)28011注意:在Rollup示例2结果中,SUM列显示为SUM(products.
quantity).
ROLLUP示例3-以下示例说明了如何使用GROUPING来区分存储空值和ROLLUP运算创建的"空"值.
之后,存储空值在列prod_id中显示为[空],而ROLLUP创建的"空"值在PROD_IDS列中由ALL替换,如查询中所指定.
SELECTyear(ShipDate)ASYear,ProductID,SUM(quantity)ASOSum,CASEWHENGROUPING(Year)=1THEN'ALL'ELSECAST(YearASchar(8))END,CASEWHENGROUPING(ProductID)=1THEN'ALL'ELSECAST(ProductIDaschar(8))ENDFROMSalesOrderItemsGROUPBYROLLUP(Year,ProductID)HAVINGOSum>36ORDERBYYear,ProductID;前面的查询返回:YearProductIDOSum.
.
.
(Year)ProductID).
.
.
NULLNULL28359ALLALL2000NULL176422000ALL200030014762000300200030114402000301200030211522000302200040019462000400200040115962000401200050017042000500使用OLAP26SybaseIQ2000501157220005012000600212420006002000601193220006012000700270020007002001NULL107172001ALL20013008882001300200130194820013012001302996200130220014001332200140020014011105200140120015009482001500200150193620015012001600936200160020016017922001601200170018362001700ROLLUP示例4-下面的示例查询返回按年和季度汇总销售订单数的数据.
SELECTyear(OrderDate)ASYear,quarter(OrderDate)ASQuarter,COUNT(*)OrdersFROMSalesOrdersGROUPBYROLLUP(Year,Quarter)ORDERBYYear,Quarter下图说明了查询结果,并突出显示了结果集中的小计行.
每个小计行在计算小计时所针对的列中的值为空值.
行[1]表示两年(2000、2001)和所有季度的订单总数.
该行在Year列和Quarter列中的值均为空值,并且是所有列均未包括在前缀中的行.
注意:每个ROLLUP运算返回的结果集均含有这样一行:除集合列外,每个列中均显示空值.
该行表示针对其执行集合函数的每列的汇总.
例如,如果SUM是正在讨论的集合函数,则该行将表示所有值的总和.
行[2]分别表示2000年和2001年的订单总数.
这两个行的Quarter列中均为空值,原因是:该列中的值会累计,从而为Year提供小计.
结果集中这种行的数目取决于ROLLUP查询中出现的变量数.
使用OLAP系统管理指南第二卷27标有[3]的其余行通过提供两年内每个季度的订单总数而提供摘要信息.
ROLLUP示例5-此ROLLUP运算示例返回一个略加复杂的结果集,该结果集按年份、季度和区域汇总销售订单数.
在此示例中,只检查第一季度和第二季度以及两个选定区域(加拿大和东部地区).
SELECTyear(OrderDate)ASYear,quarter(OrderDate)ASQuarter,region,COUNT(*)ASOrdersFROMSalesOrdersWHEREregionIN('Canada','Eastern')ANDquarterIN(1,2)GROUPBYROLLUP(Year,Quarter,Region)ORDERBYYear,Quarter,Region下图说明了从上述查询得到的结果集.
每个小计行在计算小计时所针对的列中的值为空值.
行[1]是所有行的集合,在Year、Quarter和Region列中包含空值.
此行的Orders列中的值表示加拿大和东部地区在2000年和2001年第1季度和第2季度的订单总数.
标有[2]的行表示加拿大和东部地区每年(2000年和2001年)第1季度和第2季度的销售订单总数.
这些行[2]的值等于行[1]中呈现的总数.
标有[3]的行按区域提供有关给定年份和季度的订单总数的数据.
使用OLAP28SybaseIQ标有[4]的行在结果集中提供了有关每年、每季度和每个区域的订单总数的数据.
使用OLAP系统管理指南第二卷29GroupbyCUBEGROUPBY子句中的CUBE运算符通过以多维形式将数据分组(分组表达式)来分析数据.
CUBE需要一个有序维度列表作为参数,它让SELECT语句计算您在查询中指定的维度组的所有可能组合的小计,并生成一个结果集来显示选定列中值的所有组合的集合.
CUBE语法:SELECT…[GROUPING(column-name)…]…GROUPBY[expression[,…]|CUBE(expression[,…])]GROUPING采用列名作为参数,并返回下表中所列的布尔值:表3.
使用CUBE运算符时GROUPING返回的值如果结果值是GROUPING将返回由CUBE运算创建的空值1(TRUE)指示该行是小计所在行的空值1(TRUE)并非由CUBE运算创建0(FALSE)存储的空值0(FALSE)当维度不是同一层次的一部分时,CUBE特别有用.
此SQL语法.
.
.
定义以下集.
.
.
GROUPBYCUBE(A,B,C);(A,B,C)(A,B)(A,C)(A)(B,C)(B)(C)()对CUBE运算符的限制如下:CUBE运算符支持所有可用于GROUPBY子句的集合函数,但COUNTDISTINCT或SUMDISTINCT当前不支持CUBE.
逆分布分析函数PERCENTILE_CONT和PERCENTILE_DISC当前不支持CUBE.
使用OLAP30SybaseIQCUBE只能用在SELECT语句中;SELECT子查询中无法使用CUBE.
当前不支持将ROLLUP、CUBE和GROUPBY列组合在同一个GROUPBY子句中的GROUPING规范.
不支持以常量表达式作为GROUPBY键.
注意:如果CUBE的大小超过临时高速缓存的大小,CUBE的性能将会下降.
GROUPING可与CUBE运算符配合使用来区分存储空值和CUBE创建的查询结果中的空值.
请参见ROLLUP运算符说明中的示例,以了解如何使用GROUPING函数解释结果.
所有CUBE运算返回的结果集均至少有一行在除集合列以外的每个列中显示空值.
该行表示针对其执行集合函数的每列的汇总.
CUBE示例1-下列查询使用人口统计中的数据,包括州/省(地理位置)、性别、受教育水平,以及人员收入.
第一个查询包含一个GROUPBY子句,该子句根据表census中列state、gender和education的值将查询结果组织成行组,并计算每一组的平均收入和总计.
此查询只使用GROUPBY子句(不带CUBE运算符)来将行分组.
SELECTState,Sexasgender,DepartmentID,COUNT(*),CAST(ROUND(AVG(Salary),2)ASNUMERIC(18,2))ASAVERAGEFROMemployeesWHEREstateIN('MA','CA')GROUPBYState,Sex,DepartmentIDORDERBY1,2;以上查询的结果:stategenderDepartmentIDCOUNT()AVERAGECAF200258650.
00CAM200139300.
00如果要根据州/省、性别和受教育情况计算整个人口统计中的平均收入,并计算列state、gender和education的所有可能组合的平均收入,同时只遍历一次人口统计数据,请使用GROUPBY子句的CUBE扩展.
例如,如果要计算所有州/省的所有女性的平均收入,或者要根据所受教育和地理位置计算人口统计中所有人的平均收入,请使用CUBE运算符.
当CUBE计算组时,系统会为计算其组的列生成空值.
必须使用GROUPING函数确定某个空值是存储在数据库中的空值,还是从CUBE生成的空值.
如果已将指定列合并到更高级别的组中,则GROUPING函数返回1.
CUBE示例2-以下查询说明了如何将GROUPING函数与GROUPBYCUBE结合使用.
SELECTcasegrouping(State)WHEN1THEN'ALL'ELSEStateENDASc_state,casegrouping(sex)WHEN1THEN'ALL'ELSESexendASc_gender,casegrouping(DepartmentID)WHEN1THEN'ALL'ELSEcast(DepartmentIDaschar(4))endASc_dept,COUNT(*),CAST(ROUND(AVG(salary),2)ASNUMERIC(18,2))ASAVERAGEFROMemployeesWHEREstateIN('MA','CA')GROUPBYCUBE(state,sex,DepartmentID)ORDERBY1,2,3;使用OLAP系统管理指南第二卷31下面显示了此查询的结果.
系统将按照查询中的指定,在小计行中将CUBE生成的指示小计行的空值替换为ALL.
c_statec_genderc_deptCOUNT()AVERAGEALLALL200352200.
00ALLALLALL352200.
00ALLF200258650.
00ALLFALL258650.
00ALLM200139300.
00ALLMALL139300.
00CAALL200352200.
00CAALLALL352200.
00CAF200258650.
00CAFALL258650.
00CAM200139300.
00CAMALL139300.
00CUBE示例3-在此示例中,查询返回一个汇总订单总数的结果集,然后按年和季度计算订单数小计.
注意:随着待比较变量数量的增加,CUBE的计算成本呈指数增长.
SELECTyear(OrderDate)ASYear,quarter(OrderDate)ASQuarter,COUNT(*)OrdersFROMSalesOrdersGROUPBYCUBE(Year,Quarter)ORDERBYYear,Quarter下图显示的是从查询得到的结果集.
在结果集中突出显示小计行.
每个小计行在计算小计所针对的列中的值为空值.
第一个突出显示的行[1]表示两年和所有季度内的订单总数.
Orders列中的值是每个标有[3]的行中值的总和.
它也是标有[2]的行中的四个值的总和.
使用OLAP32SybaseIQ下一组突出显示的行[2]按季度显示两年内的订单总数.
标有[3]的两个行分别显示2000年和2001年的所有季度的订单总数.
分析函数SybaseIQ既提供简单集合函数,又提供窗口集合函数,利用这些函数,可以通过一个SQL语句执行复杂数据分析.
可以使用这些函数计算查询(如"WhatisthequarterlymovingaverageoftheDowJonesIndustrialaverage"或"Listallemployeesandtheircumulativesalariesforeachdepartment")的结果.
可计算各个区间的移动平均值和累计总和,并且可对集合和秩进行分区以便集合计算在分区值改变时重置.
在单个查询表达式的范围内,您可以定义多个不同的OLAP函数,每个函数都有它自己的任意分区规则.
分析函数可分为两种类别:简单集合函数(如AVG、COUNT、MAX、MIN和SUM)可对数据库的一组行中的数据进行汇总.
这些组是使用SELECT语句的GROUPBY子句构成的.
采用一个参数的一元统计集合函数包括STDDEV、STDDEV_SAMP、STDDEV_POP、VARIANCE、VAR_SAMP和VAR_POP.
简单集合类别和一元集合类别汇总数据库中某一组行的数据,并且可在处理结果集时与窗口规范配合使用来计算结果集的移动窗口.
注意:集合函数AVG、SUM、STDDEV、STDDEV_POP、STDDEV_SAMP、VAR_POP、VAR_SAMP和VARIANCE不支持二进制数据类型BINARY和VARBINARY.
简单集合函数简单集合函数(如AVG、COUNT、MAX、MIN和SUM)可对数据库的一组行中的数据进行汇总.
这些组是使用SELECT语句的GROUPBY子句构成的.
只能在选择列表中以及SELECT语句的HAVING和ORDERBY子句中使用这些集合.
注意:除Grouping()函数以外,简单集合和一元集合都可以在将纳入SQL查询规范(一个窗口,可在处理结果集时在概念上为该结果集创建移动窗口)的窗口函数中使用.
请参见《参考:构件块、表和过程》>"SQL函数">"集合函数".
窗口化OLAP的ANSISQL扩展的一个主要特征是:它具有一个名为窗口的结构.
利用此窗口化扩展,用户可以将查询(或查询的逻辑分区)的结果集分成名为"分区"的行组,并确定要与当前行集合的行的子集.
您可以对窗口使用三类窗口函数:排名函数、行计算函数和窗口集合函数.
::=使用OLAP系统管理指南第二卷33|ROW_NUMBER|窗口化扩展通过窗口名称或规范指定窗口函数的类型,并应用于单个查询表达式范围内的分区结果集.
窗口分区是由查询返回的行的子集,由一个特殊的OVER子句中的一个或多个列定义:olap_function()OVER(PARTITIONBYcol1,col2.
.
.
)使用窗口化操作,可以建立信息,诸如在行的分区中排列每行、在某个分区内的行中分布值,以及类似操作.
利用窗口化操作,还可对数据计算移动平均值和总数,从而增强对数据及其对操作的影响进行评估的能力.
OLAP窗口的三个基本部分OLAP窗口包含三个基本方面:窗口分区、窗口排序和窗口构架.
在任何时刻,每一方面都会对窗口中显示的特定数据行产生重大影响.
同时,OLAPOVER子句可利用三项独特的功能将OLAP函数与其它分析函数或报告函数区分开:定义窗口分区(PARTITIONBY子句).
对分区中的行进行排序(ORDERBY子句).
定义窗口构架(ROWS/RANGE规范).
若要指定多个窗口函数,并避免出现冗余窗口定义,可以指定OLAP窗口规范的名称.
在这种用法中,关键字WINDOW后面至少跟有一个窗口定义,窗口定义之间用逗号分隔开.
窗口定义包含窗口在查询中使用的名称以及窗口规范中的详细信息,利用它,可以定义窗口分区、窗口排序和窗口构架:::=::=[{::=AS::=[][][][]对于窗口分区中的每一行,用户可以定义窗口构架,这可能会改变用于对分区的当前行执行任何计算的特定行范围.
当前行提供了可用于确定窗口构架的起点和终点的参照点.
窗口规范可以基于一定数量的物理行(使用定义ROWS的窗口构架单元的窗口规范)或数值的逻辑区间(使用定义RANGE的窗口构架单元的窗口规范).
在OLAP窗口化操作中,可以使用以下函数类别:排名函数使用OLAP34SybaseIQ窗口化集合函数统计集合函数分布函数另请参见分布函数(第53页)OLAP优点(第20页)OLAP计算(第20页)排名函数(第43页)统计集合函数(第49页)窗口化集合函数(第47页)OLAP函数的BNF语法(第67页)窗口分区窗口分区是指使用PARTITIONBY子句拆分用户指定的结果集(输入行).
分区由一个或多个用逗号分隔的值表达式定义.
分区数据也是隐式排序的,缺省排序顺序是升序(ASC).
::=PARTITIONBY如果未指定窗口分区子句,则会将输入作为单个分区处理.
注意:术语分区像在分析函数中使用时一样,仅仅是指使用PARTITIONBY子句将结果行集拆分开.
可根据任意表达式定义窗口分区.
此外,因为窗口分区在GROUPING之后发生(如果指定了GROUPBY子句),所以,任何集合函数(如SUM、AVG和VARIANCE)的结果都可以在分区表达式中使用.
因此,除了GROUPBY和ORDERBY子句外,利用分区,也可以执行分组和排序操作;例如,您可以构造通过集合函数来计算集合函数(如特定数量的最大SUM)的查询.
即使没有GROUPBY子句,也可以指定PARTITIONBY子句.
另请参见窗口构架(第36页)窗口排序(第35页)窗口排序窗口排序是指使用windoworder子句(包含一个或多个用逗号分隔的值表达式)排列每个窗口分区中的结果(行).
如果未指定windoworder子句,则可以按任意顺序处理输入行.
::=使用OLAP系统管理指南第二卷35OLAPwindoworder子句不同于ORDERBY子句,后者可以附加到非窗口查询表达式中.
例如,OLAP函数中的ORDERBY子句通常定义用于对窗口分区中的行进行排序的表达式;但是,您可以使用不带PARTITIONBY子句的ORDERBY子句,在这种情况下,排序规范可确保使用OLAP函数来对中间结果集进行有意义的(并且是预期的)排序.
排序规范是OLAP函数的排列系列的前提条件;用于标识排列值的测量标准的不是函数参数本身,而是ORDERBY子句.
如果是OLAP集合,则一般不需要ORDERBY子句,但该子句是定义窗口构架的前提条件.
这是因为,必须先对分区行进行排序,然后才可以为每个构架计算相应的集合值.
ORDERBY子句包括用于定义升序排序和降序排序的语义,以及空值的处理规则.
缺省情况下,OLAP函数采用升序,而最小测量值的排名为1.
虽然此行为与ORDERBY子句(位于SELECT语句的末尾)的缺省行为一致,但对于大多数有序计算,它都是与直觉相反的.
OLAP计算通常需要降序,而最大测量值的排名为1;必须使用带DESC关键字的ORDERBY子句显式声明此要求.
注意:排名函数需要,因为它们是仅针对排序输入定义的.
就像使用中的一样,缺省排序顺序是升序.
使用RANGE的时也要求存在.
如果是RANGE,则只能包括一个表达式.
另请参见窗口构架(第36页)窗口分区(第35页)窗口构架对于非秩集合OLAP函数,可以使用windowframe子句定义一个窗口构架,该子句指定窗口的开始位置和结束位置(相对于当前行).
::=计算此OLAP函数时针对的是移动构架的内容而不是整个分区的固定内容.
根据定义,分区具有开始行和结束行,而窗口构架从分区的起点滑至终点.
使用OLAP36SybaseIQ图3:含分区输入的三行移动窗口UNBOUNDEDPRECEDING和FOLLOWING窗口构架可由未受限制的集合组(扩展回到分区的开始位置(UNBOUNDEDPRECEDING)或扩展到分区的结束位置(UNBOUNDEDFOLLOWING))定义.
UNBOUNDEDPRECEDING包括分区中当前行之前的所有行,对于这些行,可使用ROWS或RANGE指定.
UNBOUNDEDFOLLOWING包括分区中当前行之后的所有行,对于这些行,可使用ROWS或RANGE指定.
值FOLLOWING指定当前行后面的行的范围或数量.
如果指定了ROWS,则该值是一个表示行数的正整数.
如果指定了RANGE,则窗口包括所有小于当前行加指定数值的行.
如果是RANGE,则窗口值的数据类型必须与ORDERBY子句的排序键表达式的类型相当.
只能有一个排序键表达式,并且排序键表达式的数据类型必须允许相加.
值PRECEDING指定当前行前面的行的范围或数量.
如果指定了ROWS,则该值是一个表示行数的正整数.
如果指定了RANGE,则窗口包括所有小于当前行减去指定数值的行.
如果是RANGE,则窗口值的数据类型必须与ORDERBY子句的排序键表达式的类型相当.
只能有一个排序键表达式,并且排序键表达式的数据类型必须允许相减.
如果第一个绑定组为CURRENTROW或值FOLLOWING,则不能在第二个绑定组中指定此子句.
使用OLAP系统管理指南第二卷37组合BETWEENUNBOUNDEDPRECEDINGANDUNBOUNDEDFOLLOWING提供整个分区的集合,且不需要构造到分组查询的连接.
整个分区的集合也称为报告聚合.
CURRENTROW概念在物理集合组中,根据行相对于当前行的位置来包括或排除行(通过统计相邻行的数目).
当前行仅仅是查询的中间结果中下一行的参照.
如果当前行前进,则会根据窗口中的新行集重新计算窗口.
对于窗口中包括的当前行,没有任何要求.
如果未指定windowframe子句,则缺省窗口构架取决于是否指定了windoworder子句:如果窗口规范包含windoworder子句,且窗口的起点是UNBOUNDEDPRECEDING,终点是CURRENTROW,则定义适合用于计算累计值的大小可变的窗口.
如果窗口规范不包含windoworder子句,且窗口的起点是UNBOUNDEDPRECEDING,终点是UNBOUNDEDFOLLOWING,则定义大小固定的窗口(不考虑当前行).
注意:windowframe子句不能与排名函数一起使用.
您还可以通过指定基于行(行规范)或基于值(范围规范)的窗口构架单元来定义窗口.
::=ROWS|RANGE::=|当窗口构架范围指定BETWEEN时,它会显式提供窗口构架的开始位置和结束位置.
如果窗口构架范围仅指定这两个值中的一个,则另一个值缺省为CURRENTROW.
基于行的窗口构架-在示例中,行[1]至[5]表示分区;随着OLAP窗口构架的向前滑动,每个行都可成为当前行.
构架是指"BetweenCurrentRowAnd2Following",因此每个构架都最多包括三行,最少包括一行.
当构架到达分区的末尾时,只包括当前行.
带阴影的区域表示每一步从构架中排除的行.
图4:基于行的窗口构架窗口构架实施下列规则:当行[1]为当前行时,系统将排除行[4]和行[5].
当行[2]为当前行时,将排除行[5]和行[1].
使用OLAP38SybaseIQ当行[3]为当前行时,系统将排除行[1]和行[2].
当行[4]为当前行时,将排除行[1]、[2]和[3].
当行[5]为当前行时,系统将排除行[1]、[2]、[3]和[4].
下图将这些规则应用到一组特定值,并显示将为每一行计算的OLAPAVG函数.
滑动计算生成区间为三行(或更少)的移动平均值,具体取决于哪一行是当前行:下面的示例说明了一个滑动窗口:SELECTdimension,measure,AVG(measure)OVER(partitionBYdimensionORDERBYmeasureROWSBETWEENCURRENTROWand2FOLLOWING)ASolap_avgFROM.
.
.
平均值按以下方式计算:行[1]=(10+50+100)/3行[2]=(50+100+120)/3行[3]=(100+120+500)/3行[4]=(120+500+NULL)/3行[5]=(500+空值+空值)/3将为结果集中的所有后续分区执行相似计算(如B、C等).
如果当前窗口中没有行,则结果为空值,但对于COUNT则例外.
另请参见窗口排序(第35页)窗口分区(第35页)ROWS窗口构架单元ROWS通过指定当前行前面或后面的行的数量来定义窗口,当前行充当确定窗口开始位置和结束位置的参照点.
每个分析计算都基于分区中的当前行.
要为以行表示的窗口生成确定性结果,排序表达式应该是唯一的.
使用OLAP系统管理指南第二卷39所有窗口构架的参照点都是当前行.
使用SQL/OLAP语法,可以将基于行的窗口构架定义为当前行前面和/或后面的任意数量的行.
以下列表说明了常见的窗口构架单元示例:RowsBetweenUnboundedPrecedingandCurrentRow-指定以每个分区的开始位置作为起点并以当前行作为终点的窗口,经常用于构造计算累计结果(如累计总和)的窗口.
Rowsbetweenunboundedprecedingandunboundedfollowing-指定跨整个分区的固定窗口(不考虑当前行).
因此,窗口集合函数的值在分区的每一行中都是相同的.
Rowsbetween1precedingand1following-指定跨三个相邻行(当前行前后各一行)的大小固定的移动窗口.
您可以使用此窗口构架单元执行计算,例如,计算3天或3个月的移动平均值.
请注意,由于窗口值之间存在间距,因此在使用ROWS时可能会生成没有意义的结果.
如果值集是不连续的,请考虑使用RANGE而不是ROWS,因为基于RANGE的窗口定义会自动处理含重复值的相邻行,并且,如果范围中存在间距,则不会包括任何其它行.
注意:如果是移动窗口,则假设在输入中,包含空值的行位于第一行之前、最后一行之后.
这意味着,在一个包含3行的移动窗口中,输入中最后一行(当前行)的计算将包括紧挨在它前面的一行和空值.
Rowsbetweencurrentrowandcurrentrow-将窗口限制为仅含当前行.
RowsBetween1Precedingand1Preceding-指定仅含上一行(相对于当前行而言)的单行窗口.
此构造与仅基于当前行计算值的另一窗口函数组合使用,使得您可以轻松地计算相邻行间的增量(即值的差额).
另请参见RANGE(第40页)RANGE基于范围的窗口构架-SQL/OLAP语法支持另一种窗口构架,这种构架的限制是根据一组基于值(或基于范围)的行定义的,而不是根据一系列特定行定义的.
基于值的窗口构架定义窗口分区中包含特定范围的数值的行.
OLAP函数的ORDERBY子句定义应用范围规范的数值列(相对于当前行的该列中的值).
范围规范与行规范使用的语法相同,但是语法的解释方式不同.
窗口构架单元RANGE可定义一个窗口构架,通过查找排序列的值在指定值范围内的行(相对于当前行),可以确定该构架的内容.
这称为窗口构架的逻辑偏移,您可以使用常量(如"3preceding")或任何计算结果为数值常量的表达式指定该偏移.
如果所使用的窗口是用RANGE定义的,则ORDERBY子句中只能有一个数值表达式.
注意:ORDERBY键必须是RANGE窗口构架中的数值数据.
例如,可将构架定义为一组含year值(当前行的年份之前或之后的数年)的行:使用OLAP40SybaseIQORDERBYyearASCrangeBETWEENCURRENTROWand1PRECEDING在上面的示例查询中,"1preceding"表示当前行的year值减去1.
这种范围规范是包含性的.
如果当前行的year值为2000,则窗口分区中所有year值为2000和1999的行都符合成为构架内容的条件,无论这些行在分区中处于哪个物理位置都是如此.
用于包括和排除基于值的行的规则与应用于基于行的构架的规则非常不同,后者完全依赖于行的物理顺序.
如果是在OLAPAVG()计算环境中,则下面的部分结果集可进一步说明基于值的窗口构架的概念.
重申一遍,构架包括符合以下条件的行:与当前行具有相同的year值year值等于当前行减去1以下查询说明了基于范围的窗口定义:SELECTdimension,year,measure,AVG(measure)OVER(PARTITIONBYdimensionORDERBYyearASCrangeBETWEENCURRENTROWand1PRECEDING)asolap_avgFROM.
.
.
平均值按以下方式计算:行[1]=1999;排除行[2]至[5];AVG=10,000/1行[2]=2001;排除行[1]、[4]和[5];AVG=6,000/2行[3]=2001;排除行[1]、[4]和[5];AVG=6,000/2行[4]=2002;排除行[1];AVG=21,000/4行[5]=2002;排除行[1];AVG=21,000/4基于值的构架的升序和降序-用于基于值的窗口构架的OLAP函数的ORDERBY子句不仅标识范围规范所基于的数值列,而且还声明ORDERBY值的排序顺序.
以下规范受它之前的排序顺序(ASC或DESC)约束:RANGEBETWEENCURRENTROWANDnFOLLOWING规范nFOLLOWING表示:如果分区按缺省升序(ASC)排序,则加上n如果分区按降序(DESC)排序,则减去n例如,假设year列包含四个不同的值(从1999到2002).
下表在左侧显示这此值的缺省升序,在右侧显示这些值的降序:使用OLAP系统管理指南第二卷41如果当前行是1999并且按照如下所示指定构架,则包含值1999和1998的行(在表中不存在)会包括在构架中:ORDERBYyearDESCrangeBETWEENCURRENTROWand1FOLLOWING注意:ORDERBY值的排序顺序是测试哪些行可以包括在基于值的构架中的关键部分;仅仅依赖于数值,无法确定是排除还是包括行.
使用未受限制的窗口-以下查询会生成一个结果集,结果集中包含所有产品以及所有产品的总量:SELECTid,description,quantity,SUM(quantity)OVER()AStotalFROMproducts;计算相邻行之间的增量-如果使用两个窗口(一个在当前行上,另一个在上一行上),则可以直接计算相邻行之间的增量(即变化).
SELECTEmployeeID,Surname,SUM(salary)OVER(ORDERBYBirthDaterowsbetweencurrentrowandcurrentrow)AScurr,SUM(Salary)OVER(ORDERBYBirthDaterowsbetween1precedingand1preceding)ASprev,(curr-prev)asdeltaFROMEmployeesWHEREStateIN('MA','AZ','CA','CO')ANDDepartmentID>10ORDERBYEmployeeID,Surname;以上查询的结果:EmployeeIDSurnamecurrprevdelta148Jordan51432.
000191Bertrand29800.
00039300.
000-9500.
000278Melkisetian48500.
00042300.
0006200.
000299Overbey39300.
00041700.
750-2400.
750318Crow41700.
75045000.
000-3299.
250586Coleman42300.
00046200.
000-3900.
000690Poitras46200.
00029800.
00016400.
000703Martinez55500.
80051432.
0004068.
800949Savarino72300.
00055500.
80016799.
2001101Preston37803.
00048500.
000-10697.
0001142Clark45000.
00072300.
000-27300.
000使用OLAP42SybaseIQ虽然使用了窗口函数SUM(),但总和只包含当前行或上一行的薪水值,这是由于窗口的指定方式而导致的.
此外,结果中第一行的prev值为空值(因为它没有前项);因此,delta也为空值.
在上面的每个示例中,用于OVER()子句的函数是SUM()集合函数.
另请参见ROWS(第39页)显式窗口子句和行内窗口子句SQLOLAP提供了两种方式来在查询中指定窗口:使用HAVING子句后面的显式窗口子句,可以定义窗口.
您可以在调用OLAP函数时通过指定名称来引用这些窗口子句定义的窗口,如:SUM(.
.
.
)OVERw2使用行内窗口规格,可以通过查询表达式的SELECT列表定义窗口.
使用此功能,可以在跟在HAVING子句后面的窗口子句中定义窗口,然后利用窗口函数调用按名称引用它们,或将它们与函数调用一起定义.
注意:如果使用行内窗口规格,则无法命名窗口.
一个SELECT列表中的两个或更多个使用相同窗口的窗口函数调用都必须引用在窗口子句中定义的命名窗口,或者必须以冗余方式定义它们的行内窗口.
窗口函数示例-下面的示例显示了一个窗口函数.
查询返回一个结果集,该结果集按部门将数据分区,然后提供雇员薪水的累计汇总(从在公司工作时间最长的雇员开始).
结果集仅包括住在马萨诸塞州的雇员.
列Sum_Salary提供雇员薪水的累计总计.
SELECTDepartmentID,Surname,StartDate,Salary,SUM(Salary)OVER(PARTITIONBYDepartmentIDORDERBYstartdaterowsbetweenunboundedprecedingandcurrentrow)ASsum_salaryFROMEmployeesWHEREStateIN('CA')ANDDepartmentIDIN(100,200)ORDERBYDepartmentID;以下结果集是按部门分区的.
DepartmentIDSurnamestart_datesalarysum_salary200Overbey1987-02-1939300.
00039300.
000200Savarino1989-11-0772300.
000111600.
000200Clark1990-07-2145000.
000156600.
000排名函数使用排名函数,可以按排列顺序编译数据集中值的列表,以及编写执行请求的单语句SQL查询(如"Namethetop10productsshippedthisyearbytotalsales"或"Givethetop5%ofsalespersonswhosoldorderstoatleast15differentcompanies").
使用OLAP系统管理指南第二卷43SQL/OLAP定义五个属于排名函数类别的函数:::=RANK|DENSE_RANK|PERCENT_RANK|ROW_NUMBER|NTILE使用排名函数,可以根据在查询中指定的顺序为结果集中的每一行计算秩值.
例如,一名销售经理可能需要确定公司中的最领先或最落后的销售人员,业绩最好或最差的销售区域,或者销售情况最好或最差的产品.
排名函数可以提供此信息.
另请参见分布函数(第53页)OLAP优点(第20页)OLAP计算(第20页)统计集合函数(第49页)窗口化(第33页)窗口化集合函数(第47页)OLAP函数的BNF语法(第67页)RANK()函数RANK函数返回一个数字,该数字表示当前行在行分区中各行间的秩(由ORDERBY子句定义).
分区中第一行的秩为1,包含25个行的分区的最后一个秩为25.
RANK被指定为语法转换,这表示实施可以选择将RANK实际转换为它的等同项,否则,它仅能返回与转换返回的结果等同的结果.
在下面的示例中,ws1表示定义名为w1的窗口的窗口规范.
RANK()OVERws等效于:(COUNT(*)OVER(wsRANGEUNBOUNDEDPRECEDING)-COUNT(*)OVER(wsRANGECURRENTROW)+1)RANK函数的转换使用逻辑集合(RANGE).
因此,两个或更多个绑定的(即在排序列中具有相等值)的记录将具有相同的秩.
分区中下一个具有不同值的组的秩将比绑定行的秩至少大1.
例如,如果有一些行的排序列值为10、20、20、20、30,则第一行的秩为1,第二行的秩为2,第三行和第四行的秩也为2,但第五行的秩为5.
没有秩为3或4的行.
此算法有时也称为稀疏排名.
另请参见《参考:构件块、表和过程》>"SQL函数">"RANK函数[分析]".
DENSE_RANK()函数DENSE_RANK会返回没有间距的秩值.
绑定行的值仍旧相等,但行的秩表示在排序列中具有相等值的行的集群位置,而不是各个行的位置.
正如在RANK示例中,行排序列值是10、20、20、20、30,第一行使用OLAP44SybaseIQ的秩仍旧是1,而第二行的秩仍旧是2,第三行和第四行的秩也是相同的.
但是,最后一行的秩是3而不是5.
DENSE_RANK也是通过语法转换计算的.
DENSE_RANK()OVERws等效于:COUNT(DISTINCTROW(expr_1,expr_n))OVER(wsRANGEUNBOUNDEDPRECEDING)在上面的示例中,expr_1至expr_n代表窗口w1的排序规范列表中值表达式的列表.
另请参见《参考:构件块、表和过程》>"SQL函数">"DENSE_RANK函数[分析]".
PERCENT_RANK()函数PERCENT_RANK函数计算秩的百分比,而不是分数,并返回一个介于0和1之间的小数值.
PERCENT_RANK返回行的相对秩,这个数字指出当前行在它所在的窗口分区中的相对位置.
例如,在包含10个在排序列中具有不同值的行的分区中,将为第三行提供PERCENT_RANK值0.
222……,原因是您涵盖了分区的第一行后面的2/9(22.
222……%)个行.
行的PERCENT_RANK是指行的RANK减去一,再除以分区中的行数减去一,如以下示例中所示(其中"ANT"代表近似数值类型,如REAL或DOUBLEPRECISION).
PERCENT_RANK()OVERws等效于:CASEWHENCOUNT(*)OVER(wsRANGEBETWEENUNBOUNDEDPRECEDINGANDUNBOUNDEDFOLLOWING)=1THENCAST(0ASANT)ELSE(CAST(RANK()OVER(ws)ASANT)-1/(COUNT(*)OVER(wsRANGEBETWEENUNBOUNDEDPRECEDINGANDUNBOUNDEDFOLLOWING)-1)END另请参见《参考:构件块、表和过程》>"SQL函数">"PERCENT_RANK函数[分析]".
ROW_NUMBER()函数ROW_NUMBER函数为每一行返回一个唯一行号.
如果您定义窗口分区,ROW_NUMBER就会在每个分区中从1开始对行进行编号,每行递增1.
如果您不指定窗口分区,ROW_NUMBER就会对整个结果集进行编号,从1到表的总基数.
使用OLAP系统管理指南第二卷45ROW_NUMBER函数语法为:ROW_NUMBER()OVER([PARTITIONBYwindowpartition]ORDERBYwindowordering)ROW_NUMBER不需要参数,但您必须指定括号.
PARTITIONBY子句是可选的.
OVER(ORDER_BY)子句不能包含窗口构架ROWS/RANGE规范.
排名示例下面是一些排名函数示例:排名示例1-下面的SQL查询查找加利福尼亚州的男女雇员并按薪水以降序排列他(她)们.
SELECTSurname,Sex,Salary,RANK()OVER(ORDERBYSalaryDESC)asRANKFROMEmployeesWHEREStateIN('CA')ANDDepartmentID=200ORDERBYSalaryDESC;以上查询的结果:SurnameSexSalaryRANKSavarinoF72300.
0001ClarkF45000.
0002OverbeyM39300.
0003排名示例2-使用上一示例中的查询,您可以按性别划分数据,从而更改数据.
下面的示例按薪水以降序排列雇员并按性别将雇员分区:SELECTSurname,Sex,Salary,RANK()OVER(PARTITIONBYSexORDERBYSalaryDESC)ASRANKFROMEmployeesWHEREStateIN('CA','AZ')ANDDepartmentIDIN(200,300)ORDERBYSex,SalaryDESC;以上查询的结果:SurnameSexSalaryRANKSavarinoF72300.
0001JordanF51432.
0002ClarkF45000.
0003ColemanM42300.
0001OverbeyM39300.
0002排名示例3-此示例查找加利福尼亚州和德克萨斯州的一些女雇员并根据薪水以降序排列她们.
PERCENT_RANK函数按降序提供累计总计.
SELECTSurname,Salary,Sex,CAST(PERCENT_RANK()OVER(ORDERBYSalaryDESC)ASnumeric(4,2))ASRANKFROMEmployeesWHEREStateIN('CA','TX')ANDSex='F'ORDERBYSalaryDESC;使用OLAP46SybaseIQ以上查询的结果:SurnamesalarysexRANKSavarino72300.
000F0.
00Smith51411.
000F0.
33Clark45000.
000F0.
66Garcia39800.
000F1.
00排名示例4-您可以使用PERCENT_RANK函数在数据集中查找最高或最低的百分点.
此查询会返回其薪水在数据集的最高的五个百分点之内的男雇员.
SELECT*FROM(SELECTSurname,Salary,Sex,CAST(PERCENT_RANK()OVER(ORDERBYsalaryDESC)asnumeric(4,2))ASpercentFROMEmployeesWHEREStateIN('CA')ANDsex='F')ASDTwherepercent>0.
5ORDERBYSalaryDESC;以上查询的结果:SurnamesalarysexpercentClark45000.
000F1.
00排名示例5-此示例使用ROW_NUMBER函数为所有窗口分区中的每一行返回行号.
查询按照部门ID对Employees表进行分区,并按照开始日期对每个分区中的行进行排序.
SELECTDepartmentIDdID,StartDate,Salary,ROW_NUMBER()OVER(PARTITIONBYdIDORDERBYStartDate)FROMEmployeesORDERBY1,2;以上查询的结果为:dIDStartDateSalaryRow_number()1001984-08-2847500.
00011001985-01-0162000.
50021001985-06-1757490.
00031001986-06-0772995.
00041001986-07-0148023.
69052001985-02-0338500.
00012001985-12-0654800.
00022001987-02-1939300.
00032001987-07-1049500.
00045001994-02-2724903.
0009窗口化集合函数使用窗口化集合函数,可以在同一查询中处理多个集合级别.
例如,可以列出花销小于平均值的所有季度.
您可以使用集合函数(包括简单集合函数AVG、COUNT、MAX、MIN和SUM)将可能在语句中的不同级别计算出的结果放置在使用OLAP系统管理指南第二卷47同一行.
通过这样放置,可以将集合值与组中的明细行进行比较,且不需要连接或相关子查询.
使用这些函数,还可以将非集合值与集合值进行比较.
例如,有些客户所订购产品的数量超过了某产品在指定年份内的平均数量,销售人员可能需要编辑所有这些客户的列表,或者,经理可能需要将雇员的薪水与部门的平均薪水进行比较.
如果查询在SELECT语句中指定DISTINCT,则在窗口运算符之后应用DISTINCT运算.
窗口运算符的计算是在处理GROUPBY子句之后、计算SELECT列表项和查询的ORDERBY子句之前进行的.
窗口化集合示例1-此查询返回一个结果集(按年分区),该结果集显示了销售量高于平均销售量的产品的列表.
SELECT*FROM(SELECTSurnameASE_name,DepartmentIDASDept,CAST(SalaryASnumeric(10,2))ASSal,CAST(AVG(Sal)OVER(PARTITIONBYDepartmentID)ASnumeric(10,2))ASAverage,CAST(STDDEV_POP(Sal)OVER(PARTITIONBYDepartmentID)ASnumeric(10,2))ASSTD_DEVFROMEmployeesGROUPBYDept,E_name,Sal)ASderived_tableWHERESal>(Average+STD_DEV)ORDERBYDept,Sal,E_name;以上查询的结果:E_nameDeptSalAverageSTD_DEVLull10087900.
0058736.
2816829.
59Sheffield10087900.
0058736.
2816829.
59Scott10096300.
0058736.
2816829.
59Sterling20064900.
0048390.
9413869.
59Savarino20072300.
0048390.
9413869.
59Kelly20087500.
0048390.
9413869.
59Shea300138948.
0059500.
0030752.
39Blaikie40054900.
0043640.
6711194.
02Morris40061300.
0043640.
6711194.
02Evans40068940.
0043640.
6711194.
02Martinez50055500.
8033752.
209084.
49对于2000年,平均订单数是1,787.
四种产品(700、601、600和400)的销售数量高于该数量.
在2001年,平均订单数是1,048,有三种产品超过该数量.
窗口化集合示例2-此查询返回一个结果集,该结果集显示了其薪水比其部门的平均薪水高一个标准偏差的雇员.
标准偏差是数据与平均值的差异的测量单位.
SELECT*FROM(SELECTSurnameASE_name,DepartmentIDASDept,CAST(SalaryASnumeric(10,2))ASSal,CAST(AVG(Sal)OVER(PARTITIONBYdept)ASnumeric(10,2))ASAverage,CAST(STDDEV_POP(Sal)OVER(PARTITIONBYdept)ASnumeric(10,2))ASSTD_DEVFROMEmployees使用OLAP48SybaseIQGROUPBYDept,E_name,Sal)ASderived_tableWHERESal>(Average+STD_DEV)ORDERBYDept,Sal,E_name;每个部门至少有一名雇员的薪水远远超过平均值,如下列结果所示:E_nameDeptSalAverageSTD_DEVLull10087900.
0058736.
2816829.
59Sheffield10087900.
0058736.
2816829.
59Scott10096300.
0058736.
2816829.
59Sterling20064900.
0048390.
9413869.
59Savarino20072300.
0048390.
9413869.
59Kelly20087500.
0048390.
9413869.
59Shea300138948.
0059500.
0030752.
39Blaikie40054900.
0043640.
6711194.
02Morris40061300.
0043640.
6711194.
02Evans40068940.
0043640.
6711194.
02Martinez50055500.
8033752.
209084.
49雇员Scott的薪水为$96,300.
00,而部门100的平均薪水为$58,736.
28.
该部门的标准偏差是16,829.
00,这表示低于$75,565.
88(58736.
28+16829.
60=75565.
88)的薪水会在平均值的一个标准偏差范围内.
另请参见分布函数(第53页)OLAP优点(第20页)OLAP计算(第20页)排名函数(第43页)统计集合函数(第49页)窗口化(第33页)OLAP函数的BNF语法(第67页)统计集合函数ANSISQL/OLAP扩展提供了许多其它集合函数,这些函数允许对数值数据进行统计分析.
此支持包括用于计算方差、标准偏差、相关和线性回归的函数.
标准偏差和方差采用一个参数的SQL/OLAP常规集函数包括以下语法语句中以粗体显示的那些函数:::=|STDDEV|STDDEV_POP|STDDEV_SAMP|VARIANCE|VARIANCE_POP|VARIANCE_SAMPSTDDEV_POP-计算所提供的值表达式(为组或分区的每个行计算,如果指定了DISTINCT,则为删除重复值后仍旧保留的每个行计算)的总体标准偏差,总体标准偏差是指总体方差的平方根.
使用OLAP系统管理指南第二卷49STDDEV_SAMP-计算所提供的值表达式(为组或分区的每个行计算,如果指定了DISTINCT,则为删除重复值后仍旧保留的每个行计算)的总体标准偏差,总体标准偏差是指样本方差的平方根.
VAR_POP-计算值表达式(为组或分区的每个行计算,如果指定了DISTINCT,则为删除重复值后仍旧保留的每个行计算)的总体方差,总体方差是指值表达式与值表达式平均值的差值的平方和除以组或分区中的保留行数.
VAR_SAMP-计算值表达式(为组或分区的每个行计算,如果指定了DISTINCT,则为删除重复值后仍旧保留的每个行计算)的样本方差,样本方差是指值表达式与值表达式平均值的差值的平方和除以组或分区中的保留行数减一.
这些函数(包括STDDEV和VARIANCE)是真正的集合函数,原因在于,它们可以计算由查询的ORDERBY子句确定的行分区的值.
就像使用其它基本集合函数(如MAX或MIN)一样,它们的计算忽略输入中的空值.
此外,无论所分析的表达式的域是什么,所有方差和标准偏差计算都使用IEEE双精度浮点值.
如果对任何方差或标准偏差函数的输入为空集,则每个函数都将返回空值作为其结果.
如果为单个行计算VAR_SAMP,则它返回空值,而VAR_POP返回值0.
相关用于计算相关系数的SQL/OLAP函数是:CORR-返回一组数字对的相关系数.
您可以使用CORR函数作为窗口化集合函数(在该函数中指定窗口名称或规范使用的窗口函数类型)或作为不带OVER子句的简单集合函数.
协方差用于计算协方差的SQL/OLAP函数包括:COVAR_POP-返回一组数字对的总体协方差.
COVAR_SAMP-返回一组数字对的样本协方差.
协方差函数删除了expression1或expression2的值为空值的所有对.
您可以使用协方差函数作为窗口化集合函数(在该函数中指定窗口名称或规范使用的窗口函数类型)或作为不带OVER子句的简单集合函数.
累积分布用于计算一个值在行组中的相对位置的SQL/OLAP函数是CUME_DIST.
窗口规范必须包含ORDER_BY子句.
不得在CUME_DIST函数中使用组合排序键.
回归分析回归分析函数使用线性回归公式计算独立变量和相关变量之间的关系.
SQL/OLAP线性回归函数包括:使用OLAP50SybaseIQREGR_AVGX-计算回归线的独立变量的平均值.
REGR_AVGY-计算回归线的相关变量的平均值.
REGR_COUNT-返回一个整数,该整数表示用于拟合回归线的非空数字对的数量.
REGR_INTERCEPT-计算可以最好地拟合相关和独立变量的回归线的y截距.
REGR_R2-计算回归线的决定系数(拟合优度统计).
REGR_SLOPE-计算与非空对拟合的线性回归线的斜率.
REGR_SXX-返回线性回归模型中使用的独立表达式的平方和.
使用此函数可以计算回归模型的统计有效性.
REGR_SXY-返回相关和独立变量的乘积之和.
使用此函数可以计算回归模型的统计有效性.
REGR_SYY-返回可以计算回归模型的统计有效性的值.
您可以使用回归分析函数作为窗口化集合函数(在该函数中指定窗口名称或规范使用的窗口函数类型)或作为不带OVER子句的简单集合函数.
加权OLAP集合加权OLAP集合函数计算加权移动平均值:EXP_WEIGHTED_AVG-计算指数加权移动平均值.
加权确定构成平均值的每个数量的相对重要性.
EXP_WEIGHTED_AVG中的权重呈指数级减小.
指数加权会为最新的值应用较多权重,而减小较旧值的权重,同时仍旧为较旧值应用一些权重.
WEIGHTED_AVG-计算线性加权移动平均值,其中权重随着时间的推移按算术级数减小.
对于最新的数据点,权重从最高值减小,而对于最旧的数据点,权重减小为零.
窗口规范必须包含ORDER_BY子句.
非标准数据库行业扩展在数据库行业使用的非ANSISQL/OLAP集合函数扩展包括FIRST_VALUE、MEDIAN和LAST_VALUE.
FIRST_VALUE-返回一组值中的第一个值.
MEDIAN-返回表达式中的中位数.
LAST_VALUE-返回一组值中的最后一个值.
FIRST_VALUE和LAST_VALUE函数需要窗口规范.
您可以使用MEDIAN函数作为窗口化集合函数(在该函数中指定窗口名称或规范使用的窗口函数类型)或作为不带OVER子句的简单集合函数.
另请参见分布函数(第53页)OLAP优点(第20页)OLAP计算(第20页)排名函数(第43页)使用OLAP系统管理指南第二卷51窗口化(第33页)窗口化集合函数(第47页)OLAP函数的BNF语法(第67页)行间函数通过行间函数LAG和LEAD可以访问数据系列中的先前值或后续值,或表中的多个行.
行间函数还同时进行分区,且无需自连接.
LAG提供对在表或分区中CURRENTROW前面且与之相距给定物理偏移量的行的访问.
LEAD提供对在表或分区中CURRENTROW后面且与之相距给定物理偏移量的行的访问.
LAG和LEAD使用的语法相同.
这两个函数都需要OVER(ORDER_BY)窗口规范.
例如:LAG(value_expr)[,offset[,default]])OVER([PARTITIONBYwindowpartition]ORDERBYwindowordering)和:LEAD(value_expr)[,offset[,default]])OVER([PARTITIONBYwindowpartition]ORDERBYwindowordering)OVER(ORDER_BY)子句中的PARTITIONBY子句是可选的.
OVER(ORDER_BY)子句不能包含窗口构架ROWS/RANGE规范.
value_expr是定义要从表返回的偏移数据的表列或表达式.
可以在value_expr中定义其它函数(分析函数除外).
对于这两个函数,都需要通过输入物理偏移量来指定目标行.
offset值是指当前行上面或下面的行数.
请输入一个非负数值数据类型(输入负值会生成错误).
如果输入0,SybaseIQ会返回当前行.
可选的default值定义offset值超过表的范围时要返回的值.
default的缺省值为NULL.
数据类型default必须可隐式转换为数据类型value_expr,否则SybaseIQ将生成转换错误.
LAG示例1-行间函数用于对数据流进行计算的金融服务应用程序(如股票交易).
此示例使用LAG函数来计算特定股票的交易价格的百分比变化.
请考虑下面的来自stock_trades虚构表的交易数据:tradedatsymbolprice2009-07-1306:07:12SQL15.
842009-07-1306:07:13TST5.
752009-07-1306:07:14TST5.
802009-07-1306:07:15SQL15.
86使用OLAP52SybaseIQ2009-07-1306:07:16TST5.
902009-07-1306:07:17SQL15.
86注意:stock_trades虚构表在iqdemo数据库中不可用.
查询按照股票符号对交易进行分区,按照交易时间对它们进行排序,并使用LAG函数来计算当前交易和以前交易之间的交易价格增加或降低百分比:selectstock_symbolas'Stock',traded_atas'Date/TimeofTrade',trade_priceas'Price/Share',cast((((trade_price-(lag(trade_price,1)over(partitionbystock_symbolorderbytraded_at)))/trade_price)*100.
0)asnumeric(5,2))as'%PriceChangevsPreviousPrice'fromstock_tradesorderby1,2查询返回以下结果:StockDate/TimeofTradePrice/%PriceChange_vssymbolSharePreviousPriceSQL2009-07-1306:07:1215.
84NULLSQL2009-07-1306:07:1515.
860.
13SQL2009-07-1306:07:1715.
860.
00TST2009-07-1306:07:135.
75NULLTST2009-07-1306:07:145.
800.
87TST2009-07-1306:07:165.
901.
72第一和第四输出行中的NULL结果表明LAG函数对于两个分区中的第一行都超出范围.
由于没有先前行以供比较,SybaseIQ返回default变量指定的NULL.
分布函数SQL/OLAP定义了多个用于处理有序集合的函数.
这两个逆分布函数是PERCENTILE_CONT和PERCENTILE_DISC.
这些分析函数将一个百分点值作为函数参数使用,并对WITHINGROUP子句中指定的一组数据执行操作或对整个数据集执行操作.
这些函数为每个组返回一个值.
对于PERCENTILE_DISC(离散),结果的数据类型与在WITHINGROUP子句中指定的它的ORDERBY项的数据类型相同.
对于PERCENTILE_CONT(连续),结果的数据类型是数字,但前提是WITHINGROUP子句中的ORDERBY项是数字或双精度型,或者ORDERBY项是整数或浮点型.
逆分布分析函数需要WITHINGROUP(ORDERBY)子句.
例如:PERCENTILE_CONT(expression1)使用OLAP系统管理指南第二卷53WITHINGROUP(ORDERBYexpression2[ASC|DESC])expression1的值必须是数值数据类型的常量,范围从0到1(包含这两个数).
如果参数为NULL,将返回"wrongargumentforpercentile"(百分点的参数错误)错误.
如果参数值小于0或大于1,将返回"datavalueoutofrange"(数据值超出范围)错误.
ORDERBY子句(必须存在)指定对其执行百分点函数的表达式以及每组中行的排序顺序.
此ORDERBY子句只在WITHINGROUP子句中使用,而不是用于SELECT语句的ORDERBY.
WITHINGROUP子句将查询结果分布到排序数据集中,函数通过此数据集计算结果.
值expression2是一种排序规范,必须是涉及列引用的单个表达式.
不允许多个表达式,并且在此排序表达式中不允许使用rank分析函数、集合函数或子查询.
ASC或DESC参数指定排序顺序,如升序或降序.
升序是缺省值.
子查询、HAVING子句、视图或联合中允许使用逆分布分析函数.
可以在使用简单非分析集合函数的任意位置使用逆分布函数.
逆分布函数忽略数据集中的空值.
PERCENTILE_CONT示例-此示例根据以下数据集使用PERCENTILE_CONT函数确定某个区域中要进入前10个百分点而应该达到的汽车销售量:salesregiondealer_name900NortheastBoston800NortheastWorcester800NortheastProvidence700NortheastLowell540NortheastNatick500NortheastNewHaven450NortheastHartford800NorthwestSF600NorthwestSeattle500NorthwestPortland400NorthwestDublin500SouthHouston400SouthAustin300SouthDallas200SouthDover在以下示例查询中,SELECT语句包含PERCENTILE_CONT函数:SELECTregion,PERCENTILE_CONT(0.
1)WITHINGROUP(ORDERBYProductIDDESC)FROMViewSalesOrdersSalesGROUPBYregion;SELECT语句的结果列出了某区域中要进入前10个百分点应该达到的汽车销售量:regionpercentile_contCanada601.
0使用OLAP54SybaseIQCentral700.
0Eastern700.
0South700.
0Western700.
0PERCENTILE_DISC示例-此示例根据以下数据集使用PERCENTILE_DISC函数确定某个区域中要进入前10个百分点而应该达到的汽车销售量:salesregiondealer_name900NortheastBoston800NortheastWorcester800NortheastProvidence700NortheastLowell540NortheastNatick500NortheastNewHaven450NortheastHartford800NorthwestSF600NorthwestSeattle500NorthwestPortland400NorthwestDublin500SouthHouston400SouthAustin300SouthDallas200SouthDover在以下查询中,SELECT语句包含PERCENTILE_DISC函数:SELECTregion,PERCENTILE_DISC(0.
1)WITHINGROUP(ORDERBYsalesDESC)FROMcarSalesGROUPBYregion;SELECT语句的结果列出了每一个区域中要进入前10个百分点而应该达到的汽车销售量:regionpercentile_contNortheast900Northwest800South500有关分布函数的详细信息,请参见《参考:构件块、表和过程》>"SQL函数">"PERCENTILE_CONT函数[分析]"和"PERCENTILE_DISC函数[分析]".
另请参见OLAP优点(第20页)OLAP计算(第20页)排名函数(第43页)统计集合函数(第49页)窗口化(第33页)窗口化集合函数(第47页)OLAP函数的BNF语法(第67页)使用OLAP系统管理指南第二卷55数值函数SybaseIQ支持的OLAP数值函数包括CEILING(别名为CEIL)、EXP(别名为EXPONENTIAL)、FLOOR、LN(别名为LOG)、SQRT和WIDTH_BUCKET.
::=||||||表4.
数值函数和语法数值函数语法自然对数LN(numeric-expression)指数函数EXP(numeric-expression)Power函数POWER(numeric-expression1,numeric-expression2)平方根SQRT(numeric-expression)Floor函数FLOOR(numeric-expression)Ceiling函数CEILING(numeric-expression)Widthbucket函数WIDTH_BUCKET(expression,min_value,max_value,num_buckets)数值函数的语义是:LN-返回参数值的自然对数.
如果参数值为零或为负数,则会引发错误.
LN是LOG的同义词.
EXP-返回通过将e(自然对数的底数)的值增加至参数值指定的幂而计算出的值.
POWER-返回通过将第一个参数的值增加至第二个参数的值指定的幂而计算出的值.
如果第一个参数为0,第二个参数也为0,则返回1.
如果第一个参数为0,而第二个参数为正数,则返回0.
如果第一个参数为0,而第二个参数为负数,则引发异常.
如果第一个参数为负数,第二个参数不是整数,则引发异常.
SQRT-返回参数值的平方根,该平方根由"POWER(expression,0.
5)"的语法转换定义.
FLOOR-返回最接近于正无限大且不大于参数值的整数值.
CEILING-返回最接近于负无限小且不小于参数值的整数值.
CEIL是CEILING的同义词.
WIDTH_BUCKET函数WIDTH_BUCKET函数比其它数值函数略微复杂一些.
它接受四个参数:"实时值"、两个范围边界以及大小相同(或尽可能接近)的分区(边界指示的范围要拆分为这些使用OLAP56SybaseIQ分区)的数目.
WIDTH_BUCKET返回一个数字,该数字指示应将实时值放置在的分区(基于它的值,它的值是范围上边界和下边界之间差值的百分比).
第一个分区的编号为1.
为了避免在实时值超出边界范围时出错,小于范围下边界的值应该放置在第一个附加表元(即表元0)中,大于范围上边界的值应该放在最后一个附加表元(即表元N+1)中.
例如,WIDTH_BUCKET(14,5,30,5)返回2,原因是:(30-5)/5=5,因此范围拆分为5个分区,每个分区的宽度为5个单位.
第一个表元表示从0.
00%到19.
999…%的值,第二个表元表示从20.
00%到39.
999…%的值,第五个表元表示从80.
00%到100.
00%的值.
所选表元是通过计算(5*(14-5)/(30-5))+1(表元数乘以指定值距最小值的偏移与可能值范围的比率,再加上一,即(5*9/25)+1,结果是2.
8)来确定的.
此值是编号为2的表元的值范围(2.
0到2.
999……),因此选择编号为2的表元.
WIDTH_BUCKET示例以下示例基于credit_limit列为样本表中马萨诸塞州的客户创建十表元直方图,并为每名客户返回表元号("CreditGroup").
其信用额度超过最大值的客户将被分配到溢出表元11:注意:此示例仅用于进行说明,不会使用iqdemo数据库生成此示例.
SELECTcustomer_id,cust_last_name,credit_limit,WIDTH_BUCKET(credit_limit,100,5000,10)"CreditGroup"FROMcustomersWHEREterritory='MA'ORDERBY"CreditGroup";CUSTOMER_IDCUST_LAST_NAMECREDIT_LIMITCreditGroup825Dreyfuss5001826Barkin5001853Palin4001827Siegel5001843Oates7002844Julius7002835Eastwood12003840Elliott14003842Stern14003使用OLAP系统管理指南第二卷57841Boyer14003837Stanton12003836Berenger12003848Olmos18004847Streep500011如果将这些限定反转过来,表元将成为半开半闭区间.
例如:WIDTH_BUCKET(credit_limit,5000,0,5).
在此示例中,表元号1的上下限为(4000,5000],表元号2的上下限为(3000,4000],表元号5的上下限为(0,1000].
上溢表元的编号为0(5000,+infinity),下溢表元的编号为6(-infinity,0].
另请参见《参考:构件块、表和过程》>"SQL函数">"BIT_LENGTH函数[字符串]"、"EXP函数[数值]"、"FLOOR函数[数值]"、"POWER函数[数值]"、"SQRT函数[数值]"和"WIDTH_BUCKET函数[数值]".
OLAP规则和限制下文概述了控制OLAP功能的规则和限制.
可以使用OLAP函数SybaseIQ为SQLOLAP函数提供了一些规则、约束和限制.
在SELECT列表中在表达式中作为标量函数的参数在最终ORDERBY子句中(通过在查询中的其它位置使用OLAP函数的别名或位置引用)不能使用OLAP函数在以下情况下,不能使用OLAP函数:在子查询中.
在WHERE子句的搜索条件中.
作为SET(集合)函数的参数.
例如,以下表达式无效:SUM(RANK()OVER(ORDERBYdollars))窗口集合不能是另一个参数的参数,但如果在视图或派生表中生成内部参数则例外.
对于排名函数,同样如此.
窗口集合函数和RANK函数不得在HAVING子句中使用.
窗口集合函数不得指定DISTINCT.
窗口函数不能嵌套在其它窗口函数内部.
OVER子句不支持逆分布函数.
不得在窗口定义子句中使用外部引用.
允许在OLAP函数中使用相关引用,但不允许使用相关列别名.
使用OLAP58SybaseIQOLAP函数引用的列必须是同一查询块(OLAP函数和GROUPBY子句显示在该查询块中)中的分组列或集合函数.
OLAP处理发生在分组和集合操作之后、应用最终ORDERBY子句之前;因此,必须可以从这些中间结果派生OLAP表达式.
如果查询块中没有GROUPBY子句,则OLAP函数可以引用选择列表中的其它列.
SybaseIQ限制SybaseIQ对SQLOLAP函数的限制如下:不支持窗口构架定义中用户定义的函数.
在窗口构架定义中使用的常量必须是不带符号的数值,且不得超过BIGINT263-1的最大值.
窗口集合函数和RANK函数不能在DELETE和UPDATE语句中使用.
窗口集合函数和RANK函数不得在子查询中使用.
CUME_DIST当前不受支持.
分组集当前不受支持.
相关函数和线性回归函数当前不受支持.
其它OLAP示例此节提供了其它OLAP函数使用示例.
当处理中间结果行时,窗口的起点和终点可能会改变.
例如,计算累计总和将涉及一个窗口,该窗口的起点固定在每个分区的第一行,终点沿分区行滑动以包括当前行.
像另一示例一样,窗口的起点和终点都是可变的,但它能为整个分区定义固定数量的行.
使用这种构造,用户可以编写计算移动平均值的查询;例如,返回三天的股票价格的移动平均值的SQL查询.
示例:查询中的窗口函数此查询列出了2005年7月和8月装运的所有产品以及到装运日期为止的累计装运数量:SELECTp.
id,p.
description,s.
quantity,s.
shipdate,SUM(s.
quantity)OVER(PARTITIONBYproductidORDERBYs.
shipdaterowsbetweenunboundedprecedingandcurrentrow)FROMSalesOrderItemssJOINProductspon(s.
ProductID=p.
id)WHEREs.
ShipDateBETWEEN'2001-05-01'and'2001-08-31'ANDs.
quantity>40ORDERBYp.
id;以上查询的结果:IDdescriptionquantityship_datesumquantity302CrewNeck602001-07-0260400CottonCap602001-05-2660400CottonCap482001-07-05108401Woolcap482001-06-0248401Woolcap602001-06-30108使用OLAP系统管理指南第二卷59401Woolcap482001-07-09156500ClothVisor482001-06-2148501PlasticVisor602001-05-0360501PlasticVisor482001-05-18108501PlasticVisor482001-05-25156501PlasticVisor602001-07-07216601ZippedSweatshirt602001-07-1960700CottonShorts722001-05-1872700CottonShorts482001-05-31120在此示例中,要在连接两个表和应用查询的WHERE子句之后,才执行SUM窗口函数的计算.
查询使用行内窗口规格,该规范指定按如下方式处理的连接的输入行:1.
根据prod_id属性的值将输入行分区(分组).
2.
在每个分区中,按ship_date属性对行进行排序.
3.
对于分区中的每一行,计算数量属性的SUM()函数,并使用包括每个分区的第一(排序)行的滑动窗口,直到包含当前行.
另一种构造查询的方式是指定与使用它的函数不同的窗口.
当根据同一窗口指定多个窗口函数时,这非常有用.
在使用窗口函数的查询中,使用窗口子句(声明由累计标识的窗口)的构造如下所示:SELECTp.
id,p.
description,s.
quantity,s.
shipdate,SUM(s.
quantity)OVER(cumulativeROWSBETWEENUNBOUNDEDPRECEDINGandCURRENTROW)cumulativeFROMSalesOrderItemssJOINProductspOn(s.
ProductID=p.
id)WHEREs.
shipdateBETWEEN'2001-07-01'and'2001-08-31'Windowcumulativeas(PARTITIONBYs.
productidORDERBYs.
shipdate)ORDERBYp.
id;窗口子句显示在查询规范中的ORDERBY子句之前.
当使用窗口子句时,存在以下限制:行内窗口规格不得包含PARTITIONBY子句.
在窗口子句中指定的窗口不得包含窗口构架子句.
::=行内窗口规格或在窗口子句中指定的窗口规范都可以(但不能同时)包含窗口排序子句.
::=示例:含多个函数的窗口此查询定义一个(命名)窗口并通过它计算多个函数结果:SELECTp.
ID,p.
Description,s.
quantity,s.
ShipDate,SUM(s.
Quantity)OVERws1,MIN(s.
quantity)OVERws1FROMSalesOrderItemssJOINProductspON(s.
ProductID=p.
ID)WHEREs.
ShipDateBETWEEN'2000-01-09'AND'2000-01-17'ANDs.
Quantity>40windowws1AS(PARTITIONBYproductidORDERBYshipdaterowsbetweenunboundedprecedingandcurrentrow)ORDERBYp.
id;以上查询的结果:使用OLAP60SybaseIQIDDescriptionquantityshipDateSUMMIN400CottonCap482000-01-094848401Woolcap482000-01-094848500ClothVisor602000-01-146060500ClothVisor602000-01-1512060501PlasticVisor602000-01-146060示例:计算累计总和以下查询按部门和ORDERBYstart_date计算薪水的累计总和.
SELECTdept_id,start_date,name,salary,SUM(salary)OVER(PARTITIONBYdept_idORDERBYstart_dateROWSBETWEENUNBOUNDEDPRECEDINGANDCURRENTROW)FROMemp1ORDERBYdept_id,start_date;以上查询的结果:DepartmentIDstart_datenamesalarysum(salary)1001996-01-01Anna18000180001001997-01-01Mike28000460001001998-01-01Scott29000750001001998-02-01Antonia22000970001001998-03-12Adam250001220001001998-12-01Amy180001400002001998-01-01Jeff18000180002001998-01-20Tim29000470002001998-02-01Jim22000690002001999-01-10Tom28000970003001998-03-12Sandy55000550003001998-12-01Lisa38000930003001999-01-10Peter48000141000示例:计算移动平均值以下查询生成连续三个月的销售额的移动平均值.
窗口构架的大小是三行:两个前面的行加一个当前行.
窗口从分区的开始滑至结尾.
SELECTprod_id,month_num,sales,AVG(sales)OVER(PARTITIONBYprod_idORDERBYmonth_numROWSBETWEEN2PRECEDINGANDCURRENTROW)FROMsaleWHERErep_id=1ORDERBYprod_id,month_num;以上查询的结果:prod_idmonth_numsalesavg(sales)使用OLAP系统管理指南第二卷61101100100.
00102120110.
00103100106.
66104130116.
66105120116.
66106110120.
002012020.
002023025.
002032525.
002043028.
332053128.
662062027.
003011010.
003021110.
503031211.
0030418.
00示例:ORDERBY结果在此示例中,查询顶部的ORDERBY子句应用到窗口函数的最终结果.
窗口子句中的ORDERBY应用到窗口函数的输入数据.
SELECTprod_id,month_num,sales,AVG(sales)OVER(PARTITIONBYprod_idORDERBYmonth_numROWSBETWEEN2PRECEDINGANDCURRENTROW)FROMsaleWHERErep_id=1ORDERBYprod_iddesc,month_num;以上查询的结果:prod_idmonth_numsalesavg(sales)3011010.
003021110.
503031211.
0030418.
002012020.
002023025.
002032525.
002043028.
332053128.
662062027.
00101100100.
00102120110.
00103100106.
66104130116.
66105120116.
66106110120.
00示例:查询中的多个集合函数此示例针对查询中的不同窗口计算集合值.
SELECTprod_id,month_num,sales,AVG(sales)OVER(WS1ROWSBETWEEN1PRECEDINGAND1FOLLOWING)ASCAvg,SUM(sales)OVER(WS1ROWSBETWEENUNBOUNDED使用OLAP62SybaseIQPRECEDINGANDCURRENTROW)ASCSumFROMsaleWHERErep_id=1WINDOWWS1AS(PARTITIONBYprod_idORDERBYmonth_num)ORDERBYprod_id,month_num;以上查询的结果:prod_idmonth_numsalesCAvgCSum101100110.
00100102120106.
66220103100116.
66320104130116.
66450105120120.
00570106110115.
006802012025.
00202023025.
00502032528.
33752043028.
661052053127.
001362062025.
501563011010.
50103021111.
0021303128.
003330416.
5034示例:对ROWS和RANGE进行比较的窗口构架此查询对ROWS和RANGE进行比较.
数据在每个ORDERBY子句中包含重复的ROWS.
SELECTprod_id,month_num,sales,SUM(sales)OVER(ws1RANGEBETWEEN2PRECEDINGANDCURRENTROW)ASRange_sum,SUM(sales)OVER(ws1ROWSBETWEEN2PRECEDINGANDCURRENTROW)ASRow_sumFROMsalewindowws1AS(PARTITIONBYprod_idORDERBYmonth_num)ORDERBYprod_id,month_num;以上查询的结果:prod_idmonth_numsalesRange_sumRow_sum10110025010010115025025010212037037010310047037010413035035010512038135010531381281106110391261201202020202305050203257575使用OLAP系统管理指南第二卷632043085852053186862062081813011010103021121213031233333041252430412514示例:不包括当前行的窗口构架在此示例中,您可以定义窗口构架以排除当前行.
查询计算四个行(不包括当前行)的总和.
SELECTprod_id,month_num,sales,sum(sales)OVER(PARTITIONBYprod_idORDERBYmonth_numRANGEBETWEEN6PRECEDINGAND2PRECEDING)FROMsaleORDERBYprod_id,month_num;以上查询的结果:prod_idmonth_numsalessum(sales)101100(NULL)101150(NULL)102120(NULL)1031002501041303701051204701053147010611060020120(NULL)20230(NULL)2032520204305020531752062010530110(NULL)30211(NULL)3031210304121304121示例:RANGE的窗口构架此查询说明RANGE窗口构架.
汇总中使用的行数是可变的.
SELECTprod_id,month_num,sales,SUM(sales)OVER(PARTITIONBYprod_idORDERBYmonth_numRANGEBETWEEN1FOLLOWINGAND3FOLLOWING)FROMsaleORDERBYprod_id,month_num;以上查询的结果:使用OLAP64SybaseIQprod_idmonth_numsalessum(sales)10110035010115035010212038110310039110413026110512011010531110106110(NULL)2012085202308620325812043051205312020620(NULL)301102530211143031223041(NULL)3041(NULL)示例:Unboundedprecedingandunboundedfollowing在此示例中,窗口构架可以包括分区中的所有行.
查询计算整个分区(一个月中没有重复行)的最大销售额.
SELECTprod_id,month_num,sales,SUM(sales)OVER(PARTITIONBYprod_idORDERBYmonth_numROWSBETWEENUNBOUNDEDPRECEDINGANDUNBOUNDEDFOLLOWING)FROMsaleWHERErep_id=1ORDERBYprod_id,month_num;以上查询的结果:prod_idmonth_numsalesSUM(sales)101100680102120680103100680104130680105120680106110680201201562023015620325156204301562053115620620156301103430211343031234304134本示例中的查询相当于:使用OLAP系统管理指南第二卷65SELECTprod_id,month_num,sales,SUM(sales)OVER(PARTITIONBYprod_id)FROMsaleWHERErep_id=1ORDERBYprod_id,month_num;示例:RANGE的缺省窗口构架此查询说明RANGE的缺省窗口构架:SELECTprod_id,month_num,sales,SUM(sales)OVER(PARTITIONBYprod_idORDERBYmonth_num)FROMsaleORDERBYprod_id,month_num;以上查询的结果:prod_idmonth_numsalesSUM(sales)10110025010115025010212037010310047010413060010512075110531751106110861201202020230502032575204301052053113620620156301101030211213031233304135304135本示例中的查询相当于:SELECTprod_id,month_num,sales,SUM(sales)OVER(PARTITIONBYprod_idORDERBYmonth_numRANGEBETWEENUNBOUNDEDPRECEDINGANDCURRENTROW)FROMsaleORDERBYprod_id,month_num;使用OLAP66SybaseIQOLAP函数的BNF语法Backus-NaurForm语法概述了各种ANSISQL分析函数(其中有许多在SybaseIQ中实现)的特定语法支持.
语法规则1::=|||||语法规则2::=[][][][][]语法规则3::=语法规则4::=GROUPING语法规则5::=OVER语法规则6::=|ROW_NUMBER|语法规则7::=RANK|DENSERANK|PERCENTRANK|CUME_DIST使用OLAP系统管理指南第二卷67语法规则8::=|语法规则9::=||语法规则10::=|LISTDISTINCT[][]语法规则11::=SUM|MAX|MIN|AVG|COUNT语法规则12::=|LIST[][]语法规则13::=语法规则14::=|GROUPINGFUNCTION语法规则15::=|STDDEV|STDDEV_POP|STDDEV_SAMP|VARIANCE|VARIANCE_POP|VARIANCE_SAMP使用OLAP68SybaseIQ语法规则16::=语法规则17::=CORR|COVAR_POP|COVAR_SAMP|REGR_R2|REGR_INTERCEPT|REGR_COUNT|REGR_SLOPE|REGR_SXX|REGR_SXY|REGR_SYY|REGR_AVGY|REGR_AVGX语法规则18::=|语法规则19::=语法规则20::=语法规则21::=语法规则22::=[{语法规则23::=AS语法规则24::=语法规则25::=使用OLAP系统管理指南第二卷69语法规则26::=[][][][]语法规则27::=语法规则28::=PARTITIONBY语法规则29::=[{语法规则30::=语法规则31::=语法规则32::=语法规则33::=ROWS|RANGE语法规则34::=|语法规则35::=UNBOUNDEDPRECEDING||CURRENTROW使用OLAP70SybaseIQ语法规则36::=PRECEDING语法规则37::=BETWEENAND语法规则38::=语法规则39::=语法规则40::=|UNBOUNDEDFOLLOWING|语法规则41::=FOLLOWING语法规则42::=语法规则43::=||语法规则44::=[{语法规则45::=[{使用OLAP系统管理指南第二卷71语法规则46::=ROLLUP语法规则47::=CUBE语法规则48::=|||语法规则49::=[{}…]语法规则50::=GROUPBY语法规则51::=|WITHROLLUP|WITHCUBE|语法规则52::=GROUPINGSETS语法规则53::=ORDERBY::=[{::=[][]::=::=ASC|DESC:=NULLSFIRST|NULLSLAST另请参见分布函数(第53页)OLAP优点(第20页)OLAP计算(第20页)使用OLAP72SybaseIQ排名函数(第43页)统计集合函数(第49页)窗口化(第33页)窗口化集合函数(第47页)使用OLAP系统管理指南第二卷73使用OLAP74SybaseIQSybaseIQ作为数据服务器SybaseIQ通过ODBC或JDBC支持客户端应用程序连接.
本章介绍如何将SybaseIQ用作客户端应用程序的数据服务器.
由于某些限制,SybaseIQ还可能对于某些客户端应用程序表现为OpenServer.
本章还简要说明了创建和运行这些应用程序的限制.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-编程">"SQLAnywhere数据访问API">"SybaseOpenClientAPI">"OpenClient体系结构".
本章所介绍的功能不为Windows和SunSolaris系统上的IQ用户提供远程数据访问.
远程数据访问由组件集成服务(CIS)提供,CIS为OmniConnect的核心互操作功能.
SybaseIQ的客户端/服务器接口为了简便起见,可将Sybase应用程序或第三方客户端应用程序与SybaseIQ一起使用.
了解这些部件如何协同工作可能会有助于您配置数据库和设置应用程序.
本节介绍这些部件如何协同工作.
有关第三方客户端应用程序的详细信息,请参见《安装和配置指南》.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"复制">"将SQLAnywhere用作OpenServer">"OpenClient、OpenServer和TDS".
使用iqdsedit配置IQ服务器SybaseIQ可以与网络上的其它AdaptiveServer、OpenServer应用程序和客户端软件通信.
客户端可以与一个或多个服务器交谈,而服务器可以通过远程过程调用与其它服务器进行通信.
为了使产品之间能够进行交互,每种产品都需要知道其它产品在网络中的位置.
该网络服务信息存储在interfaces文件中.
注意:SybaseIQ提供具有有限功能的、用于启用INSERT.
.
.
LOCATION的各种版本OpenClient实用程序,包括:iqisqliqdseditiqdscp(仅UNIX)iqocscfg(仅Windows)SybaseIQ作为数据服务器系统管理指南第二卷75interfaces文件当使用OpenClient程序连接到数据库服务器时,该程序在interfaces文件中查找服务器名,然后连接到使用该地址的服务器.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"复制">"将SQLAnywhere用作OpenServer">"配置OpenServer">"interfaces文件".
iqdsedit数据库管理实用程序使用iqdsedit实用程序可以配置interfaces文件(interfaces或SQL.
ini).
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"复制">"将SQLAnywhere用作OpenServer">"配置OpenServer">"使用DSEdit实用程序".
启动iqdsedit在Windows中,iqdsedit可执行文件位于%SYBASE%\IQ-15_3\bin32或%SYBASE%\IQ-15_3\bin64目录中,该目录在安装期间自动添加到您的路径中.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"复制">"将SQLAnywhere用作OpenServer">"配置OpenServer">"启动DSEdit".
打开目录服务会话您可以在"选择目录服务"窗口中添加、修改或删除服务器条目(包括SybaseIQ服务器).
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"复制">"将SQLAnywhere用作OpenServer">"配置OpenServer">"打开目录服务会话".
添加服务器条目服务器条目将显示在"服务器"字段中.
要指定服务器的属性,您必须修改该条目.
此处输入的服务器名称不需要与在SybaseIQ命令行处提供的名称匹配.
使用服务器地址(而非服务器名称)来标识和定位服务器.
服务器名称字段完全是OpenClient的标识符.
对于SybaseIQ,如果服务器装载了多个数据库,则IQDSEDIT服务器名称条目用来标识要使用的数据库.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"复制">"将SQLAnywhere用作OpenServer">"配置OpenServer">"添加服务器条目".
添加或更改服务器地址输入"服务器名"后,需要修改"服务器地址"以完成interfaces文件条目.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"复制">"将SQLAnywhere用作OpenServer">"配置OpenServer">"添加或更改服务器地址".
SybaseIQ作为数据服务器76SybaseIQ端口号您输入的端口号必须与在SybaseIQ数据库服务器命令行处指定的端口匹配.
SybaseIQ服务器的缺省端口号为2638.
以下为有效的服务器地址条目:elora,2638123.
85.
234.
029,2638另请参见将数据库服务器作为OpenServer启动(第79页)验证服务器地址在Windows中,可以在"服务器对象"菜单中使用Ping服务器命令来验证网络连接.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"复制">"将SQLAnywhere用作OpenServer">"配置OpenServer">"验证服务器地址".
重命名服务器条目可以在dsedit会话窗口中重命名服务器条目.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"复制">"将SQLAnywhere用作OpenServer">"配置OpenServer">"重命名服务器条目".
删除服务器条目可以在dsedit会话窗口中删除服务器条目.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"复制">"将SQLAnywhere用作OpenServer">"配置OpenServer">"删除服务器条目".
Sybase应用程序和SybaseIQSybaseIQ充当OpenServer这一功能使Sybase应用程序(如OmniConnect)能够与SybaseIQ协同工作.
要使用OpenClient库,客户端应用程序只能使用支持的系统表、视图和存储过程.
OmniConnect支持SybaseOmniConnect为组织中的不同数据提供统一的视图,使用户可以不必了解数据的模样或其所在的位置,即可访问多个数据源.
此外,OmniConnect对整个企业中的数据执行异构连接,实现了目标(例如DB2、SybaseAdaptiveServerEnterprise、SQLAnywhere、Oracle和VSAM)的跨平台表连接.
通过使用OpenServer接口,SybaseIQ可以充当OmniConnect的数据源.
SybaseIQ作为数据服务器系统管理指南第二卷77OpenClient应用程序和SybaseIQ您可以构建OpenClient应用程序,以使用OpenClient库直接从C或C++编程环境(如PowerSoftPower++)访问SybaseIQ基表中的数据.
如果此类应用程序引用目录表、视图或系统存储过程,则AdaptiveServerEnterprise(Transact-SQL语法)和SybaseIQ都必须支持这些对象.
请参见《参考:构件块、表和过程》>"附录A'与其它Sybase数据库的兼容性'".
配置OpenClient在使用OpenClient连接到SybaseIQ或使用INSERT.
.
.
LOCATION语法时,可以在OpenClient运行环境配置(.
cfg)文件中设置多个OpenClient配置参数.
例如,可以更改最大缺省连接数,该数量由CS_MAX_CONNECT选项的值控制.
INSERT.
.
.
LOCATION的应用程序名称为SybaseIQ.
(单词之间的空格是必需的.
)此应用程序名称是在OpenClient连接级别(而不是OpenClient上下文级别)设置的.
有关使用OpenClient运行环境配置文件以及可用选项的详细信息,请参见OpenClient的Client-LibraryCReferenceManual.
要使.
cfg生效,请停止并重新启动SybaseIQ服务器.
此外,还可以在INSERT.
.
.
LOCATION命令行中指定某些配置参数.
在INSERT.
.
.
LOCATION中设置的参数将被配置文件中设置的参数取代.
当用作远程服务器时,SybaseIQ支持TabularDataSteam(TDS)口令加密.
SybaseIQ服务器接受由客户端发送的使用加密口令的连接.
有关针对口令加密设置的连接属性的信息,请参见《OpenServer15.
5》>"OpenClientClient-Library/C参考手册">"Client-Library主题">"安全性功能">"AdaptiveServerEnterprise安全性功能">"安全握手:加密口令".
注意:口令加密需要OpenClient15.
0.
TDS口令加密需要OpenClient15.
0ESD#7或更高版本.
要使SybaseIQ服务器接受具有加密口令的jConnect连接,请将jConnectENCRYPT_PASSWORD连接属性设置为true.
SybaseIQ作为OpenServer本节介绍如何设置SybaseIQ服务器,以接收来自OpenClient应用程序的连接.
SybaseIQ作为数据服务器78SybaseIQ系统要求对使用SybaseIQ作为OpenServer的客户端和服务器有单独的要求.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"复制">"将SQLAnywhere用作OpenServer">"将SQLAnywhere设置为OpenServer">"系统要求".
注意:使用OmniConnect从本地SQLAnywhereEnterprise服务器连接到远程SybaseIQ时,请使用以下服务器类:要连接到SybaseIQ12或更高版本,请使用服务器类asaodbc和sajdbc.
要连接到SybaseIQ11.
x,请使用服务器类asiq.
将数据库服务器作为OpenServer启动如果您要将SybaseIQ用作OpenServer,必须确保使用TCP/IP协议启动它.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"复制">"将SQLAnywhere用作OpenServer">"将SQLAnywhere设置为OpenServer">"将数据库服务器作为OpenServer启动".
计算机上每个使用TCP/IP的应用程序都使用不同的TCP/IP端口,以使网络包发送到正确的应用程序.
SybaseIQ的缺省端口为2638,该端口用于共享内存通信.
您可以指定另一个端口号:start_iq-xtcpip{port=2629}-nmyserveriqdemo.
db另请参见添加或更改服务器地址(第76页)配置数据库以与OpenClient一起使用数据库必须为SybaseIQ12.
0或更高版本.
如果要将SybaseIQ与AdaptiveServerEnterprise一起使用,需要确保创建的数据库与AdaptiveServerEnterprise具有最大的兼容性.
连接到作为OpenServer的SybaseIQ时,应用程序经常假定已提供它们在AdaptiveServerEnterprise下所期望的服务.
这些服务并非总是存在.
请参见《参考:构件块、表和过程》>"附录A'与其它Sybase数据库的兼容性'".
SybaseIQ作为数据服务器系统管理指南第二卷79OpenClient和jConnect连接的特性当SybaseIQ通过TDS为应用程序提供服务时,它会自动将相关数据库选项的值设置为与SQLAnywhereServer的缺省行为兼容.
这些选项是临时设置的,它们仅用于此连接期间.
客户端应用程序可以随时覆盖这些选项.
注意:SybaseIQ不支持ANSI_BLANKS、FLOAT_AS_DOUBLE和TSQL_HEX_CONSTANT选项.
虽然SybaseIQ允许更长的用户名和口令,但TDS客户端用户名和口令不能超过30字节.
如果您的口令或用户ID超过30字节,则尝试通过TDS进行连接(例如,使用jConnect)会返回"用户ID或口令无效"错误.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"复制">"将SQLAnywhere用作OpenServer">"将SQLAnywhere设置为OpenServer">"OpenClient和jConnect连接的特性".
注意:ODBC应用程序(包括InteractiveSQL应用程序)会自动将某些数据库选项设置为ODBC规范所规定的值.
这样将覆盖通过LOGIN_PROCEDURE数据库选项所做的设置.
有关详细信息和解决方法,请参见《参考:语句和选项》>"LOGIN_PROCEDURE选项".
具有多个数据库的服务器使用OpenClientLibrary,可以连接到包含多个数据库的服务器上的特定数据库.
在服务器的interfaces文件中设置条目.
使用start_iq命令的-n参数为数据库名称设置快捷方式.
在isql命令中用数据库名称指定-Sdatabase_name参数.
进行连接时,需要此参数.
可以在不更改程序本身的情况下,通过将快捷方式名称放到程序中并只更改快捷方式定义,对多个数据库运行相同的程序.
例如,以下interfaces文件摘录定义了live_sales和test_sales两个服务器:live_salesquerytcpethermyhostname5555mastertcpethermyhostname5555test_salesquerytcpethermyhostname7777mastertcpethermyhostname7777启动服务器并为特定数据库设置别名.
以下命令将live_sales设置为等效于salesbase.
db:SybaseIQ作为数据服务器80SybaseIQstart_iq-nsales_live-x\'tcpip{port=5555}'salesbase.
db-nlive_sales要连接到live_sales服务器:isql-Udba-Psql-Slive_sales一个服务器名称只能在interfaces文件中出现一次.
因为与SybaseIQ的连接现在基于数据库名称,所以数据库名称必须唯一.
如果所有脚本都设置为在salesbase数据库上工作,则不必修改脚本,脚本即可与live_sales或test_sales一起工作.
SybaseIQ作为数据服务器系统管理指南第二卷81SybaseIQ作为数据服务器82SybaseIQ访问远程数据SybaseIQ可以访问位于单独的服务器(Sybase和非Sybase)上的数据,就像这些数据存储在本地服务器上一样.
SybaseIQ和远程数据SQLAnywhere远程数据访问允许您访问其它数据源中的数据.
您可以使用此功能将数据迁移到SQLAnywhere数据库.
您还可以使用此功能查询各个数据库中的数据.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"OpenClient和jConnect连接的特性".
访问远程数据的要求访问远程数据需要具备几个基本元素.
远程表映射SybaseIQ将表提供给客户端应用程序的方式就像表中的所有数据都存储在与该应用程序连接的数据库中一样.
从内部来看,当SybaseIQ执行涉及远程表的查询时,它会确定存储位置并访问远程位置来检索数据.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"远程表映射".
服务器类为每个远程服务器指派一个服务器类.
服务器类指定用于与服务器进行交互的访问方法.
不同类型的远程服务器要求使用不同的访问方法.
服务器类为SybaseIQ提供详细的服务器功能信息.
SybaseIQ根据这些功能对它与远程服务器的交互进行调整.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"服务器类".
注意:IPv6不支持OMNIJDBC类.
远程服务器必须先定义远程对象所在的远程服务器,然后才能将远程对象映射到本地代理表.
访问远程数据系统管理指南第二卷83创建远程服务器使用CREATESERVER语句设置远程服务器定义.
对于某些系统(包括SybaseIQ和SQLAnywhere),每个数据源都描述一个数据库,因此每个数据库都需要一个单独的远程服务器定义.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"使用远程服务器">"使用CREATESERVER语句创建远程服务器".
装载没有本机类的远程数据使用DirectConnect装载数据.
本机类使用DirectConnect来访问远程数据源:在64位UNIX平台上在没有ODBC驱动程序可用的32位平台上(例如MicrosoftSQLServer)将MSSQLServer数据装载到UNIX上的IQ服务器中本远程数据示例将MSSQLServer数据装载到UNIX上的IQ服务器中.
对于本示例,假设以下情况:名为mssql的EnterpriseConnectDataAccess(ECDA)服务器位于UNIX主机myhostname端口12530上.
要从主机myhostname端口1433上的MSSQLServer2000中检索数据.
1.
使用DirectConnect文档为您的数据源配置DirectConnect.
2.
确保ECDA服务器(mssql)列在SybaseIQinterfaces文件中:mssqlmastertcpethermyhostname12530querytcpethermyhostname125303.
使用服务器mssql的用户ID和口令,添加新用户:isql-Udba-Psql-Stst_iqdemograntconnecttochillidentifiedbychillgrantdbatochill4.
以新用户身份登录,在SybaseIQ上创建本地表:isql-Uchill-Pchill-Stst_iqdemocreatetablebilling(statuschar(1),namevarchar(20),telnoint)5.
插入数据:insertintobillinglocation'mssql.
pubs'{select*frombilling}访问远程数据84SybaseIQ查询没有本机类的数据请遵循以下准则来查询没有本机类的数据.
1.
使用远程服务器和代理配置ASE/CIS,以通过DirectConnect连接.
例如,将DirectConnectforOracle用于Oracle服务器.
2.
使用ASE服务器类ASEJDBC为SybaseIQ配置远程服务器.
(ASEODBC类不可用,因为ASE没有64位UnixODBC驱动程序.
)3.
使用CREATEEXISTINGTABLE语句创建指向ASE中的代理表的代理表,而ASE中的代理表又指向Oracle.
使用DirectConnect和UNIX中的代理表查询远程数据使用DirectConnect查询数据.
本示例显示如何访问MSSQLServer数据.
对于本示例,假设情况如下所示:SybaseIQ服务器位于主机myhostname端口7594上.
AdaptiveServerEnterprise服务器位于主机myhostname端口4101上.
名为mssql的EnterpriseConnectDataAccess(ECDA)服务器位于主机myhostname端口12530上.
要从主机myhostname端口1433上的MSSQLServer2000中检索数据.
设置AdaptiveServerEnterprise以查询MSSQLServer设置AdaptiveServer和组件集成服务(CIS)以通过DirectConnect查询MSSQLServer.
对于本示例,假设服务器名为jones_1207.
1.
将一个条目添加到ASEinterfaces文件,以连接至mssql:mssqlmastertcpetherhostname12530querytcpetherhostname125302.
从ASE服务器启用CIS和远程过程调用处理.
例如,如果缺省情况下,CIS已启用:sp_configure'enablecis'ParameterNameDefaultMemoryUsedConfigValueRunValueenablecis1011(1rowaffected)(returnstatus=0)sp_configure'cisrpchandling',1ParameterNameDefaultMemoryUsedConfigValueRunValue访问远程数据系统管理指南第二卷85enablecis0001(1rowaffected)Configuationoptionchanged.
TheSQLServerneednotberestartedsincetheoptionisdynamic.
在旧版本(例如SybaseIQ12.
5版)中,启用CIS远程过程调用处理之后,可能需要重新启动AdaptiveServerEnterprise服务器.
3.
将DirectConnect服务器添加到ASE服务器的SYSSERVERS系统表中.
sp_addservermssql,direct_connect,mssqlAddingserver'mssql',physicalname'mssql'Serveradded.
(Returnstatus=0)4.
在AdaptiveServerEnterprise中创建用户,该用户在SybaseIQ中用于连接到ASE.
sp_addlogintst,tsttstPasswordcorrectlyset.
Accountunlocked.
Newlogincreated.
(returnstatus=0)grantrolesa_roletotstusetst_dbsp_addusertstNewuseradded.
(returnstatus=0)5.
从主数据库添加外部登录名:usemastersp_addexternloginmssql,tst,chill,chillUser'tst'willbeknownas'chill'inremoteserver'mssql'.
(returnstatus=0)6.
从所需数据库,以所添加用户身份创建ASE代理表:isql-Utst-Ttsttstusetest_dbcreateproxy_tablebilling_tstat'mssql.
pubs.
.
billing'select*frombilling_tststatusnametelnoDBOTANICALLY1BBOTANICALL2(2rowsaffected)设置SybaseIQ以连接到ASE服务器请按照以下步骤来查询AdaptiveServerEnterprise数据.
1.
将条目添加到SybaseIQinterfaces文件:访问远程数据86SybaseIQjones_1207mastertcpetherjones4101querytcpetherjones41012.
创建用户以连接到ASE:grantconnecttotstidentifiedbytsttstgrantdbatotst3.
以所添加用户的身份登录,创建"asejdbc"服务器类并添加外部登录名:isql-Utst-Ptsttst-Stst_iqdemocreateSERVERjones_1207CLASS'asejdbc'USING'jones:4101/tst_db'createexistingtablebilling_iqat'jones_1207.
tst_db.
.
billing_txt'select*frombilling_iqstatusnametelnoDBOTANICALLY1BBOTANICALL2(2rowsaffected)删除远程服务器使用SybaseCentral或DROPSERVER语句从ISYSSERVER系统表中删除远程服务器.
必须删除在该服务器上定义的所有远程表才能使此操作成功.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"使用远程服务器">"删除远程服务器".
更改远程服务器使用ALTERSERVER语句修改服务器的属性.
这些更改直到下一次与远程服务器连接时才生效.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"使用远程服务器">"更改远程服务器".
列出服务器上的远程表配置SybaseIQ时,拥有特定服务器上所提供远程表的列表的访问权限会很有帮助.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"使用远程服务器">"列出服务器上的远程表".
另请参见《参考:构件块、表和过程》>"sp_remote_tables系统过程".
访问远程数据系统管理指南第二卷87列出远程服务器功能sp_servercaps过程显示有关远程服务器功能的信息.
SybaseIQ使用此功能信息来确定可以向远程服务器传递多少SQL语句.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"使用远程服务器">"列出远程服务器功能".
另请参见《参考:构件块、表和过程》>"sp_servercaps系统过程".
外部登录SybaseIQ代表其客户端连接到远程服务器时会使用其客户端的名称和口令.
但是,您可以通过创建外部登录名来取代这一行为.
外部登录名是与远程服务器通信时使用的替代登录名和口令.
当SybaseIQ连接到远程服务器时,INSERT.
.
.
LOCATION将使用当前连接的用户ID的远程登录名,但前提是已使用CREATEEXTERNLOGIN创建远程登录名并且已使用CREATESERVER语句定义了远程服务器.
如果未定义远程服务器,或者未为当前连接的用户ID创建远程登录,则IQ将使用当前连接的用户ID和口令连接.
有关INSERT.
.
.
LOCATION使用远程登录名的详细信息和示例,请参见《参考:语句和选项》>"INSERT语句".
如果您使用集成登录,则SybaseIQ客户端的SybaseIQ名称和口令将与SybaseIQ用户ID映射到syslogins中的数据库登录ID和口令相同.
创建外部登录名只有DBA帐户或具有USERADMIN权限的帐户才能添加或修改外部登录名.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"使用远程服务器">"创建外部登录名".
有关详细信息,请参见《参考:语句和选项》>"SQL语句">"CREATEEXTERNLOGIN语句".
删除外部登录名使用DROPEXTERNLOGIN语句从SybaseIQ系统表中删除外部登录名.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"使用远程服务器">"删除外部登录名".
有关详细信息,请参见《参考:语句和选项》>"SQL语句">"DROPEXTERNLOGIN语句".
访问远程数据88SybaseIQ代理表远程数据的位置透明性是通过创建映射到远程对象的本地代理表启用的.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"使用代理表".
指定代理表位置CREATETABLE和CREATEEXISTINGTABLE都可以使用AT关键字定义现有对象的位置.
该位置字符串由句点或分号隔开的四部分组成.
分号允许在数据库和所有者字段中使用文件名和扩展名.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"使用代理表">"指定代理表位置".
示例下面的示例说明了位置字符串的用法:SybaseIQ:'testiq.
.
DBA.
employee'创建代理表CREATEEXISTINGTABLE语句创建映射到远程服务器上现有表的代理表.
SybaseIQ从位于远程位置的对象派生列属性和索引信息.
示例要在当前服务器上创建一个映射到iqdemo1服务器上employee远程表的名为p_employee的代理表,请使用以下语法:CREATEEXISTINGTABLEp_employeeAT'iqdemo1.
.
DBA.
employee'请参见《参考:语句和选项》>"CREATEEXISTINGTABLE语句".
访问远程数据系统管理指南第二卷89CREATETABLE语句CREATETABLE语句在远程服务器上创建新表,如果使用AT选项,则可以为该表定义代理表.
使用SybaseIQ数据类型定义列.
SybaseIQ会自动将数据转换为远程服务器的本机类型.
如果您使用CREATETABLE语句创建本地表和远程表,并随后使用DROPTABLE语句删除代理表,则远程表也将被删除.
但是,您可以使用DROPTABLE语句来删除使用CREATEEXISTINGTABLE语句创建的代理表.
这种情况下,未删除远程表.
示例以下语句在远程服务器iqdemo1上创建名为Employees的表,并创建映射到该远程位置的名为members的代理表:CREATETABLEmembers(membership_idINTEGERNOTNULL,member_nameCHAR(30)NOTNULL,office_heldCHAR(20)NULL)AT'iqdemo1.
.
DBA.
Employees'有关详细信息,请参见《参考:语句和选项》>"INSERT语句".
列出远程表上的列sp_remote_columns系统过程生成远程表上列的列表和这些数据类型的说明.
如果您正在输入CREATEEXISTINGTABLE语句并指定列的列表,则获取远程表上可用列的列表可能很有帮助.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"使用代理表">"列出远程表上的列".
有关详细信息,请参见《参考:构件块、表和过程》>"系统过程">"系统存储过程">"目录存储过程">"sp_remote_columns系统过程".
示例:两个远程表之间的连接下图说明演示数据库中映射到名为testiq的本地服务器的远程SybaseIQ表employee和department.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"连接远程表".
访问远程数据90SybaseIQ多个本地数据库SybaseIQ服务器上可能有多个本地数据库在同时运行.
通过将其它本地SybaseIQ数据库中的表定义为远程表,您可以执行跨数据库连接.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"连接多个本地数据库中的表".
将本机语句发送到远程服务器使用FORWARDTO语句将一个或多个语句以其本机语法发送到远程服务器.
可以通过两种方式使用此语句.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"将本机语句发送到远程服务器".
远程过程调用(RPC)SybaseIQ用户可以向支持过程调用功能的远程服务器发出过程调用.
SybaseIQ、SQLAnywhere和AdaptiveServerEnterprise以及Oracle和DB2都支持此功能.
发出远程过程调用与使用本地过程调用类似.
创建远程过程使用以下过程之一发出远程过程调用.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"使用远程过程调用(RPC)">"创建远程过程".
事务管理和远程数据事务提供一种对SQL语句进行分组的方式,这样可以将这些语句作为一个整体对待,即要么将这些语句执行的所有工作都提交到数据库,要么一个也不提交.
对远程表的事务管理和对本地SybaseIQ表的处理方法稍有不同.
对远程表的事务管理的处理方法在很大程度上就像在SQLAnywhere中一样,但有一些差异.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"创建数据库">"使用事务和隔离级别".
有关SybaseIQ中事务的一般性讨论,请参见《系统管理指南第一卷》>"事务和版本控制".
远程事务管理概述这种涉及远程服务器的事务管理方法使用两阶段提交协议.
SybaseIQ执行的策略可以确保大多数情况的事务完整性.
访问远程数据系统管理指南第二卷91请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"事务管理和远程数据">"远程事务管理概述".
事务管理的限制事务管理具有保存点和嵌套语句限制.
事务管理的限制为:不将保存点传播到远程服务器.
如果涉及远程服务器的事务中包含嵌套的BEGINTRANSACTION和COMMITTRANSACTION语句,则只处理最外层的一组语句.
系统不会将包含BEGINTRANSACTION和COMMITTRANSACTION语句的最里层一组语句传输到远程服务器.
内部操作本节介绍SQLAnywhere代表客户端应用程序对远程服务器执行的基础操作.
查询分析当从客户端接收到语句时,数据库服务器将对该语句进行分析.
如果该语句不是有效的SQLAnywhereSQL语句,数据库服务器将引发错误.
查询规范化在查询规范化中,系统将验证引用的对象并检查数据类型兼容性.
例如,请考虑下列查询:SELECT*FROMt1WHEREc1=10查询规范化阶段验证系统表中是否存在具有列c1的表t1.
它还验证列c1的数据类型是否和值10兼容.
例如,如果该列的数据类型为DATETIME,则系统将拒绝此语句.
查询预处理查询预处理准备进行优化的查询.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"内部操作">"查询预处理".
访问远程数据92SybaseIQ服务器功能定义到SybaseIQ的每个远程服务器都有一组与其关联的功能.
这些功能存储在syscapabilities系统表中.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"内部操作">"服务器功能".
语句的完整直通处理语句最有效的方式通常是尽可能多地向涉及的远程服务器传递原始语句.
缺省情况下,SybaseIQ尝试尽可能多地传递语句.
在很多情况下,这是最初提供给SybaseIQ的完整语句.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"内部操作">"语句的完整直通".
语句的部分直通如果某个语句包含对多个服务器的引用,或者使用远程服务器不支持的SQL功能,则会将查询分解为多个较简单的部分.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"内部操作">"语句的部分直通".
远程数据访问故障排除本节提供远程服务器访问故障排除的一些建议.
不支持远程数据的功能有些功能从不受SybaseIQ支持.
有些功能仅针对本地数据而受到支持.
SybaseIQ对SQLAnywhere列表具有以下附加功能:不支持Java数据类型.
在某些地理区域中使用组件集成服务(CIS)时,连接尝试将返回错误"无合适的驱动程序".
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"远程数据访问故障排除">"不支持远程数据的功能".
访问远程数据系统管理指南第二卷93区分大小写您的SybaseIQ数据库的区分大小写设置应该和所访问的任何远程服务器使用的设置匹配.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"远程数据访问故障排除">"区分大小写".
连接问题若要验证您是否可以连接到远程服务器,请执行到远程服务器的简单的直通语句以检查您的连接和远程登录配置.
例如:FORWARDTOtestiq{select@@version}请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"远程数据访问故障排除">"连接测试".
查询的一般问题如果您遇到某些类型的问题涉及SybaseIQ对远程表处理查询的方式,则了解SybaseIQ如何执行该查询通常会很有帮助.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"远程数据访问故障排除">"查询的一般问题".
管理远程数据访问连接如果您通过ODBC访问远程数据库,到远程服务器的连接就会被指定一个名称.
该名称可用于断开连接,作为取消远程请求的一种方法.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"访问远程数据">"远程数据访问故障排除">"管理通过ODBC执行的远程数据访问连接".
访问远程数据94SybaseIQ用于进行远程数据访问的服务器类本章介绍SybaseIQ如何与各种服务器类相连接.
服务器类概述远程连接的行为由CREATESERVER语句中的服务器类决定.
服务器类为SybaseIQ提供详细的服务器功能信息.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"用于远程数据访问的服务器类".
基于JDBC的服务器类当SybaseIQ在内部使用Java虚拟机和jConnectforJDBC5.
5连接到远程服务器时,使用的便是基于JDBC的服务器类.
基于JDBC的服务器类有:SybaseIQ和SQLAnywhereSybaseSQLAnywhere和AdaptiveServerEnterprise(版本10和更高版本).
JDBC类的配置说明在访问用基于JDBC的类定义的远程服务器时,请考虑最佳性能、远程服务器访问和远程服务器连接.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"用于远程数据访问的服务器类">"基于JDBC的服务器类">"JDBC类的配置说明".
服务器类sajdbc对于SybaseIQ或SQLAnywhere数据源,没有任何特殊的配置要求.
CREATESERVER语句中的参数值CREATESERVER语句中的USING参数采用以下形式:hostname:portnumber[/databasename].
其中:hostname–运行远程服务器的计算机用于进行远程数据访问的服务器类系统管理指南第二卷95portnumber–远程服务器监听的TCP/IP端口号.
SybaseIQ监听的缺省端口号是2638.
databasename–连接将使用的SybaseIQ数据库.
这是启动服务器时在-n开关中指定的名称,或是在DBN(DatabaseName)连接参数中指定的名称.
SybaseIQ示例若要配置名为testiq的SybaseIQ服务器(该服务器位于apple计算机上,并监听端口号2638),请使用:CREATESERVERtestiqCLASS'sajdbc'USING'apple:2638'请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"用于远程数据访问的服务器类">"基于JDBC的服务器类">"服务器类sajdbc">"CREATESERVER语句中的USING参数".
服务器类asejdbc具有服务器类asejdbc的服务器可以是AdaptiveServerEnterprise或SQLAnywhere版本10和更高版本.
虽然AdaptiveServerEnterprise数据源通常不需要进行特殊配置,但是ASE15.
5需要jConnect-6_0元数据存储过程和表.
请参见《访问远程数据》>"用于远程数据访问的服务器类">"基于JDBC的服务器类">"服务器类aseodbc">"安装jConnect6.
0元数据".
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"用于远程数据访问的服务器类">"基于JDBC的服务器类">"服务器类asejdbc".
数据类型转换当您发出CREATETABLE语句创建代理表时,SybaseIQ会自动将数据类型转换为相应的AdaptiveServerEnterprise数据类型.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"用于远程数据访问的服务器类">"基于JDBC的服务器类">"服务器类asejdbc".
安装jConnect6.
0元数据AdaptiveServerEnterprise15.
5数据的代理表需要使用jConnect6.
0元数据.
如果没有jConnect6.
0元数据,CREATEEXISTINGTABLE语句可能会返回错误"SQLAnywhere错误-667:无法访问表的列信息".
使用isql:1.
连接到AdaptiveServerEnterprise数据库.
用于进行远程数据访问的服务器类96SybaseIQ2.
按以下格式输入命令:isql-I-Usa-P-S-i$SYBASE/jConnect-6_0/sp/sql_server15.
0.
sql基于ODBC的服务器类SybaseIQ支持多种基于ODBC的服务器类.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"用于远程数据访问的服务器类">"基于ODBC的服务器类".
ODBC外部服务器定义基于ODBC的服务器的最常用方法是将其基于ODBC数据源.
要进行这样的定义,您必须在ODBC管理器中创建数据源名称(DSN).
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"用于远程数据访问的服务器类">"基于ODBC的服务器类">"定义ODBC外部服务器".
SybaseIQ示例与SybaseIQ的连接可以是:CREATESERVERtestiqCLASS'asaodbc'USING'driver=adaptiveserverIQ12.
0;eng=testasaiq;dbn=iqdemo;links=tcpip{}'有关创建SybaseIQ的ODBC数据源的详细信息,请参见《系统管理指南第一卷》>"SybaseIQ连接">"ODBC数据源".
服务器类saodbc若要访问可以支持多个数据库的SQLAnywhere数据库服务器,请创建ODBC数据源名称,并定义与每一个数据库的连接.
为创建的每一个ODBC数据源名称发出CREATESERVER语句.
具有服务器类saodbc的服务器如下所示:SybaseIQ版本12或更高版本SQLAnywhere对于SQLAnywhere或SybaseIQ数据源,没有任何特殊的配置要求.
用于进行远程数据访问的服务器类系统管理指南第二卷97服务器类aseodbcSybaseIQ要求必须在本地安装AdaptiveServerEnterpriseODBC驱动程序和OpenClient连接库,才能连接到具有aseodbc类的远程AdaptiveServer.
不过,其性能要优于具有asejdbc类的AdaptiveServer.
具有服务器类aseodbc的服务器为:AdaptiveServerEnterpriseSQLAnywhere(版本10和更高版本)请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"用于远程数据访问的服务器类">"基于ODBC的服务器类">"服务器类aseodbc".
服务器类db2odbc具有服务器类db2odbc的服务器是IBMDB2.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"用于远程数据访问的服务器类">"基于ODBC的服务器类">"服务器类db2odbc".
服务器类oraodbc使用服务器类oraodbc的服务器是Oracle10.
0或更高版本.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"用于远程数据访问的服务器类">"基于ODBC的服务器类">"服务器类oraodbc".
SybaseIQ到Oracle数据类型映射当您使用CREATETABLE语句在Oracle服务器上创建远程表时,SybaseIQ会将IQ数据类型转换为相应的Oracle数据类型:表5.
数据映射到新的远程Oracle表SybaseIQ数据类型Oracle数据类型BIGINTNUMBER(20,0)BINARY(n)if(n>255)LONGRAWelseRAW(n)BITNUMBER(1,0)CHAR(n)If(n>255)LONGelseVARCHAR(n)CHARACTERVARYING(n)VARCHAR2(n)CHARACTER(n)VARCHAR2(n)用于进行远程数据访问的服务器类98SybaseIQSybaseIQ数据类型Oracle数据类型DATEDATEDATETIMEDATEDECIMAL(prec,scale)NUMBER(prec,scale)DOUBLEFLOATFLOATFLOATINTNUMBER(11,0)LONGBINARYLONGRAWLONGVARCHARLONGorCLOBMONEYNUMBER(19,4)NUMERIC(prec,scale)NUMBER(prec,scale)REALFLOATSMALLDATETIMEDATESMALLINTNUMBER(5,0)SMALLMONEYNUMBER(10,4)TIMEDATETIMESTAMPDATETINYINTNUMBER(3,0)UNIQUEIDENTIFIERSTRCHAR(36)UNSIGNEDBIGINTNUMBER(20,0)UNSIGNEDINTNUMBER(11,0)UNSIGNEDINTEGERNUMBER(11,0)VARBINARY(n)if(n>255)LONGRAWelseRAW(n)VARCHAR(n)VARCHAR2(n)用于进行远程数据访问的服务器类系统管理指南第二卷99Oracle到SybaseIQ数据映射当您使用CREATEEXISTING语句为现有的Oracle表创建代理表时,SybaseIQ会将Oracle数据类型转换为相应的IQ数据类型.
表6.
数据映射到现有的Oracle表Oracle数据类型IQ数据类型BFILELONGBINARYBLOBLONGBINARYCHAR(n)CHAR(n)CLOBLONGVARCHARDATETIMESTAMPDEC(prec,scale)NUMERIC(prec,scale)DECIMAL(prec,scale)NUMERIC(prec,scale)DOUBLEPRECISIONDOUBLEFLOATDOUBLEINTNUMERIC(38.
0)INTEGERNUMERIC(38.
0)NCHAR(n)NCHAR(n)NCLOBLONGNVARCHARNUMBER(prec,scale)NUMERIC(prec,scale)NUMERIC(prec,scale)NUMERIC(prec,scale)NVARCHAR2(n)VARCHAR(n)RAW(n)VARBINARY(n)REALDOUBLESMALLINTNUMERIC(38.
0)TIMESTAMPTIMESTAMPVARCHAR2(n)VARCHAR(n)注意:用于进行远程数据访问的服务器类100SybaseIQSybaseIQ允许您将代理表映射到Oracle视图.
由于Oracle标识符始终以大写字母显示,因此您必须使用大写字母来创建或引用要映射到Oracle视图的任何代理表.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"用于远程数据访问的服务器类">"基于ODBC的服务器类">"服务器类oraodbc".
服务器类mssodbc具有mssodbc服务器类的服务器是MicrosoftSQLServer6.
5版(带ServicePack4).
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"用于远程数据访问的服务器类">"基于ODBC的服务器类">"服务器类mssodbc".
服务器类odbc不具有自己的服务器类的ODBC数据源使用odbc服务器类.
您可以使用任何ODBC驱动程序.
可以通过Microsoft数据访问组件(MDAC)发布(可在Microsoft下载中心上找到)获得MicrosoftODBC驱动程序的最新版本.
列出的Microsoft驱动程序版本是MDAC2.
0的组成部分.
MicrosoftExcel(Microsoft3.
51.
171300)每一个Excel工作簿都可以被视为包含若干个表的数据库.
数据库中的表可以映射到工作簿中的工作表.
当您在ODBC驱动程序管理器中配置ODBC数据源名称时,可以指定与该数据源相关联的缺省工作簿名称.
不过,当您发出CREATETABLE语句时,可以替换该缺省值并在位置字符串中指定工作簿名称.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"用于远程数据访问的服务器类">"基于ODBC的服务器类">"服务器类odbc">"MicrosoftExcel(Microsoft3.
51.
171300)".
MicrosoftFoxpro(Microsoft3.
51.
171300)您可以将多个Foxpro表一起存储在一个Foxpro数据库文件(.
dbc)内;或者,可以将每个表单独存储在各个.
dbf文件中.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"用于远程数据访问的服务器类">"基于ODBC的服务器类">"服务器类odbc">"MicrosoftFoxPro(Microsoft3.
51.
171300)".
LotusNotesSQL2.
0(2.
04.
0203)您可以从LotusWeb站点获取LotusNotesSQL2.
0(2.
04.
0203)驱动程序.
请阅读附随的文档,以便了解有关如何将Notes数据映射到关系表的说明.
您可以很轻松地将IQ表映射到Notes表单.
用于进行远程数据访问的服务器类系统管理指南第二卷101请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"远程数据和批量操作">"用于远程数据访问的服务器类">"基于ODBC的服务器类">"服务器类odbc">"LotusNotesSQL2.
0".
设置IQ访问Address示例文件设置IQ访问Address示例文件.
1.
使用NotesSQL驱动程序创建ODBC数据源.
数据库将是示例名文件c:\notes\data\names.
nsf.
应选中"映射特殊字符"选项.
对于此示例,"DataSourceName"是my_notes_dsn.
2.
创建IQ服务器:CREATESERVERnamesCLASS'odbc'USING'my_notes_dsn'3.
将Person表单映射到IQ表中:CREATEEXISTINGTABLEPersonAT'names.
.
.
Person'4.
查询该表SELECT*FROMPerson用于进行远程数据访问的服务器类102SybaseIQ使用日程表和事件自动完成任务本章介绍如何使用SybaseIQ的调度和事件处理功能来自动执行数据库管理和其它任务.
调度和事件处理简介对于很多数据库管理任务,最好是有计划有步骤地将其完成.
例如,定期备份过程是合理数据库管理过程的重要组成部分.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"维护数据库">"使用日程表和事件自动完成任务">"日程表和事件使用简介".
日程表通过对活动进行调度,您可以确保在一组预置的时间执行一组操作.
调度信息和事件处理程序都存储在数据库本身中.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"维护数据库">"使用日程表和事件自动完成任务">"了解日程表".
SybaseIQ示例注意:例如,使用SybaseIQ演示数据库iqdemo.
db.
CreatetableOrderSummary(c1date,c2int);createeventSummarizeschedulestarttime'6:00pm'on('Mon','Tue','Wed','Thu','Fri')handlerbegininsertintoDBA.
OrderSummaryselectmax(OrderDate),count(*)fromGROUPO.
SalesOrderswhereOrderDate=currentdateend定义日程表为了增加灵活性,日程表定义由多个组件组成.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"维护数据库">"使用日程表和事件自动完成任务">"了解日程表">"定义日程表".
使用日程表和事件自动完成任务系统管理指南第二卷103事件数据库服务器会跟踪几种系统事件.
在数据库服务器检查某系统事件且相应事件符合提供的触发条件时,会触发事件处理程序.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"维护数据库">"使用日程表和事件自动完成任务">"了解系统事件".
选择系统事件SybaseIQ跟踪若干个系统事件.
每个系统事件都提供一个您可以在其上挂接一组操作的挂钩.
数据库服务器为您跟踪事件,并在需要时执行操作(操作在事件处理程序中定义).
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"维护数据库">"使用日程表和事件自动完成任务">"了解系统事件".
定义事件的触发器状态每个事件定义都有一个与其关联的系统事件.
该事件也有一个或多个触发条件.
在满足系统事件的触发条件时,会触发事件处理程序.
注意:与SybaseIQ事件关联的触发器状态不同于SQLAnywhere触发器或AdaptiveServerEnterprise触发器,后两种触发器在用户尝试在指定表上执行指定的数据修改语句时自动执行.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"维护数据库">"使用日程表和事件自动完成任务">"了解系统事件">"定义事件的触发器状态".
SybaseIQ示例注意:例如,使用SybaseIQ演示数据库iqdemo.
db.
createeventSecurityChecktypeConnectFailedhandlerbegindeclarenum_failuresint;declareminsint;insertintoFailedConnections(log_time)values(currenttimestamp);selectcount(*)intonum_failuresfromFailedConnectionswherelog_time>=dateadd(minute,-5,currenttimestamp);if(num_failures>=3)thenselectdatediff(minute,last_notification,currenttimestamp)intominsfromNotification;if(mins>30)thenupdateNotificationsetlast_notification=currenttimestamp;call使用日程表和事件自动完成任务104SybaseIQxp_sendmail(recipient='DBAdmin',subject='SecurityCheck',"message"='over3failedconnectionsinlast5minutes')endifendifend事件处理程序事件处理程序不在触发相应事件的操作所在的连接上执行,因此不与客户端应用程序进行交互.
它们是使用事件创建者的权限执行的.
开发事件处理程序不管是用于调度事件的处理,还是用于系统事件处理,事件处理程序都包含复合语句,而且在很多方面都与存储过程类似.
可以添加循环、条件执行等等,还可以使用SybaseIQ调试工具来调试事件处理程序.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"维护数据库">"使用日程表和事件自动完成任务">"了解系统事件">"开发事件处理程序".
EVENT_PARAMETER函数提供事件处理程序的上下文信息.
请参见《参考:构件块、表和过程》.
有关使用事件处理的示例,请参见《系统管理指南第一卷》>"使用日程表和事件自动完成任务">"管理用户帐户和连接".
日程表和事件深入解析本节说明了数据库服务器如何处理日程表和事件定义.
数据库服务器如何检查系统事件事件按在CREATEEVENT语句中直接指定的事件类型进行分类.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"维护数据库">"使用日程表和事件自动完成任务">"日程表和事件深入解析">"数据库服务器如何检查系统事件".
数据库服务器如何检查预定时间在数据库服务器启动时以及每当调度的事件处理程序完成时,都会进行调度的事件时间的计算.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"维护数据库">"使用日程表和事件自动完成任务">"日程表和事件深入解析">"数据库服务器如何检查调度事件".
使用日程表和事件自动完成任务系统管理指南第二卷105事件处理程序是如何执行的触发事件处理程序时,将建立临时的内部连接,并在其上执行事件处理程序.
该处理程序不在导致该处理程序触发的连接中执行,因此与客户端应用程序交互的语句(例如MESSAGE…TOCLIENT)在事件处理程序中没有任何意义.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"维护数据库">"使用日程表和事件自动完成任务">"事件处理任务">"将事件添加到数据库中".
调度和事件处理任务本节全面介绍了与自动处理日程表和事件相关的任务.
将日程表或事件添加到数据库中可以在SybaseCentral中和使用SQL添加日程表和事件.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"维护数据库">"使用日程表和事件自动完成任务">"事件处理任务">"将事件添加到数据库中".
将手动触发的事件添加到数据库中如果您创建的事件处理程序没有可触发它的日程表或系统事件,则仅当手动触发时它才会执行.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"维护数据库">"使用日程表和事件自动完成任务">"事件处理任务">"将手动触发的事件添加到数据库中".
使用ALTEREVENT语句更改事件.
请参见《参考:语句和选项》.
触发事件处理程序任何事件处理程序都可以手动触发,以及因日程表或系统事件而执行.
您会发现,在开发事件处理程序过程中,手动触发事件是很有用的;对于生产环境中的某些事件,它也是很有用的.
例如,您可能已经有了一个按月调度的销售报表,但有时并未到月末也希望获得销售报表.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"维护数据库">"使用日程表和事件自动完成任务">"事件处理任务">"触发事件处理程序".
有关触发的详细信息,请参见《参考:语句和选项》中的TRIGGEREVENT语句.
使用日程表和事件自动完成任务106SybaseIQ调试事件处理程序调试是软件开发必不可少的一个环节.
在开发过程中可以调试事件处理程序.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"维护数据库">"使用日程表和事件自动完成任务">"事件处理任务">"调试事件处理程序".
检索有关事件或日程表的信息SybaseIQ在系统表SYSEVENT、SYSEVENTTYPE和SYSSCHEDULE中存储有关事件、系统事件和日程表的信息.
使用ALTEREVENT语句更改事件时,需要指定事件名称和(可选)日程表名称.
使用TRIGGEREVENT语句触发事件时,需要指定事件名称.
通过查询系统表SYSEVENT,可以列出事件名称.
例如:SELECTevent_id,event_nameFROMSYSEVENT通过查询系统表SYSSCHEDULE,可以列出日程表名称.
例如:SELECTevent_id,sched_nameFROMSYSSCHEDULE每个事件都具有唯一的事件ID.
可使用SYSEVENT和SYSSCHEDULE的event_id列将事件与关联的日程表匹配.
使用日程表和事件自动完成任务系统管理指南第二卷107使用日程表和事件自动完成任务108SybaseIQ使用JDBC访问数据本附录介绍如何使用JDBC访问数据.
您既可从客户端应用程序使用JDBC,也可从数据库内部使用JDBC.
在数据库中加入编程逻辑时,使用JDBC的Java类也可以起到SQL存储过程的作用,而且功能比SQL存储过程更强.
JDBC概述JDBC为Java应用程序提供了SQL接口:如果您要从Java访问关系数据,则可利用JDBC调用进行此访问.
本附录并不深入讲解JDBC数据库接口,而是提供一些简单示例来介绍JDBC,并阐释如何在服务器内部和外部使用JDBC.
此外,本附录将提供有关服务器端使用JDBC(在数据库服务器内部运行)的详细信息.
这些示例说明在SybaseIQ中使用JDBC时的一些独特功能.
有关JDBC编程的详细信息,请参见讲解JDBC编程的书籍.
JDBC和SybaseIQ您可以通过以下方式来配合使用JDBC和SybaseIQ:Java客户端应用程序可对SybaseIQ发出JDBC调用.
该连接通过SybasejConnectJDBC驱动程序或通过iAnywhereJDBC驱动程序进行.
本附录中的术语客户端应用程序指用户计算机上运行的应用程序和中层应用程序服务器上运行的逻辑.
数据库中安装的服务器Java类中的JDBC可使用内部JDBC驱动程序进行JDBC调用,以此来访问和修改数据库中的数据.
本附录重点介绍服务器端的JDBC.
JDBC资源必需的软件使用SybasejConnect驱动程序需要TCP/IP.
您的计算机上可能已有SybasejConnect驱动程序,具体有无取决于所安装的SybaseIQ.
另请参见jConnect驱动程序文件(第127页)使用JDBC访问数据系统管理指南第二卷109选择JDBC驱动程序现为SybaseIQ提供了两种JDBC驱动程序:表7.
驱动程序定义jConnect此驱动程序是100%的Java驱动程序.
它使用TDS客户端/服务器协议与SybaseIQ进行通信.
iAnywhereJDBC驱动程序此驱动程序使用命令序列客户端/服务器协议与SybaseIQ进行通信.
它的行为与ODBC、嵌入式SQL和OLEDB应用程序是一致的.
有关jConnect文档,请参见《jConnectforJDBC》.
在选择使用哪个驱动程序时,可能需要考虑下列因素:功能-这两个驱动程序都兼容JDK2.
iAnywhereJDBC驱动程序提供完全可滚动的游标,jConnect则不能.
纯Java-jConnect驱动程序是纯Java解决方案.
iAnywhereJDBC驱动程序需要SybaseIQ或AdaptiveServerAnywhereODBC驱动程序,它不是纯Java解决方案.
性能-在大多数情况下,iAnywhereJDBC驱动程序所提供的性能要比jConnect驱动程序好一些.
兼容性-jConnect驱动程序使用的TDS协议可与AdaptiveServerEnterprise共享.
该驱动程序行为的某些方面受此协议的控制,并被配置为与AdaptiveServerEnterprise兼容.
这两种驱动程序都可用于Windows95/98/Me和WindowsNT/2000/2003/XP,以及受支持的UNIX和Linux操作系统.
JDBC注意事项运行Java应用程序时请注意以下事项:使用iAnywhereJDBC驱动程序通过dbisqlJava连接到SybaseIQ12.
5服务器时存在问题.
有关详细信息,请参见《系统管理指南第一卷》>"故障排除提示">"数据截断或数据转换错误".
运行在SybaseIQ中的Java应用程序比运行在SunJava虚拟机(JVM)外的应用程序慢.
尽管存在此限制,但Sybase仍然建议您通过增加IQJVM用于数据库选项JAVA_HEAP_SIZE和JAVA_NAMESPACE_SIZE的可用内存来优化您的应用程序;有关这两个选项的信息,请参见《参考:语句和选项》>"数据库选项">"JAVA_HEAP_SIZE".
JDBC程序结构JDBC程序结构具有一系列事件.
JDBC应用程序中通常会发生以下事件序列:使用JDBC访问数据110SybaseIQ创建连接对象-调用DriverManager类的getConnection类方法即可创建Connection对象,并与数据库建立连接.
生成语句对象-Connection对象会生成Statement对象.
传递SQL语句-在数据库环境内部执行的SQL语句传递到Statement对象.
如果该语句是一个查询,则此操作会返回ResultSet对象.
ResultSet对象包含SQL语句返回的数据,但一次只显示一行(与游标的工作方式类似).
循环访问结果集中的行-ResultSet对象的next方法可执行两种操作:当前行(通过ResultSet对象显示的结果集中的行)前进一行.
返回布尔值(true/false),指示要前进到的目标行是否真正存在.
为每行检索值-通过识别ResultSet对象中每一列的名称或位置来检索每一列的值.
可以使用getDate方法来获取当前行中某列的值.
Java对象可使用JDBC对象与数据库交互作用并获取数据供自己使用,例如,获取数据后加以操纵或将其用在其它查询中.
服务器端JDBC功能JDBC1.
2是JDK1.
1的一部分.
JDBC2.
0是Java2(JDK1.
2)的一部分.
数据库中的Java提供JDK1.
1版的子集,因此内部JDBC驱动程序支持JDBC1.
2版.
内部JDBC驱动程序(asajdbc)使您能从服务器端的Java应用程序使用JDBC2.
0的某些功能,但未提供完整的JDBC2.
0支持.
属于数据库支持中Java一部分的java.
sql包中的JDBC类处于1.
2级.
属于JDBC2.
0一部分的服务器端功能在sybase.
sql.
ASA包中实现.
要使用JDBC2.
0功能,您必须将JDBC对象转换为sybase.
sql.
ASA包中相应的类,而不是java.
sql包中的类.
声明为java.
sql的类仅限于JDBC1.
2功能.
sybase.
sql.
ASA中的类如下所示:JDBC类Sybase内部驱动程序类java.
sql.
Connectionsybase.
sql.
ASA.
SAConnectionjava.
sql.
Statementsybase.
sql.
ASA.
SAStatementjava.
sql.
PreparedStatementsybase.
sql.
ASA.
SAPreparedStatementjava.
sql.
CallableStatementsybase.
sql.
ASA.
SACallableStatementjava.
sql.
ResultSetMetaDatasybase.
sql.
ASA.
SAResultSetMetaDatajava.
sql.
ResultSetsybase.
sql.
SAResultSetjava.
sql.
DatabaseMetaDatasybase.
sql.
SADatabaseMetaData以下函数为预准备语句提供一个ResultSetMetaData对象,无需ResultSet,也不用执行该语句.
此函数不是JDBC标准的一部分.
使用JDBC访问数据系统管理指南第二卷111ResultSetMetaDatasybase.
sql.
ASA.
SAPreparedStatement.
describe()JDBC2.
0限制以下类是JDBC2.
0核心接口的一部分,但sybase.
sql.
ASA包中没有这些类:java.
sql.
Blobjava.
sql.
Clobjava.
sql.
Refjava.
sql.
Structjava.
sql.
Arrayjava.
sql.
Mapsybase.
sql.
ASA包中没有以下JDBC2.
0核心函数:sybase.
sql.
ASA中的类缺少的函数SAConnectionjava.
util.
MapgetTypeMap()voidsetTypeMap(java.
util.
Mapmap)SAPreparedStatementvoidsetRef(intpidx,java.
sql.
Refr)voidsetBlob(intpidx,java.
sql.
Blobb)voidsetClob(intpidx,java.
sql.
Clobc)voidsetArray(intpidx,java.
sql.
Arraya)SACallableStatementObjectgetObject(pidx,java.
util.
Mapmap)java.
sql.
RefgetRef(intpidx)java.
sql.
BlobgetBlob(intpidx)java.
sql.
ClobgetClob(intpidx)java.
sql.
ArraygetArray(intpidx)使用JDBC访问数据112SybaseIQsybase.
sql.
ASA中的类缺少的函数SAResultSetObjectgetObject(intcidx,java.
util.
Mapmap)java.
sql.
RefgetRef(intcidx)java.
sql.
BlobgetBlob(intcidx)java.
sql.
ClobgetClob(intcidx)java.
sql.
ArraygetArray(intcidx)ObjectgetObject(StringcName,java.
util.
Mapmap)java.
sql.
RefgetRef(StringcName)java.
sql.
BlobgetBlob(StringcName)java.
sql.
ClobgetClob(StringcName)java.
sql.
ArraygetArray(StringcName)客户端与服务器端JDBC连接的区别客户端JDBC与数据库服务器中的JDBC之间的区别是它们与数据库环境建立连接的方式不同.
客户端-在客户端JDBC中,建立连接需要SybasejConnectJDBC驱动程序.
将参数传递给DriverManager.
getConnection就建立了连接.
从客户端应用程序的角度看,数据库环境是外部应用程序.
服务器端-在数据库服务器中使用JDBC时,连接已经存在.
jdbc:default:connection的值传递给DriverManager.
getConnection,从而使JDBC应用程序能在当前用户连接中工作.
这是一个快速、有效且安全的操作,因为客户端应用程序已通过了数据库安全检查建立了连接.
用户ID和口令一经提供,便不需要再次提供.
asajdbc驱动程序只能连接到当前连接的数据库.
您可以用这样一种方式编写JDBC类:使用一个条件语句构造URL,让JDBC类既能在客户端运行,又能在服务器端运行.
外部连接需要计算机名称和端口号,而内部连接需要jdbc:default:connection.
建立JDBC连接本节介绍那些用来从Java应用程序建立JDBC数据库连接的类.
使用JDBC访问数据系统管理指南第二卷113使用jConnect从JDBC客户端应用程序建立连接如果希望从JDBC应用程序访问数据库系统表(数据库元数据),必须向数据库添加一组jConnect系统对象.
如果希望从JDBC应用程序访问数据库系统表(数据库元数据),必须向数据库添加一组jConnect系统对象.
Asajdbc和jConnect共享相同的数据库元数据支持的存储过程.
这些过程会缺省安装到所有数据库.
iqinit开关-i会阻止此安装.
-i开关对iqinit和SQLAnywhere实用程序dbinit是通用的.
有关-i开关的说明,请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-数据库管理">"管理数据库">"数据库管理实用程序">"初始化实用程序(dbinit)".
以下完整的Java应用程序是一个命令行应用程序,它连接到正在运行的数据库,在命令行显示一组信息,然后结束.
对于任何JDBC应用程序,要使用数据库数据,第一步都必须建立连接.
另请参见从服务器端的JDBC类建立连接(第117页)SybasejConnectJDBC驱动程序(第126页)运行外部连接示例(第116页)分布式应用程序示例(第131页)外部连接示例代码用来建立连接的方法的源代码.
源代码位于SybaseIQ安装目录下Windows上的C:\DocumentsandSettings\AllUsers\SybaseIQ\samples\SQLAnywhere\JDBC目录内或UNIX上的$SYBASE/IQ-15_3/samples/sqlanywhere/JDBC内的文件JDBCExamples.
java中的main方法和ASAConnect方法内://Importthenecessaryclassesimportjava.
sql.
*;//JDBCimportcom.
sybase.
jdbc.
*;//SybasejConnectimportjava.
util.
Properties;//Propertiesimportsybase.
sql.
*;//Sybaseutilitiesimportasademo.
*;//ExampleclassesprivatestaticConnectionconn;publicstaticvoidmain(Stringargs[]){conn=null;StringmachineName;if(args.
length!
=1){machineName="localhost";}else{machineName=newString(args[0]);}使用JDBC访问数据114SybaseIQASAConnect("dba","sql",machineName);if(conn!
=null){System.
out.
println("Connectionsuccessful");}else{System.
out.
println("Connectionfailed");}try{serializeVariable();serializeColumn();serializeColumnCastClass();}catch(Exceptione){System.
out.
println("Error:"+e.
getMessage());e.
printStackTrace();}}}privatestaticvoidASAConnect(StringUserID,StringPassword,StringMachinename){//usesglobalConnectionvariableString_coninfo=newString(Machinename);Properties_props=newProperties();_props.
put("user",UserID);_props.
put("password",Password);//LoadtheSybaseDrivertry{Class.
forName("com.
sybase.
jdbc.
SybDriver").
newInstance();StringBuffertemp=newStringBuffer();//UsetheSybasejConnectdriver.
.
.
temp.
append("jdbc:sybase:Tds:");//toconnecttothesuppliedmachinename.
.
.
temp.
append(_coninfo);//onthedefaultportnumberforASA.
.
.
temp.
append(":2638");//andconnect.
System.
out.
println(temp.
toString());conn=DriverManager.
getConnection(temp.
toString(),_props);}catch(Exceptione){System.
out.
println("Error:"+e.
getMessage());e.
printStackTrace();}}使用JDBC访问数据系统管理指南第二卷115外部连接示例如何工作外部连接示例是Java命令行应用程序.
导入包该应用程序需要若干库,这些库在JDBCExamples.
java的最先几行导入:java.
sql包中包含所有JDBC应用程序都需要的SunMicrosystemsJDBC类.
该类位于Java子目录下的classes.
zip文件中.
使用jConnect建立连接的所有应用程序都需要从com.
sybase.
jdbc导入的SybasejConnectJDBC驱动程序.
该类位于Java子目录下的jdbcdrv.
zip文件中.
该应用程序使用属性列表.
处理属性列表需要java.
util.
Properties类.
该类位于Java子目录下的classes.
zip文件中.
sybase.
sql包中包含用于序列化的实用程序.
该类位于Java子目录下的asajdbc.
zip文件中.
asademo包中包含某些示例中用到的类.
该类位于java子目录下的asademo.
jar文件中.
main方法每个Java应用程序都需要一个具有main方法的类,该方法是在程序启动时调用的方法.
在此简单示例中,JDBCExamples.
main是应用程序中的唯一方法.
JDBCExamples.
main方法执行以下任务:如果提供了计算机名称,则用计算机名称处理命令行参数.
缺省情况下,计算机名称是适用于个人数据库服务器的localhost.
调用ASAConnect方法建立连接.
执行将数据滚动到命令行的多个方法.
ASAConnect方法JDBCExamples.
ASAConnect方法执行以下任务:使用SybasejConnect连接到缺省的运行数据库.
Class.
forName装载jConnect.
使用newInstance方法能解决某些浏览器中的问题.
StringBuffer语句会根据命令行所提供的文字字符串和已有的计算机名称建立连接字符串.
DriverManager.
getConnection使用连接字符串建立连接.
将控制权还给调用方法.
运行外部连接示例本节介绍如何运行外部连接示例1.
在系统命令提示符下,转到SybaseIQ安装目录.
使用JDBC访问数据116SybaseIQ2.
转到IQ-15_3/java子目录3.
确保CLASSPATH环境变量包含当前目录(.
)以及导入的zip文件.
例如,在命令提示符下(应全部在一行上输入):setclasspath=.
.
\java\jdbcdrv.
zip;.
;.
.
\java\asajdbc.
zip;asademo.
jarJava的默认zip文件名为classes.
zip.
对于任何名为classes.
zip文件中的类,您只需CLASSPATH变量中的目录名,无需zip文件名本身.
对于其它名称的文件中的类,您必须提供zip文件名.
您需要CLASSPATH中的当前目录来运行示例.
4.
确保数据库已装载到运行TCP/IP的数据库服务器上.
您可以在本地计算机上使用以下命令(从IQ-15_3/samples/sqlanywhere子目录)启动该服务器:在UNIX平台上:start_iq.
.
.
/iqdemo在Windows平台上:start_iq.
.
.
\iqdemo5.
在命令提示符下输入以下内容,运行该示例:javaJDBCExamples如果希望对另一计算机上运行的服务器尝试此命令,必须输入该计算机的正确名称.
缺省名称为localhost,它是当前计算机名称的别名.
6.
确认命令提示符下出现人员和产品列表.
如果连接尝试失败,则显示的是错误消息.
请确认是否已执行了所需的全部步骤.
请检查CLASSPATH是否正确.
不正确的CLASSPATH将导致无法找到类.
另请参见从服务器端的JDBC类建立连接(第117页)使用jConnect从JDBC客户端应用程序建立连接(第114页)SybasejConnectJDBC驱动程序(第126页)从服务器端的JDBC类建立连接JDBC中的SQL语句是使用Connection对象的createStatement方法构建的.
即使是在服务器内部运行的类,也需要建立连接以创建Connection对象.
从服务器端的JDBC类建立连接比建立外部连接更为直接.
因为已连接的用户将执行服务器端的类,而该类只需使用当前连接.
有关JDBC连接的说明自动提交行为-JDBC规范要求在每个数据修改语句后缺省执行COMMIT.
当前,服务器端JDBC行为是提交.
您可使用以下语句控制这一行为:conn.
setAutoCommit(false);使用JDBC访问数据系统管理指南第二卷117其中conn是当前的连接对象.
连接缺省值-从服务器端的JDBC对getConnection("jdbc:default:connection")的调用中,只有第一个调用使用缺省值创建新连接.
后续调用返回当前连接的包装,所有连接属性均保持不变.
如果在初始连接中将AutoCommit设为OFF,同一Java代码中,任何后续getConnection调用所返回的连接中的AutoCommit均设置为OFF.
您可能希望确保关闭连接会将连接属性重置为缺省值,这样,所获得的后续连接就会采用标准的JDBC值.
以下代码示范可实现这一点:Connectionconn=DriverManager.
getConnection("");booleanoldAutoCommit=conn.
getAutoCommit();try{//docodehere}finally{conn.
setAutoCommit(oldAutoCommit);}此处的讨论不仅适用于AutoCommit,也适用于TransactionIsolation和ReadOnly等其它连接属性.
另请参见使用jConnect从JDBC客户端应用程序建立连接(第114页)SybasejConnectJDBC驱动程序(第126页)运行外部连接示例(第116页)服务器端连接的示例代码以下是服务器端连接的示例源代码.
该源代码位于SybaseIQ安装目录下C:\DocumentsandSettings\AllUsers\SybaseIQ\samples\SQLAnywhere\JDBC目录中的JDBCExamples.
java的InternalConnect方法中:publicstaticvoidInternalConnect(){try{conn=DriverManager.
getConnection("jdbc:default:connection");System.
out.
println("HelloWorld");}catch(Exceptione){System.
out.
println("Error:"+e.
getMessage());e.
printStackTrace();}}}服务器端连接示例如何工作在此简单示例中,InternalConnect()是应用程序中使用的唯一方法.
该应用程序只需要在JDBCExamples.
java类的第一行导入一个库(JDBC).
其它库供外部连接使用.
名为java.
sql的包中包含JDBC类.
使用JDBC访问数据118SybaseIQInternalConnect()方法执行以下任务:1.
使用当前连接与缺省的运行数据库建立连接:DriverManager.
getConnection使用jdbc:default:connection的连接字符串建立连接.
2.
在当前标准输出(服务器窗口)中显示HelloWorld.
System.
out.
println执行这一显示任务.
3.
如果尝试连接时出现错误,服务器窗口将显示一条错误消息,同时显示出现错误的位置.
try和catch指令提供了处理错误的框架.
4.
该类终止.
运行服务器端连接示例本节介绍如何运行服务器端连接示例.
1.
如果尚未编译JDBCExamples.
java文件,先编译该文件.
如果您使用的是JDK,可以在命令提示符下从SybaseIQ安装目录下的C:\DocumentsandSettings\AllUsers\SybaseIQ\samples\SQLAnywhere\JDBC目录中执行以下任务:javacJDBCExamples.
java2.
启动使用演示数据库的数据库服务器.
您可以在本地计算机上使用以下命令(从/ASIQ-12_7/java子目录)启动该服务器:在UNIX平台上:start_iq.
.
.
/iqdemo在Windows平台上:start_iq.
.
.
\iqdemo在这种情况下,由于未使用jConnect,因此可以不用TCP/IP网络协议.
但您必须至少有8Mb可用高速缓存,才能使用数据库中的Java类.
3.
在演示数据库中安装类.
连接到演示数据库后,即可使用以下命令从InteractiveSQL进行安装:INSTALLJAVANEWFROMFILE'C:\DocumentsandSettings\AllUsers\SybaseIQ\samples\SQLAnywhere\JDBC\JDBCExamples.
class'其中path是安装目录的路径.
您也可使用SybaseCentral安装此类.
在连接到演示数据库时,打开"JavaObjects"文件夹,然后双击"添加类"(AddClass).
然后按向导中的说明进行操作.
4.
您现在可调用此类的InternalConnect方法,就像调用存储过程一样:CALLJDBCExamples>>InternalConnect()第一次在会话中调用Java类时,必须装载内部Java虚拟机.
这可能需要几秒钟.
5.
确认服务器屏幕上是否出现HelloWorld这一消息.
使用JDBC访问数据系统管理指南第二卷119使用JDBC访问数据在数据库中保存某些类或全部类的Java应用程序大大优于传统的SQL存储过程.
不过,在入门阶段,最好并行使用SQL存储过程来证实JDBC的功能,这样或许会有所帮助.
在下面的示例中,我们编写了向Department表中插入行的Java类.
与其它接口一样,JDBC中的SQL语句要么为静态,要么为动态.
静态SQL语句在Java应用程序中构造,然后会发送到数据库.
数据库服务器会分析该语句,选择执行计划,然后执行该语句.
语法分析与选择执行计划统称为准备语句.
如果某条类似的语句必须被执行多次(例如,向一个表中插入多次),使用静态SQL会带来很大的开销,因为每次都必须执行准备步骤.
相对而言,动态SQL语句包含占位符.
只需用这些占位符准备一次语句,就可以多次执行语句,省去了额外的准备开销.
本节使用静态SQL.
动态SQL将在后面一节讨论.
其它JDBC说明访问权限-与数据库中的所有Java类一样,包含JDBC语句的类可由任何用户访问.
没有等同于GRANTEXECUTE语句(该语句授予执行过程的权限)的语句,也无需用类所有者的名称限定类名称.
执行权限-执行Java类时需要具有执行这些类的连接权限.
此行为与存储过程的行为不同,执行存储过程需要所有者权限.
安装JDBCExamples类本节介绍如何安装JDBCExamples.
class以及为本附录其余部分的JDBC示例做准备.
示例代码本节中的代码段取自安装目录下的完整类C:\DocumentsandSettings\AllUsers\SybaseIQ\samples\SQLAnywhere\JDBC\JDBCExamples.
java.
安装JDBCExamples类1.
如果尚未安装JDBCExamples类,请在演示数据库中安装JDBCExamples.
class文件.
2.
从InteractiveSQL连接到演示数据库后,请在"SQL语句"窗格中输入以下命令:INSTALLJAVANEWFROMFILE'C:\DocumentsandSettings\AllUsers\SybaseIQ\samples\SQLAnywhere\JDBC\JDBCExamples.
class'其中path是安装目录的路径.
使用JDBC访问数据120SybaseIQ您也可使用SybaseCentral安装此类.
在连接到演示数据库时,打开"JavaObjects"文件夹,然后双击"添加Java类"(AddJavaClass)或JAR.
然后按向导中的说明进行操作.
使用JDBC执行插入、更新和删除Statement对象执行静态SQL语句.
您可使用Statement对象的executeUpdate方法执行INSERT、UPDATE和DELETE等SQL语句,这些语句不返回结果集.
诸如CREATETABLE的语句及其它数据定义语句也可使用executeUpdate来执行.
以下代码段说明了JDBC如何执行INSERT语句.
它使用名为conn的Connection对象中所包含的内部连接.
使用JDBC从外部应用程序插入值的代码需要使用另一不同连接,但其它方面均保持不变.
publicstaticvoidInsertFixed(){//returnscurrentconnectionconn=DriverManager.
getConnection("jdbc:default:connection");//Disableautocommitconn.
setAutoCommit(false);Statementstmt=conn.
createStatement();IntegerIRows=newInteger(stmt.
executeUpdate("INSERTINTODepartment(dept_id,dept_name)"+"VALUES(201,'EasternSales')"));//PrintthenumberofrowsupdatedSystem.
out.
println(IRows.
toString()+"rowinserted");}注意:此代码段是JDBCExamples类的InsertFixed方法的一部分.
在Windows上,可以使用C:\DocumentsandSettings\AllUsers\SybaseIQ\samples\SQLAnywhere\JDBC中的build.
bat来构建此类.
setAutoCommit方法关闭自动提交行为,因此只有执行显式COMMIT指令,才会提交更改.
executeUpdate方法返回一个整数,该数字反映受操作影响的行数.
在此情况下,成功的INSERT会返回值一(1).
整数返回类型转换为Integer对象.
Integer类是基本int数据类型的包装,它提供一些有用的方法,如toString().
整数IRows转换为要输出的字符串,输出将显示在服务器窗口中.
运行JDBCInsert示例创建非常简单的JDBC类.
1.
以用户IDdba的身份使用InteractiveSQL连接到演示数据库.
2.
确保已安装JDBCExamples类.
它是与其它Java示例类一起安装的.
3.
按以下方式调用方法:使用JDBC访问数据系统管理指南第二卷121CALLJDBCExamples>>InsertFixed()4.
确认department表中已添加一行.
SELECT*FROMdepartment不提交ID为201的行.
您可执行ROLLBACK语句以删除该行.
向Java方法传递参数可以展开InsertFixed方法,来说明如何将参数传递给Java方法.
以下方法使用在调用中传递给该方法的参数作为插入值:publicstaticvoidInsertArguments(Stringid,Stringname){try{conn=DriverManager.
getConnection("jdbc:default:connection");StringsqlStr="INSERTINTODepartment"+"(dept_id,dept_name)"+"VALUES("+idname+"')";//ExecutethestatementStatementstmt=conn.
createStatement();IntegerIRows=newInteger(stmt.
executeUpdate(sqlStr.
toString()));//PrintthenumberofrowsupdatedSystem.
out.
println(IRows.
toString()+"rowinserted");}catch(Exceptione){System.
out.
println("Error:"+e.
getMessage());e.
printStackTrace();}}使用带参数的Java方法这两个参数是部门ID(整数)和部门名称(字符串).
由于两个参数是SQL语句字符串的一部分,因此它们在此处都作为字符串传递给方法.
INSERT是静态语句,除SQL自身外,它不带任何参数.
如果提供的参数数目或类型有错误,将出现"ProcedureNotFound"错误.
1.
如果尚未在演示数据库中安装JDBCExamples.
class文件,请安装该文件.
2.
从InteractiveSQL连接到演示数据库,然后输入以下命令:callJDBCExamples>>InsertArguments('203','NorthernSales')3.
检查Department表中是否已另外添加了一行:SELECT*FROMDepartment使用JDBC访问数据122SybaseIQ4.
回退更改,使数据库保持原样:ROLLBACK使用JDBC的查询Statement对象执行静态查询和不返回结果集的语句.
对于查询,应使用Statement对象的executeQuery方法.
这将在ResultSet对象中返回结果集.
以下代码段说明了如何在JDBC中处理查询.
此代码段将产品的总库存值放在名为inventory的变量中.
产品名称包含在String变量prodname中.
此示例可用作JDBCExamples类的Query方法.
此示例假定已建立了内部或外部连接,该连接包含在名为conn的Connection对象中.
它还假定了变量publicstaticvoidQuery(){intmax_price=0;try{conn=DriverManager.
getConnection("jdbc:default:connection");//BuildthequeryStringsqlStr="SELECTid,unit_price"+"FROMproduct";//ExecutethestatementStatementstmt=conn.
createStatement();ResultSetresult=stmt.
executeQuery(sqlStr);while(result.
next()){intprice=result.
getInt(2);System.
out.
println("Priceis"+price);if(price>max_price){max_price=price;}}}catch(Exceptione){System.
out.
println("Error:"+e.
getMessage());e.
printStackTrace();}returnmax_price;}运行示例在演示数据库中安装JDBCExamples类后,可以在InteractiveSQL中使用以下语句执行该方法:selectJDBCExamples>>Query()使用JDBC访问数据系统管理指南第二卷123注释该查询选择名为prodname的所有产品的数量和单价.
这些结果返回到名为result的ResultSet对象中.
遍历结果集内的每一行.
该循环使用next方法.
对于每一行,每列的值都使用getInt方法检索到一个整数变量中.
ResultSet也有用于其它数据类型的方法,例如getString、getDate和getBinaryString.
getInt方法的参数是列的索引号,索引号是从1开始编排的.
从SQL到Java的数据类型转换是按照《SybaseIQ参考手册》的"SQL数据类型"一章的"Java/SQL数据类型转换"中介绍的信息执行的.
SybaseIQ支持双向滚动游标.
不过,JDBC只提供next方法,相当于在结果集中向前滚动.
该方法向调用环境返回max_price的值,InteractiveSQL在"结果"窗格中显示该值.
另请参见分布式应用程序(第129页)插入和检索对象(第125页)使用预准备语句进行更有效的访问如果使用Statement接口,则将分析每条发送到数据库的语句,生成访问计划,然后执行该语句.
实际执行语句前的步骤称为准备语句.
如果使用PreparedStatement接口,将会在性能方面获得一些益处.
这样您就可以使用占位符来准备语句,然后在执行语句时向占位符赋值.
使用预准备语句在执行多个类似的操作(如插入多行)时特别有用.
有关预准备语句的详细信息,请参见《参考:语句和选项》>"SQL语句">"PREPARE语句[ESQL]".
示例以下示例说明如何使用PreparedStatement接口,只不过插入单行并未有效地利用预准备语句.
JDBCExamples类的以下方法执行一个预准备语句:publicstaticvoidJInsertPrepared(intid,Stringname)try{conn=DriverManager.
getConnection("jdbc:default:connection");//BuildtheINSERTstatement//isaplaceholdercharacterStringsqlStr="INSERTINTODepartment"+"(dept_id,dept_name)"+"VALUES使用JDBC访问数据124SybaseIQ//PreparethestatementPreparedStatementstmt=conn.
prepareStatement(sqlStr);stmt.
setInt(1,id);stmt.
setString(2,name);IntegerIRows=newInteger(stmt.
executeUpdate());//PrintthenumberofrowsupdatedSystem.
out.
println(IRows.
toString()+"rowinserted");}catch(Exceptione){System.
out.
println("Error:"+e.
getMessage());e.
printStackTrace();}}运行示例在演示数据库中安装JDBCExamples类后,可输入以下语句执行此示例:callJDBCExamples>>InsertPrepared(202,'EasternSales')字符串参数括在单引号中,这是适用于SQL的规范.
如果从Java应用程序调用此方法,则应使用双引号来分隔该字符串.
插入和检索对象JDBC作为关系数据库的接口,其设计目的是检索和操纵传统的SQL数据类型.
SybaseIQ也以Java类的形式提供了抽象数据类型.
使用JDBC来访问这些Java类的方式取决于您是要插入对象还是要检索对象.
另请参见分布式应用程序(第129页)使用JDBC的查询(第123页)检索对象您可以通过以下方式检索对象、对象字段及对象方法:访问方法和字段-Java方法和字段可以包含在查询的选择列表中.
这样,方法或字段会显示为结果集中的列,通过标准的ResultSet方法(如getInt或getString)就能访问这些列.
检索对象-如果查询选择列表中包括了使用Java类数据类型的列,您可以使用ResultSetgetObject方法将对象检索到Java类中.
然后,在Java类中访问该对象的方法和字段.
Java对象只能存储在Catalog存储中.
使用JDBC访问数据系统管理指南第二卷125插入对象您可从服务器端的Java类使用JDBCsetObject方法将对象插入到数据类型为Java类数据类型的列中.
您可使用预准备语句插入对象.
例如,以下代码段将MyJavaClass类型的对象插入到表T的列中:java.
sql.
PreparedStatementps=conn.
prepareStatement("insertTvalues(ps.
setObject(1,newMyJavaClass());ps.
executeUpdate();另一方法是建立保存对象的SQL变量,然后将该变量插入表中.
SybasejConnectJDBC驱动程序如果希望从客户端应用程序或小程序使用JDBC,必须将SybasejConnect连接到SybaseIQ数据库.
SybaseIQ可能包含或不含SybasejConnect,具体取决于您收到的安装包.
您必须要有jConnect,才能从客户端应用程序使用JDBC.
如果没有jConnect,您可以使用服务器端的JDBC.
有关jConnect及其用于SybaseIQ的完整说明,请参见联机手册或jConnectWeb站点上提供的jConnect文档注意:在应用程序中使用jConnect之前,需要先输入以下语句来装载驱动程序:Class.
forName("com.
sybase.
jdbc.
SybDriver").
newInstance();使用newInstance方法能解决某些浏览器中的问题.
另请参见从服务器端的JDBC类建立连接(第117页)使用jConnect从JDBC客户端应用程序建立连接(第114页)运行外部连接示例(第116页)SybaseIQ随附的jConnect的版本SybaseIQ提供两种版本的SybasejConnectJDBC驱动程序:完整版本-如果选择安装jConnect,则jConnect子目录将添加到您的SybaseIQ安装中.
其中保存了一个有全部jConnect文件的目录树.
zip文件-远程数据访问功能以及Java调试工具都使用jConnect连接数据库.
同时还提供了一个基本jConnect类的zip文件,以使您即便没有完整开发版本的驱动程序,也可使用jConnect.
使用JDBC访问数据126SybaseIQjConnect驱动程序文件SybasejConnect驱动程序安装在SybaseIQ安装目录的jConnect子目录的一组目录中.
如果您没有安装jConnect,则可以使用安装在Java子目录中的jdbcdrv.
zip文件.
jConnect的类路径设置为了让应用程序使用jConnect,jConnect类在编译时和运行时必须位于CLASSPATH环境变量中,这样,Java编译器和Java运行时才能找到必要的文件.
例如,以下命令将jConnect驱动程序类路径添加到现有的CLASSPATH环境变量中,其中path是SybaseIQ安装目录.
setclasspath=%classpath%;path\jConnect\classes以下替代命令将jdbcdrv.
zip文件添加到CLASSPATH.
setclasspath=%classpath%;path\java\jdbcdrv.
zip导入jConnect类jConnect中的所有类都在com.
sybase包中.
客户端应用程序需要访问com.
sybase.
jdbc中的类.
为了应用程序可以使用jConnect,您必须在每个源文件的开头导入这些类:importcom.
sybase.
jdbc.
*另请参见JDBC概述(第109页)在数据库中安装jConnect系统对象如果要用jConnect访问系统表信息(数据库元数据),必须将jConnect系统对象添加到数据库中.
缺省情况下,jConnect系统对象将添加到使用版本12.
7创建的任何数据库,以及添加到升级到版本12.
7的任何数据库.
您可以选择在创建或升级数据库时将jConnect对象添加到数据库,也可以选择稍后再添加.
您可以从InteractiveSQL安装jConnect系统对象.
从SybaseCentral将jConnect系统对象添加到版本12.
7数据库:1.
以具有DBA权限的用户身份从SybaseCentral连接到数据库.
2.
在SybaseCentral主查看器的左窗格中,右键单击数据库图标,然后从弹出菜单中选择"重新安装jConnect元数据支持".
使用JDBC访问数据系统管理指南第二卷127从InteractiveSQL将jConnect系统对象添加到版本12.
7数据库以具有DBA授权的用户身份从InteractiveSQL连接到数据库,然后在"SQL语句"窗格中输入以下命令:readpath\scripts\jcatalog.
sql其中path是SybaseIQ安装目录.
注意:您也可使用命令提示符向版本12.
7数据库添加jConnect系统对象.
在命令提示符下键入:dbisql-c"uid=user;pwd=pwd"path\scripts\jcatalog.
sql其中user和pwd标识具有DBA权限的用户,而path是SybaseIQ安装目录.
提供服务器的URL要通过jConnect连接到数据库,您需要提供数据库的统一资源定位符(URL).
本节中提供了以下示例:StringBuffertemp=newStringBuffer();//UsetheSybasejConnectdriver.
.
.
temp.
append("jdbc:sybase:Tds:");//toconnecttothesuppliedmachinename.
.
.
temp.
append(_coninfo);//onthedefaultportnumberforASA.
.
.
temp.
append(":2638");//andconnect.
System.
out.
println(temp.
toString());conn=DriverManager.
getConnection(temp.
toString(),_props);完整的URL如下:jdbc:sybase:Tds:machine-name:port-number各组成部分包括:jdbc:sybase:Tds-使用TDS应用程序协议的SybasejConnectJDBC驱动程序.
machine-name-运行服务器的计算机的IP地址或名称.
如果要在同一计算机内建立连接,可使用localhost,表示当前计算机.
port-number-数据库服务器监听的端口号.
分配给SybaseIQ的端口号是2638.
如果没有特殊原因,请使用该端口号.
连接字符串长度必须小于253个字符.
指定服务器上的数据库每个SybaseIQ服务器一次可以装载一个或多个数据库.
上面介绍的URL指定服务器,但不会指定数据库.
尝试连接的数据库是服务器上的缺省数据库.
您可以通过下列任一方式提供URL的扩展形式,由此而指定特定数据库.
使用JDBC访问数据128SybaseIQ使用ServiceName参数jdbc:sybase:Tds:machine-name:port-numberServiceName=DBN使用问号,后面跟随一系列赋值,这是向URL提供参数的标准方式.
ServiceName是否大写并不重要,但=号两边不能有空格.
DBN参数是数据库名称.
使用RemotePWD参数另一更常用的方法可用来提供其它连接参数,如数据库名称或数据库文件,这种方法就是使用RemotePWD字段.
您可用setRemotePassword()方法将RemotePWD设置成一个Properties字段.
下面的示例代码说明了如何使用该字段.
sybDrvr=(SybDriver)Class.
forName("com.
sybase.
jdbc2.
jdbc.
SybDriver").
newInstance();props=newProperties();props.
put("User","DBA");props.
put("Password","SQL");sybDrvr.
setRemotePassword(null,"dbf=asiqdemo.
db",props);Connectioncon=DriverManager.
getConnection("jdbc:sybase:Tds:localhost",props);利用数据库文件参数DBF,您可使用jConnect启动服务器上的数据库.
缺省情况下,数据库启动时的设置为autostop=YES.
如果指定utility_db的DBF或DBN,实用程序数据库将自动启动.
有关实用程序数据库的信息,请参见《系统管理指南第一卷》>"SybaseIQ系统管理概述"以及"管理用户ID和权限".
TDS客户端中的特定于IQ的连接参数应该在RemotePWD中指定.
以下示例显示如何指定特定于IQ的连接参数,其中的myconnection为IQ连接名:p.
put("RemotePWD",",,CON=myconnection");其中的myconnection为IQ连接名.
分布式应用程序在分布式应用程序中,部分应用程序逻辑在一台计算机上运行,另外一部分在另一台计算机上运行.
利用SybaseIQ,您可创建分布式Java应用程序,让部分逻辑在数据库服务器中运行,另一部分逻辑在客户端计算机上运行.
SybaseIQ能够与外部Java客户端交换Java对象.
让客户端应用程序从数据库检索Java对象是分布式应用程序中的关键任务.
本节说明如何完成此任务.
使用JDBC访问数据系统管理指南第二卷129分布式应用程序的功能JDBCExamples.
java中还有其它两种使用分布式计算的方法:serializeVariable-此方法创建由数据库服务器上的SQL变量引用的本地Java对象,并将其传递回客户端应用程序.
serializeColumnCastClass-此方法与serializeColumn方法类似,但讲的是如何重新构造子类.
被查询的列(product表的JProd)数据类型为asademo.
Product.
某些行为asademo.
Hat,它是Product类的子类.
相应的类会在客户端得以重新构造.
分布式应用程序的要求建立分布式应用程序涉及到两个任务.
服务器中运行的所有类都必须实现Serializable接口.
这非常简单.
客户端应用程序必须导入类,这样才能在客户端重新构造对象.
以下各节对这些任务逐一进行说明.
另请参见插入和检索对象(第125页)使用JDBC的查询(第123页)Serializable接口对象以序列化的形式从服务器传递到客户端应用程序.
为了让对象传送到客户端应用程序,对象必须实现Serializable接口.
好在该任务非常简单.
Serializable接口不包含任何方法和变量.
序列化对象会将该对象转换为字节流,这样它就可以保存到磁盘或发送到其它Java应用程序,然后可以在磁盘或该Java应用程序中重新构建它或对它进行反序列化.
数据库服务器中的序列化Java对象被发送到客户端应用程序并反序列化后,各方面仍与其原始状态完全相同.
不过,对象中的某些变量要么不需要被序列化,要么由于安全原因而不应被序列化.
应使用关键字transient声明那些变量,如下面的变量声明中所示.
transientStringpassword;带有该变量的对象被反序列化后,总是包含其缺省值NULL.
在类中添加writeObject()和readObject()方法即可完成自定义序列化.
有关序列化的详细信息,请参见SunMicrosystems的JavaDevelopmentKit(JDK).
实现Serializable接口实现Serializable接口就等于直接声明类可以被序列化.
将implementsjava.
io.
Serializable字样添加到类定义中.
使用JDBC访问数据130SybaseIQ例如,位于$SADIR/samples/asa/java/asademo(UNIX)或%SADIR%\samples\asa\java\asademo(Windows)子目录中的Product类借助于以下声明实现Serializable接口:publicclassProductimplementsjava.
io.
Serializable在客户端导入类在客户端,检索对象的任何类都必须具备对相应类定义的访问权限才能使用对象.
如果要使用Product类(它是asademo包的一部分),应用程序中必须包括下面一行:importasademo.
*CLASSPATH中必须包括asademo.
jar文件,这样才能找到此包.
分布式应用程序示例JDBCExamples.
java类包含说明分布式Java计算的三种方法.
这些方法都从main方法调用.
下面是JDBCExamples类中的getObjectColumn方法.
privatestaticvoidgetObjectColumn()throwsException{//Returnaresultsetfromacolumncontaining//Javaobjectsasademo.
ContactInfoci;Stringname;StringsComment;if(conn!
=null){Statementstmt=conn.
createStatement();ResultSetrs=stmt.
executeQuery("SELECTJContactInfoFROMjdba.
contact");while(rs.
next()){ci=(asademo.
ContactInfo)rs.
getObject(1);System.
out.
println("\n\tStreet:"+ci.
street+"City:"+ci.
city+"\n\tState:"+ci.
state+"Phone:"+ci.
phone+"\n");}}}getObject方法的使用方式与在内部Java中的使用方式相同.
另请参见使用jConnect从JDBC客户端应用程序建立连接(第114页)使用JDBC访问数据系统管理指南第二卷131使用JDBC访问数据132SybaseIQ调试数据库中的逻辑本附录介绍了如何使用Sybase调试工具协助开发SQL存储过程和事件处理程序以及Java存储过程.
调试数据库简介您可以在开发期间使用调试工具.
您可以使用以下对象:SQL存储过程、事件处理程序和用户定义的函数.
数据库中的Java存储过程.
调试工具的功能可以在开发SQL存储过程、触发器、事件处理程序和用户定义的函数期间使用调试工具.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"调试过程、函数、触发器和事件">"SQLAnywhere调试工具简介".
使用调试工具的要求要使用调试工具,您需要:权限-您必须具有DBA权限或在SA_DEBUG组中已被授予权限.
创建所有数据库时,都会将该组自动添加到数据库中.
Java类的源代码-必须为调试工具提供应用程序的源代码.
对于Java类,源代码保存在硬盘上的目录中.
对于存储过程,源代码保存在数据库中.
编译选项-要调试Java类,编译这些类时必须使其包含调试信息.
例如,如果使用SunMicrosystemsJDK编译器javac.
exe,就必须使用-g命令行选项对Java类进行编译.
注意:SybaseIQ演示数据库是iqdemo.
db.
教程1:调试工具快速入门这些教程说明如何启动调试工具、连接到数据库,以及如何调试Java类.
调试数据库中的逻辑系统管理指南第二卷133第1课:连接到数据库并启动调试工具本教程讲解如何启动调试工具、连接到数据库及使用连接以进行调试.
它使用的是SybaseIQ演示数据库.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"调试过程、函数、触发器和事件">"教程:调试工具快速入门">"第1课:连接到数据库并启动调试工具".
教程2:调试存储过程本教程通过一个示例会话讲解如何调试存储过程.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"调试过程、函数、触发器和事件">"教程:调试工具快速入门">"第2课:调试存储过程".
教程3:调试Java类在本教程中,您将从InteractiveSQL(dbisql)中调用JDBCExamples.
Query(),在调试工具中中断执行,然后跟踪执行此方法的源代码.
JDBCExamples.
Query()方法对演示数据库执行以下查询:SELECTID,UnitPriceFROMProducts然后循环检查结果集中的所有行,并返回单价最高的那一行.
您必须使用javac-g选项编译类才能对其进行调试.
示例类已按调试要求进行编译.
注意:要使用Java示例,必须在演示数据库中安装Java示例类.
演示数据库Java示例类如果要运行Java示例,则需要在演示数据库中安装Java示例类.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-编程">"SQLAnywhere数据访问API">"SQLAnywhereJDBC驱动程序">"使用JDBC访问数据">"准备示例".
调试数据库中的逻辑134SybaseIQ在调试工具中显示Java源代码调试工具在一组位置中查找扩展名为.
java的源代码文件.
"Java源代码路径"(JavaSourceCodePath)窗口包含调试工具在其中查找Java源代码的目录列表.
将应用查找软件包的Java规则.
调试工具也搜索源代码的当前CLASSPATH.
1.
在左侧文件夹视图中选择SybaseIQ15.
2.
在SybaseCentral中,选择"模式">"调试".
3.
当系统提示选择要调试的用户时,指定*以表示所有用户,然后单击"确定".
4.
从调试工具界面,选择"调试">"设置Java源代码路径".
5.
输入SybaseIQ安装目录的java子目录的路径.
例如,如果您将SybaseIQ安装在%IQDIR15%中,请输入:%IQDIR15%\java6.
单击"浏览文件夹"(BrowseFolder)从调试程序在其中查找Java源代码的文件夹或各个文件的列表中进行选择.
7.
单击"浏览文件"(BrowseFile)来定位要添加到列表中的文件.
8.
单击"确定",然后关闭该窗口.
设置断点可以在Query()方法的开头设置断点.
调用该方法时,将在断点处停止执行.
1.
在"源代码"窗口中,向下滚动,直到在类的结尾附近看到Query()方法的开始部分,其开头为:publicstaticintQuery(){2.
单击该方法第一行左侧的绿色指示符,直至其变为红色.
该方法的第一行为:intmax_price=0;重复单击该指示符将切换其状态.
设置断点后,Java类不需要重新编译.
运行方法您可以从InteractiveSQL(dbisql)调用Query()方法,并看到其执行在断点处中断.
1.
启动InteractiveSQL.
使用IDDBA和口令sql连接到演示数据库.
连接将出现在调试工具的"连接"窗口列表中.
2.
要调用方法,请在InteractiveSQL中输入以下命令:SELECTJDBCExamples.
Query()调试数据库中的逻辑系统管理指南第二卷135该查询不会完成.
在调试工具中该查询将在执行到断点处停止.
在InteractiveSQL中,"停止"按钮处于活动状态.
在调试工具的"源"窗口中,红色箭头指示当前行.
现在可以在调试工具中单步执行源代码并完成调试活动.
单步执行源代码上一节结束后,调试工具应在JDBCExamples.
Query()方法的第一条语句处停止执行该方法:1.
选择"调试">"单步执行跳过过程",或按F10单步执行到当前方法中的下一行.
请尝试执行两三次.
2.
使用鼠标单击以下行的结尾,然后选择"调试">"运行至游标",或按CTRL+F10以运行到该行并中断:3.
选择以下行(第292行)并按F9在该行设置断点:returnmax_price;左侧列中将出现一个星号以标记该断点.
按F5可执行到该断点.
4.
尝试使用不同的方法单步执行代码.
按F5完成执行.
完成执行后,InteractiveSQL数据窗口将显示值24.
5.
要移动到下一个断点,请添加F5.
完成执行后,InteractiveSQL数据窗口将显示值24.
"Run"菜单上显示了用于单步执行源代码的完整选项集.
有关详细信息,可查看调试工具的联机帮助.
检查和修改变量可以在调试工具中检查局部变量(在方法中声明)和类静态变量的值.
还可以在调试工具的"调试程序"(Debugger)窗口中显示类级变量(静态变量),并检查它们的值.
有关详细信息,请参见调试工具的联机帮助.
在单步执行代码时,可以检查方法中局部变量的值,以更好地了解执行情况.
注意:要使用Java示例,必须在演示数据库中安装Java示例类.
1.
在JDBCExamples.
Query方法的第一行设置断点.
该行如下所示:intmax_price=02.
在InteractiveSQL中,再次执行该方法:SELECTJDBCExamples.
Query()查询只执行到断点处.
3.
按F7以进入下一行.
现在已声明了max_price变量,并已将其初始化为零.
调试数据库中的逻辑136SybaseIQ4.
如果未显示"局部"窗口,请选择"窗口">"局部"来显示它.
"局部"窗口显示存在一些局部变量.
max_price的值为零.
所有其它变量列出为variablenotinscope(不在范围中的变量),这表示它们还未初始化.
5.
在"局部"窗口中,双击max_price的"值"列条目,然后将max_price的值更改为45.
值45高于其它任何价格.
现在,该查询返回的最高价格不再是24,而是45.
6.
在"源"(Source)窗口中,反复按F7以逐步调试代码.
变量的值出现在"局部"(Locals)窗口中.
单步执行,直到stmt和result变量具有值.
7.
单击result对象旁边的图标,将其展开,或者将游标放在该行上,然后按Enter.
这将显示该对象中的字段的值.
8.
在体验过检查和修改变量后,按F5完成该查询的执行并结束本教程.
断点断点控制何时调试工具中断源代码的执行.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"调试过程、函数、触发器和事件">"使用断点".
查看和编辑变量行为使用调试工具可以在单步执行代码时查看和编辑变量的行为.
调试工具提供了"调试工具详细信息"窗格,该窗格显示存储过程使用的各种不同变量.
当SybaseCentral在调试模式下运行时,"调试工具详细信息"窗格显示在SybaseCentral底部.
请参见《SQLAnywhere11.
0.
1》>"SQLAnywhereServer-SQL用法">"存储过程和触发器">"调试过程、函数、触发器和事件">"使用变量".
编写调试工具脚本调试工具允许您以Java编程语言编写脚本.
脚本为扩展sybase.
asa.
procdebug.
DebugScript类的Java类.
调试工具运行脚本时,将装载该类并调用其run方法.
run方法的第一个参数为指向类实例的指针.
通过此接口可以与调试工具交互并对其进行控制.
可以使用如下命令编译脚本:javac-classpath%asany%/procdebug/ProcDebug.
jar;%classpath%myScript.
Java.
调试数据库中的逻辑系统管理指南第二卷137sybase.
asa.
procdebug.
DebugScript类DebugScript类如下所示://Alldebugscriptsmustinheritfromthisclasspackagesybase.
asa.
procdebug;abstractpublicclassDebugScript{abstractpublicvoidrun(IDebugAPIdb,Stringargs[]);/*Therunmethodiscalledbythedebugger-argswillcontaincommandlinearguments*/publicvoidOnEvent(intevent)throwsDebugError{}/*-Overridethefollowingmethodstoprocessdebugevents-NOTE:thismethodwillnotbecalledunlessyoucallDebugAPI.
AddEventHandler(this);*/}sybase.
asa.
procdebug.
IDebugAPI接口IDebugAPI接口如下所示:packagesybase.
asa.
procdebug;importjava.
util.
*;publicinterfaceIDebugAPI{//SimulateMenuItemsIDebugWindowMenuOpenSourceWindow()throwsDebugError;IDebugWindowMenuOpenCallsWindow()throwsDebugError;IDebugWindowMenuOpenClassesWindow()throwsDebugError;IDebugWindowMenuOpenClassListWindow()throwsDebugError;IDebugWindowMenuOpenMethodsWindow()throwsDebugError;IDebugWindowMenuOpenStaticsWindow()throwsDebugError;IDebugWindowMenuOpenCatchWindow()throwsDebugError;IDebugWindowMenuOpenProcWindow()throwsDebugError;IDebugWindowMenuOpenOutputWindow()throwsDebugError;IDebugWindowMenuOpenBreakWindow()throwsDebugError;IDebugWindowMenuOpenLocalsWindow()throwsDebugError;IDebugWindowMenuOpenInspectWindow()throwsDebugError;IDebugWindowMenuOpenRowVarWindow()throwsDebugError;IDebugWindowMenuOpenQueryWindow()throwsDebugError;IDebugWindowMenuOpenEvaluateWindow()throwsDebugError;IDebugWindowMenuOpenGlobalsWindow()throwsDebugError;IDebugWindowMenuOpenConnectionWindow()throwsDebugError;IDebugWindowMenuOpenThreadsWindow()throwsDebugError;IDebugWindowGetWindow(Stringname)throwsDebugError;调试数据库中的逻辑138SybaseIQvoidMenuRunRestart()throwsDebugError;voidMenuRunHome()throwsDebugError;voidMenuRunGo()throwsDebugError;voidMenuRunToCursor()throwsDebugError;voidMenuRunInterrupt()throwsDebugError;voidMenuRunOver()throwsDebugError;voidMenuRunInto()throwsDebugError;voidMenuRunIntoSpecial()throwsDebugError;voidMenuRunOut()throwsDebugError;voidMenuStackUp()throwsDebugError;voidMenuStackDown()throwsDebugError;voidMenuStackBottom()throwsDebugError;voidMenuFileExit()throwsDebugError;voidMenuFileOpen(Stringname)throwsDebugError;voidMenuFileAddSourcePath(Stringwhat)throwsDebugError;voidMenuSettingsLoadState(Stringfile)throwsDebugError;voidMenuSettingsSaveState(Stringfile)throwsDebugError;voidMenuWindowTile()throwsDebugError;voidMenuWindowCascade()throwsDebugError;voidMenuWindowRefresh()throwsDebugError;voidMenuHelpWindow()throwsDebugError;voidMenuHelpContents()throwsDebugError;voidMenuHelpIndex()throwsDebugError;voidMenuHelpAbout()throwsDebugError;voidMenuBreakAtCursor()throwsDebugError;voidMenuBreakClearAll()throwsDebugError;voidMenuBreakEnableAll()throwsDebugError;voidMenuBreakDisableAll()throwsDebugError;voidMenuSearchFind(IDebugWindoww,Stringwhat)throwsDebugError;voidMenuSearchNext(IDebugWindoww)throwsDebugError;voidMenuSearchPrev(IDebugWindoww)throwsDebugError;voidMenuConnectionLogin()throwsDebugError;voidMenuConnectionReleaseSelected()throwsDebugError;//outputwindowvoidOutputClear();voidOutputLine(Stringline);voidOutputLineNoUpdate(Stringline);voidOutputUpdate();//JavasourcesearchpathvoidSetSourcePath(Stringpath)throwsDebugError;StringGetSourcePath()throwsDebugError;//CatchjavaexceptionsVectorGetCatching();voidCatch(booleanon,Stringname)throwsDebugError;//DatabaseconnectionsintConnectionCount();voidConnectionRelease(intindex);voidConnectionAttach(intindex);StringConnectionName(intindex);调试数据库中的逻辑系统管理指南第二卷139voidConnectionSelect(intindex);//LogintodatabasebooleanLoggedIn();voidLogin(Stringurl,StringuserId,Stringpassword,StringuserToDebug)throwsDebugError;voidLogout();//Simulatekeyboard/mouseactionsvoidDeleteItemAt(IDebugWindoww,introw)throwsDebugError;voidDoubleClickOn(IDebugWindoww,introw)throwsDebugError;//BreakpointsObjectBreakSet(Stringwhere)throwsDebugError;voidBreakClear(Objectb)throwsDebugError;voidBreakEnable(Objectb,booleanenabled)throwsDebugError;voidBreakSetCount(Objectb,intcount)throwsDebugError;intBreakGetCount(Objectb)throwsDebugError;voidBreakSetCondition(Objectb,Stringcondition)throwsDebugError;StringBreakGetCondition(Objectb)throwsDebugError;VectorGetBreaks()throwsDebugError;//ScriptingvoidRunScript(Stringargs[])throwsDebugError;voidAddEventHandler(DebugScripts);voidRemoveEventHandler(DebugScripts);//MiscellaneousvoidEvalRun(Stringexpr)throwsDebugError;voidQueryRun(Stringquery)throwsDebugError;voidQueryMoreRows()throwsDebugError;VectorGetClassNames();VectorGetProcedureNames();VectorWindowContents(IDebugWindowwindow)throwsDebugError;booleanAtBreak();booleanIsRunning();booleanAtStackTop();booleanAtStackBottom();voidSetStatusText(Stringmsg);StringGetStatusText();voidWaitCursor();voidOldCursor();voidError(Exceptionx);voidError(Stringmsg);voidWarning(Stringmsg);StringAsk(Stringtitle);booleanMenuIsChecked(Stringcmd);voidMenuSetChecked(Stringcmd,booleanon);voidAddInspectItem(Strings)throwsDebugError;//ConstantsforDebugScript.
OnEventparameterpublicstaticfinalintEventBreak=0;publicstaticfinalintEventTerminate=1;publicstaticfinalintEventStep=2;publicstaticfinalintEventInterrupt=3;调试数据库中的逻辑140SybaseIQpublicstaticfinalintEventException=4;publicstaticfinalintEventConnect=5;};sybase.
asa.
procdebug.
IDebugWindow接口IDebugWindow接口如下所示://thisinterfacerepresentsadebuggerwindowpackagesybase.
asa.
procdebug;publicinterfaceIDebugWindow{publicintGetSelected();/*getthecurrentlyselectedrow,or-1ifnoselection*/publicbooleanSetSelected(inti);/*setthecurrentlyselectedrow.
Ignoredifi#rows*/publicStringStringAt(introw);/*gettheStringrepresentationoftheNthrowofthewindow.
Returnsnullifrow>#rows*/publicjava.
awt.
RectangleGetPosition();publicvoidSetPosition(java.
awt.
Rectangler);/*get/setthewindowspositionwithintheframe*/publicvoidClose();/*Close(destroy)thewindow*/}调试数据库中的逻辑系统管理指南第二卷141调试数据库中的逻辑142SybaseIQ索引符号"ProcedureNotFound"错误Java方法122AAdaptiveServerEnterprise15.
596AdaptiveServerEnterprise服务器85,86ALLOW_NULLS_BY_DEFAULT选项OpenClient80asajdbc服务器类95asaodbc服务器类97asejdbc服务器类96ASEJDBC类85aseodbc服务器类98AT子句CREATEEXISTINGTABLE语句89安全隐藏对象15BBEGINTRANSACTION语句远程数据访问91包jConnect127保存点过程14保留字远程服务器93报告函数47示例48标准偏差函数49样本函数50总体函数49表代理89定义代理89,90列出远程87远程访问83表名本地89CCALL语句参数10关于3示例5语法8CASE语句语法8CHAINED选项OpenClient80CIS(组件集成服务)75CLASSPATH环境变量jConnect127设置116Client-Library关于75CLOSE语句过程12COMMIT语句JDBC117复合语句9过程14远程数据访问91CONTINUE_AFTER_RAISERROR选项OpenClient80CREATEEXISTINGTABLE错误96CREATEEXISTINGTABLE语句85使用89CREATEPROCEDURE语句参数10示例4CREATETABLE语句代理表90CUBE运算21,22,30SELECT语句30空值24示例32CURRENTROW37,38查询JDBC123前缀21小计行23触发器状态系统事件104触发事件处理程序106窗口排序34,35索引系统管理指南第二卷143运算符33窗口大小RANGE34ROWS34窗口分区34,35GROUPBY运算符35子句35窗口构架34,36基于范围40,41基于行38窗口构架单元36,39,40range40rows39窗口构架的逻辑偏移量40窗口构架的物理偏移量39窗口函数OVER子句34窗口分区34窗口函数类型34窗口名称或规范34分布35分区35构架36集合19,35排名34排序35统计35窗口化分区33函数35集合函数35,47扩展33存储过程调试134显示有关信息3错误过程13错误处理ONEXCEPTIONRESUME13DDB-Library关于75DebugScript类138DECLARE语句复合语句9过程12DirectConnect84,85DirectConnectforOracle85DSEdit启动76使用76条目76代理表85创建83,89,90关于83,89属性89位置89代理数据库75当前行39导入jConnect127调试Java134存储过程134断点135功能133简介133连接133权限133事件处理程序107要求133调试工具功能133关于133教程134快速入门134连接134要求133断点在Java类中设置135对象插入125查询129检索125,129隐藏15多个数据库DSEDIT条目76连接91EEnterpriseConnectDataAccess84,85EXECUTEIMMEDIATE语句过程14executeQuery方法关于123索引144SybaseIQexecuteUpdate方法关于121FFETCH语句过程12FOR语句语法8FORWARDTO语句91范围规范38,40方差函数49分布函数19,35,53分布式应用程序关于129示例131要求130分析函数19服务器多个数据库80服务器地址DSEDIT76服务器类asajdbc95asaodbc97asejdbc96aseodbc98ODBC97定义83关于83复合语句声明9使用9原子9GgetConnection方法实例118GROUPBYCUBE22ROLLUP22子句扩展21GROUPBY子句扩展19,21GROUPING函数ROLLUP运算24空值24故障排除服务器地址77远程数据访问93关键字远程服务器93管理事务92过程EXECUTEIMMEDIATE语句14保存点14参数3,10创建4错误处理13调试134调用5多个结果集12返回结果6,11关于3结构9结果集6,11警告13可变结果集12缺省的错误处理13删除5使用3所有者3显示有关信息3异常处理程序14优点3游标12,13允许的SQL语句10执行权限5H函数PERCENTILE_CONT函数53PERCENTILE_DISC函数53STDDEV_POP函数49STDDEV_SAMP函数50VAR_POP函数50VAR_SAMP函数50报告47标准偏差49窗口20,47窗口化33窗口化集合19,47方差49分布19,53分析19,33集合33索引系统管理指南第二卷145简单集合33逆分布53排名19,43数值19,56统计19统计集合49相关50协方差50用户定义的7有序集合53汇总行ROLLUP运算23IiAnywhereJDBC驱动程序选择JDBC驱动程序110IDebugAPI接口138IDebugWindow141IF语句语法8INSERT语句JDBC121,122对象125,126interfaces文件85,86配置76IP地址关于76iqdsedit使用76ISOLATION_LEVEL选项OpenClient80JJavaJDBC109查询对象129调试133,134关于133关于调试133Java调试工具教程134要求133Java数据类型插入125检索125jcatalog.
sql文件jConnect127jConnectCLASSPATH环境变量127jdbcdrv.
zip127URL128安装126版本126包127关于126口令加密78连接114,117数据库设置127系统对象127选择JDBC驱动程序110jConnect6.
096JDBCINSERT语句121,122jConnect126SELECT语句123版本111非标准类111服务器端113服务器端连接117概述109功能111关于109客户端113客户端连接114连接113连接代码114连接到数据库128连接缺省值118使用方式109示例114数据访问120要求109应用程序概述110预准备语句124自动提交117JDBC驱动程序兼容性110性能110选择110JDBCExamples类关于120基于范围的窗口构架40,41基于范围的构架中的ORDERBY排序顺序42基于行的窗口构架38索引146SybaseIQ基于值的窗口构架40ORDERBY子句41升序和降序41集合函数33STDDEV_POP49,50STDDEV_SAMP50VAR_POP50VAR_SAMP50统计49计算相邻行之间的增量42加密TDS口令78隐藏对象15简单集合函数33降序41脚本IDebugAPI接口138IDebugWindow接口141编写调试工具137接口IDebugAPI138IDebugWindow141结果集多个12过程6,11可变12警告过程13K可滚动游标JDBC支持110空值CUBE运算24ROLLUP运算24示例24空值和小计行24控制语句列表8口令TDS加密78口令加密jConnect78TDS78LLEAVE语句语法8libctl.
cfg文件DSEDIT环境变量76localhost计算机名称76LOOP语句语法8在过程中13类导入131连接jConnect129jConnectURL128JDBC113JDBC客户端114JDBC缺省值118JDBC示例114,117调试133,134服务器中的JDBC117远程91联机分析处理CUBE运算符30ROLLUP运算符22功能19空值24小计行23列信息不可访问96MMSSQL84MSSQLServer85N逆分布函数53OODBC服务器类97外部服务器97OLAP35CUBE运算30GROUPBY子句扩展19Grouping()21ORDERBY子句35PARTITIONBY子句35range40索引系统管理指南第二卷147RANGE34ROLLUP运算符22rows39ROWS34窗口大小34窗口分区34,35窗口概念34窗口构架34窗口函数20窗口化扩展33窗口集合函数19窗口排序34当前行39分布函数19,35分析函数19,33功能19关于19集合函数33空值24排名函数19,34使用20数值函数19统计函数35统计集合函数19小计行23优点20语义执行阶段20OLAP函数窗口化33窗口化:集合函数47分布53排名函数43数值函数56统计集合49行间函数52有序集合53OLAP示例59ORDERBY结果62RANGE的缺省窗口构架66ROW的缺省窗口构架64unboundedprecedingandunboundedfollowing65不包括当前行的窗口构架64查询中的窗口函数59查询中的多个集合函数62窗口函数43含ROWS与RANGE的窗口构架63基于范围的窗口构架40基于行的窗口构架38基于值的构架的升序和降序41计算累计总和61计算相邻行之间的增量42计算移动平均值61使用含多个函数的窗口60未受限制的窗口42OmniConnect75支持77ONEXCEPTIONRESUME子句关于13OpenClient接口75口令加密78配置75OpenServer地址76启动79体系结构75添加75系统要求79OPEN语句过程12ORDERBY子句35,36排序顺序42OVER子句34PPARTITIONBY子句35PERCENTILE_CONT函数53PERCENTILE_DISC函数53ping测试OpenClient77PREPARE语句远程数据访问91PreparedStatement接口关于124排名函数19,34OLAP的要求36windoworder子句36批处理关于3,8允许的SQL语句15QQUOTED_IDENTIFIER选项OpenClient80索引148SybaseIQ启动数据库jConnect129前缀21ROLLUP运算23小计行23区分大小写远程访问94驱动程序缺少93权限调试133过程5用户定义的函数7Rrange40windoworder子句36窗口构架单元36窗口构架的逻辑偏移量40RANGE34rank函数示例46,47REMOTEPWD使用129ReplicationServer支持77RETURN语句关于11ROLLBACK语句复合语句9过程14ROLLUP运算21,22SELECT语句22空值24示例28小计行23ROLLUP运算符22rows39rowsbetween1precedingand1following40rowsbetween1precedingand1preceding40rowsbetweencurrentrowandcurrentrow40rowsbetweenunboundedprecedingandcurrentrow40rowsbetweenunboundedprecedingandunboundedfollowing40窗口构架的物理偏移量39ROWS34日程表定义组件103SSA_DEBUG组调试工具133SELECT语句JDBC123对象125setAutocommit方法关于117setObject方法使用131sp_iqprocedure有关过程的信息3sp_iqprocparm过程参数3SQLRemote远程数据访问93sql.
ini文件配置76SQLCODE变量简介13SQLSTATE变量简介13STDDEV_POP函数49STDDEV_SAMP函数50SYBASE环境变量DSEDIT76sysservers系统表远程服务器84升序41使用调试工具的要求133使用未受限制的窗口42示例OLAP59事件触发器状态104检索日程表名称107检索事件名称107系统104事件处理程序105触发106调试107事务管理92过程14远程数据访问91事务管理91索引系统管理指南第二卷149数据库URL128代理75多个91服务器上的多个80数据库选项OpenClient80数据源外部服务器97数值函数19TTabularDataStream(TDS)关于75TCP/IPOpenServer79地址76TDS口令加密78另请参见TabularDataStream(TDS)TSQL_HEX_CONSTANT选项OpenClient80TSQL_VARIABLES选项OpenClient80统计函数35集合19统计集合函数49UUNBOUNDEDFOLLOWING37,38UNBOUNDEDPRECEDING37UNBOUNDEDPREDEDING38URLjConnect128URL数据库JDBC128VVAR_POP函数50VAR_SAMP函数50WWHILE语句语法8windowframe子句36order子句35,36外部登录名创建88关于88删除88未受限制的窗口,使用42X系统事件触发器状态104限制远程数据访问93相邻行之间的增量,计算42小计行23ROLLUP运算23定义22,30构造23空值24行规范40小计行23行规范38性能JDBC124JDBC驱动程序110序列化对象130分布式计算131选项OpenClient80Y样本方差函数50异常处理程序过程14用户定义的函数参数11创建7调用7删除7使用7执行权限7游标过程12和LOOP语句13索引150SybaseIQ在SELECT语句上13在过程中13有序集合函数53PERCENTILE_CONT53PERCENTILE_DISC53语义执行阶段20预准备语句JDBC124原子复合语句9远程表关于83列出87列出列90远程服务器创建84更改87关于83类95列出属性88删除87事务管理91外部登录名88远程过程调用关于91远程数据非Sybase84位置89远程数据访问75不支持SQLRemote93不支持的功能93故障排除93内部操作92区分大小写94远程服务器83直通模式91Z摘要信息CUBE运算符30执行阶段20子事务过程14自动提交模式JDBC117总体方差函数50组件集成服务85索引系统管理指南第二卷151索引152SybaseIQ

ZJI-全场八折优惠,香港服务器 600元起,还有日本/美国/韩国服务器

ZJI怎么样?ZJI是一家成立于2011年的商家,原名维翔主机,主要从事独立服务器产品销售,目前主打中国香港、日本、美国独立服务器产品,是一个稳定、靠谱的老牌商家。详情如下:月付/年付优惠码:zji??下物理服务器/VDS/虚拟主机空间订单八折终身优惠(长期有效)一、ZJI官网点击直达香港葵湾特惠B型 CPU:E5-2650L核心:6核12线程内存:16GB硬盘:480GB SSD带宽:5Mbps...

ProfitServer折优惠西班牙vps,荷兰vps,德国vps,5折优惠,不限制流量

profitserver正在对德国vps(法兰克福)、西班牙vps(马德里)、荷兰vps(杜廷赫姆)这3处数据中心内的VPS进行5折优惠促销。所有VPS基于KVM虚拟,纯SSD阵列,自带一个IPv4,不限制流量,在后台支持自定义ISO文件,方便大家折腾!此外还有以下数据中心:俄罗斯(多机房)、捷克、保加利亚、立陶宛、新加坡、美国(洛杉矶、锡考克斯、迈阿密)、瑞士、波兰、乌克兰,VPS和前面的一样性...

Hostodo:$19.99/年KVM-1GB/12GB/4TB/拉斯维加斯

Hostodo发布了几款采用NVMe磁盘的促销套餐,从512MB内存起,最低年付14.99美元,基于KVM架构,开设在拉斯维加斯机房。这是一家成立于2014年的国外VPS主机商,主打低价VPS套餐且年付为主,基于OpenVZ和KVM架构,产品性能一般,数据中心目前在拉斯维加斯和迈阿密,支持使用PayPal或者支付宝等付款方式。下面列出几款NVMe硬盘套餐配置信息。CPU:1core内存:512MB...

无法定位程序输入点于动态链接库为你推荐
手游运营手册游戏策划新手应该看那些书籍?怎么在qq空间里添加背景音乐如何在qq空间中添加背景音乐自助建站自助建站哪个平台最好?安卓应用平台有没有什么安卓游戏都能找到的应用商店或者游戏中心申请证书申请毕业证书办公协同软件协同企业办公的软件有哪些?中小企业信息化什么是企业信息化,应该这样实施开机滚动条开机滚动条要很长时间怎么解决?商标注册查询官网怎么查商标是否注册成功小米手柄手机用小米手柄能玩什么游戏
老左 企业主机 阿里云邮箱登陆首页 pw域名 流媒体服务器 免费ftp空间 名片模板psd godaddy优惠券 服务器日志分析 一元域名 申请个人网页 193邮箱 双线主机 亚马逊香港官网 umax120 爱奇艺会员免费试用 流媒体加速 raid10 lick qq金券 更多