远程Sybase数据库技术支持,联系手机:13811580958,QQ:289965371!

 

随着Sybase被完全整合到SAP下,Sybase原来的支持网站被SAP Support Portal取代。
只有购买了SAP服务的用户才能使用账号登录SAP Support Portal进行介质下载、补丁升级、报Incident等。
目前,原Sybase所有产品(包括:Adaptive Server Enterprise、Sybase IQ、Replication Server、PowerDesigner等)的官方手册仍然可以从http://infocenter.sybase.com/help/index.jsp进行浏览或下载。暂不清楚该网站http://infocenter.sybase.com/help/index.jsp何时会被完全迁移到SAP Support上!
Sybase官方手册英文版有html和pdf两种格式,而中文版手册只有pdf一种格式。为了国内Sybase用户更方便、快捷地搜索Sybase常见产品的官方手册内容,特将中文版Sybase官方手册转为html格式!
Sybase产品官方手册中文版的html格式所有内容的版权归SAP公司所有!本博客站长是Sybase数据库的铁杆粉丝!

如有Sybase数据库技术问题需要咨询,请联系我!

  QQ :289965371 点击这里给我发消息
  Email:

以下官方手册为SAP IQ 16.0 SP03中文版:

  1. SAP Sybase IQ 简介
  2. 新功能摘要
  3. IQ 发行公告(linux)
  4. IQ 快速入门(unix)
  5. 安装和配置指南(linux)
  6. 管理:备份、恢复和数据恢复
  7. 管理:数据库
  8. SAP Sybase IQ 错误消息
  9. 管理:全球化
  10. IQ 许可选项指南
  11. 管理:装载管理
  12. IQ 迁移
  13. 管理:Multiplex
  14. 性能和调优指南
  15. IQ 编程
  16. 参考:构件块、表和过程
  17. 参考:语句和选项
  18. 管理:内存行级版本控制
  19. 管理:空间数据
  20. IQ 非结构化数据分析
  21. 用户定义的函数
  22. 管理:用户管理和安全
  23. 实用程序指南

 


< 上一个 | 内容 | 下一步 >

ESQL ODBC 外部环境

要在外部环境而非数据库服务器中运行编译过的本地 C 函数,要用 EXTERNAL NAME 子句并在其后使用 LANGUAGE 属性定义存储过程或函数,从而指定 C_ESQL32C_ESQL64C_ODBC32 C_ODBC64 之一。


PerlPHP Java 外部环境不同的是,不需要在数据库中安装任何源代码或编译 过的对象。因此,使用 ESQL ODBC 外部环境前,无需执行任何 INSTALL 语句。


下面是一个可以在数据库服务器或外部环境中运行、以 C++ 编写的函数的示例。

image

#include <windows.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include "extfnapi.h"


BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call,

LPVOID lpReserved

)

{

return TRUE;

}


// Note: extfn_use_new_api used only for


image

// execution in the database server


extern "C"


declspec( dllexport )

a_sql_uint32 extfn_use_new_api( void )

{

return( EXTFN_API_VERSION );

}


extern "C"


declspec( dllexport )

void SimpleCFunction( an_extfn_api *api, void *arg_handle )

{

short result;

an_extfn_value arg;

an_extfn_value retval;

int * intptr;

int i, j, k;


j = 1000;

k = 0;

for( i = 1; i <= 4; i++ )

{

result = api->get_value( arg_handle, i, &arg ); if( result == 0 || arg.data == NULL ) break;

if( arg.type & DT_TYPES != DT_INT ) break; intptr = (int *) arg.data;

k += *intptr * j; j = j / 10;

}

retval.type = DT_INT; retval.data = (void*)&k;

retval.piece_len = retval.len.total_len = (a_sql_uint32) sizeof( int );

api->set_value( arg_handle, 0, &retval, 0 ); return;

}

此函数在编译到动态链接库或共享对象中后,即可从外部环境调用。数据库服务器会 启动名为 dbexternc12 的可执行文件映像,用以为您装载该动态链接库或共享对象。

请注意,32 位或 64 位版本的数据库服务器都可以使用,任何一个版本都可以启动 32 位或 64 位版本的 dbexternc12。这是使用外部环境的优点之一。请注意,dbexternc12 一旦由数据库服务器启动就会一直运行,直到连接终止或执行了 STOP EXTERNAL ENVIRONMENT 语句(包含正确的环境名)为止。每个用于执行外部环境调用的连 接都将获得一个专用 dbexternc12 副本。

要调用编译过的本地函数 SimpleCFunction,应按如下方式定义包装:

image

CREATE FUNCTION SimpleCDemo( IN arg1 INT,

IN arg2 INT, IN arg3 INT, IN arg4 INT )

RETURNS INT


image

EXTERNAL NAME 'SimpleCFunction@c:\\c\\extdemo.dll' LANGUAGE C_ODBC32;

这与在将编译后本地函数加载到数据库服务器地址空间时该函数的描述方式几乎完全 相同。唯一的区别是使用了 LANGUAGE C_ODBC32 子句。该子句说明 SimpleCDemo 是一个在外部环境中运行的函数,它使用 32 ODBC 调用。C_ESQL32C_ESQL64C_ODBC32 C_ODBC64 的语言规范可向数据库服务器表明:发出服 务器端请求时,外部 C 函数是发出 32 位还是 64 位调用,以及这些调用是 ODBCESQL 调用还是 a_v4_extfn API 调用。

如果本地函数不使用 ODBCESQL SQL Anywhere C API 调用中的任何一个执行 服务器端请求,则 C_ODBC32 C_ESQL32 可用于 32 位应用程序,C_ODBC64 C_ESQL64 可用于 64 位应用程序。这是以上所示的外部 C 函数中的情况。它未使用这些 API 中的任何一个。

要执行该编译后本地函数示例,请执行以下语句。

image

SELECT SimpleCDemo(1,2,3,4);

要使用服务器端 ODBCC/C++ 代码必须使用缺省数据库连接。要获取数据库连接的 句柄,请用 EXTFN_CONNECTION_HANDLE_ARG_NUM 参数调用 get_value。该参 数会告知数据库服务器返回当前外部环境连接,而不是打开一个新连接。

image

#include <windows.h>

#include <stdio.h>

#include "odbc.h"

#include "extfnapi.h"


BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call,

LPVOID lpReserved

)

{

return TRUE;

}


extern "C"


declspec( dllexport )

void ServerSideFunction( an_extfn_api *api, void *arg_handle )

{

short result;

an_extfn_value arg;

an_extfn_value retval;

SQLRETURN ret;


ret = -1;

// set up the return value struct retval.type = DT_INT;

retval.data = (void*) &ret; retval.piece_len = retval.len.total_len =

(a_sql_uint32) sizeof( int );


result = api->get_value( arg_handle,

EXTFN_CONNECTION_HANDLE_ARG_NUM,

&arg );


image

if( result == 0 || arg.data == NULL )

{

api->set_value( arg_handle, 0, &retval, 0 ); return;

}


HDBC dbc = (HDBC)arg.data; HSTMT stmt = SQL_NULL_HSTMT;

ret = SQLAllocHandle( SQL_HANDLE_STMT, dbc, &stmt ); if( ret != SQL_SUCCESS ) return;

ret = SQLExecDirect( stmt,

(SQLCHAR *) "INSERT INTO odbcTab "

"SELECT table_id, table_name " "FROM SYS.SYSTAB", SQL_NTS );

if( ret == SQL_SUCCESS )

{

SQLExecDirect( stmt,

(SQLCHAR *) "COMMIT", SQL_NTS );

}

SQLFreeHandle( SQL_HANDLE_STMT, stmt );


api->set_value( arg_handle, 0, &retval, 0 ); return;

}

如果以上 ODBC 代码存储在文件 extodbc.cpp 中,则可用以下命令为 Windows 生成该 文件。

image

cl extodbc.cpp /LD /Ic:\sa12\sdk\include odbc32.lib

下面的示例将创建一个表,定义用来调用编译后本地函数的存储过程包装,然后调用 该本地函数来填充该表。

image

CREATE TABLE odbcTab(c1 int, c2 char(128));


CREATE FUNCTION ServerSideODBC( ) RETURNS INT

EXTERNAL NAME 'ServerSideFunction@extodbc.dll' LANGUAGE C_ODBC32;


SELECT ServerSideODBC();


// The following statement should return two identical rows SELECT COUNT(*) FROM odbcTab

UNION ALL

SELECT COUNT(*) FROM SYS.SYSTAB;

同样,要使用服务器端 ESQLC/C++ 代码也必须使用缺省数据库连接。要获取数据 库连接的句柄,请用 EXTFN_CONNECTION_HANDLE_ARG_NUM 参数调用 get_value。该参数会告知数据库服务器返回当前外部环境连接,而不是打开一个新连 接。

image

#include <windows.h>

#include <stdio.h>


#include "sqlca.h"

image


#include "sqlda.h"

#include "extfnapi.h"


BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call,

LPVOID lpReserved

)

{

return TRUE;

}


EXEC SQL INCLUDE SQLCA;

static SQLCA *_sqlc;

EXEC SQL SET SQLCA "_sqlc";

EXEC SQL WHENEVER SQLERROR { ret = _sqlc->sqlcode; };


extern "C"


declspec( dllexport )

void ServerSideFunction( an_extfn_api *api, void *arg_handle )

{

short result;

an_extfn_value arg;

an_extfn_value retval;


EXEC SQL BEGIN DECLARE SECTION;

char *stmt_text =

"INSERT INTO esqlTab "

"SELECT table_id, table_name " "FROM SYS.SYSTAB";

char *stmt_commit = "COMMIT";

EXEC SQL END DECLARE SECTION;


int ret = -1;


// set up the return value struct retval.type = DT_INT;

retval.data = (void*) &ret; retval.piece_len = retval.len.total_len =

(a_sql_uint32) sizeof( int );


result = api->get_value( arg_handle,

EXTFN_CONNECTION_HANDLE_ARG_NUM,

&arg );

if( result == 0 || arg.data == NULL )

{

api->set_value( arg_handle, 0, &retval, 0 ); return;

}

ret = 0;

_sqlc = (SQLCA *)arg.data;


EXEC SQL EXECUTE IMMEDIATE :stmt_text;

EXEC SQL EXECUTE IMMEDIATE :stmt_commit;


api->set_value( arg_handle, 0, &retval, 0 );

}


如果以上嵌入式 SQL 语句存储在文件 extesql.sqc 中,则可用以下命令为 Windows 生 成该文件。

image

sqlpp extesql.sqc extesql.cpp

cl extesql.cpp /LD /Ic:\sa12\sdk\include c:\sa12\sdk\lib

\x86\dblibtm.lib

下面的示例将创建一个表,定义用来调用编译后本地函数的存储过程包装,然后调用 该本地函数来填充该表。

image

CREATE TABLE esqlTab(c1 int, c2 char(128));


CREATE FUNCTION ServerSideESQL( ) RETURNS INT

EXTERNAL NAME 'ServerSideFunction@extesql.dll' LANGUAGE C_ESQL32;


SELECT ServerSideESQL();


// The following statement should return two identical rows SELECT COUNT(*) FROM esqlTab

UNION ALL

SELECT COUNT(*) FROM SYS.SYSTAB;

与在前面的示例中一样,要使用服务器端 SAP Sybase IQ C API 调用,C/C++ 代码必 须使用缺省数据库连接。要获取数据库连接的句柄,请以 EXTFN_CONNECTION_HANDLE_ARG_NUM 参数调用 get_value。该参数会指示数 据库服务器返回当前外部环境连接,而不是打开一个新连接。以下示例显示了这样一 个框架:获得连接句柄、初始化 C API 环境并将连接句柄转换成可与 SAP Sybase IQ C API 一起使用的连接对象 (a_sqlany_connection)

image

include <windows.h>

#include "sacapidll.h"

#include "extfnapi.h"


BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call,

LPVOID lpReserved

)

{

return TRUE;

}


extern "C"


declspec( dllexport )

void ServerSideFunction( an_extfn_api *extapi, void *arg_handle )

{

short result;

an_extfn_value arg;

an_extfn_value retval;

unsigned offset;

char *cmd;


SQLAnywhereInterface capi; a_sqlany_connection * sqlany_conn; unsigned int max_api_ver;


image

result = extapi->get_value( arg_handle,

EXTFN_CONNECTION_HANDLE_ARG_NUM,

&arg );


if( result == 0 || arg.data == NULL )

{

return;

}

if( !sqlany_initialize_interface( &capi, NULL ) )

{

return;

}

if( !capi.sqlany_init( "MyApp", SQLANY_CURRENT_API_VERSION,

&max_api_ver ) )

{

sqlany_finalize_interface( &capi ); return;

}

sqlany_conn = sqlany_make_connection( arg.data );


// processing code goes here capi.sqlany_fini();

sqlany_finalize_interface( &capi ); return;

}

如果以上 C 代码存储在文件 extcapi.c 中,则可用以下命令为 Windows 生成该文件。

image

cl /LD /Tp extcapi.c /Tp c:\sa12\SDK\C\sacapidll.c

/Ic:\sa12\SDK\Include c:\sa12\SDK\Lib\X86\dbcapi.lib

下例用于定义用来调用编译过的本地函数的存储过程包装,然后调用该本地函数。

image

CREATE FUNCTION ServerSideC() RETURNS INT

EXTERNAL NAME 'ServerSideFunction@extcapi.dll' LANGUAGE C_ESQL32;


SELECT ServerSideC();

上例中的 LANGUAGE 属性指定 C_ESQL32。将为 64 位应用程序使用 C_ESQL64。 必须使用嵌入式 SQL 语言属性,因为 SAP Sybase IQ C API 构建在与 ESQL 相同的层

(库)上。

如前所述,每个用于执行外部环境调用的连接都将启动各自的 dbexternc12 副本。首 次执行外部环境调用时,此可执行应用程序由服务器自动装载。但是,可以使用 START EXTERNAL ENVIRONMENT 语句预装载 dbexternc12。这在想要避免在首次执行外 部环境调用时出现的略微延迟的情况下很有用。以下是该语句的示例。

image

START EXTERNAL ENVIRONMENT C_ESQL32


预装载 dbexternc12 在另一种情况也很有用,即想要调试外部函数时。可以使用调试 程序连接到正在运行的 dbexternc12 过程,并在外部函数中设置断点。

更新动态链接库或共享对象时,STOP EXTERNAL ENVIRONMENT 语句很有用。该 语句将为当前连接终止本地库装载程序 dbexternc12,从而释放对动态链接库或共享 对象的访问。如果多个连接在使用同一个动态链接库或共享对象,则必须终止其每一个 dbexternc12 副本。必须在 STOP EXTERNAL ENVIRONMENT 语句中指定相应的外 部环境名称。以下是该语句的示例。

image

STOP EXTERNAL ENVIRONMENT C_ESQL32

要从外部函数返回结果集,编译过的本地函数必须使用本地函数调用接口。

以下代码段显示了如何设置结果集信息结构。它包含列计数、指向列信息结构数组的 指针,以及指向列数据值结构数组的指针。该示例也使用 SAP Sybase IQ C API

image

an_extfn_result_set_info rs_info;

int columns = capi.sqlany_num_cols( sqlany_stmt ); an_extfn_result_set_column_info *col_info =

(an_extfn_result_set_column_info *)

malloc( columns * sizeof(an_extfn_result_set_column_info) );


an_extfn_result_set_column_data *col_data = (an_extfn_result_set_column_data *)

malloc( columns * sizeof(an_extfn_result_set_column_data) );


rs_info.number_of_columns = columns; rs_info.column_infos = col_info; rs_info.column_data_values = col_data;

以下代码段显示了如何描述结果集。它使用 SAP Sybase IQ C API 为先前由 C API 执行的 SQL 查询获取列信息。从 SAP Sybase IQ C API 获得的各列信息将被转换为用于描述 结果集的列名称、类型、宽度、索引以及空值指示符。

image

a_sqlany_column_info info; for( int i = 0; i < columns; i++ )

{

if( sqlany_get_column_info( sqlany_stmt, i, &info ) )

{

// set up a column description col_info[i].column_name = info.name; col_info[i].column_type = info.native_type; switch( info.native_type )

{


C API API

case DT_DATE: // DATE is converted to string by C API case DT_TIME: // TIME is converted to string by C API case DT_TIMESTAMP: // TIMESTAMP is converted to string by

case DT_DECIMAL: // DECIMAL is converted to string by C col_info[i].column_type = DT_FIXCHAR;

break;

case DT_FLOAT: // FLOAT is converted to double by C API


image

col_info[i].column_type = DT_DOUBLE; break;

case DT_BIT: // BIT is converted to tinyint by C API col_info[i].column_type = DT_TINYINT;

break;

}

col_info[i].column_width = info.max_size; col_info[i].column_index = i + 1; // column indices are origin

1

col_info[i].column_can_be_null = info.nullable;

}

}

// send the result set description if( extapi->set_value( arg_handle,

EXTFN_RESULT_SET_ARG_NUM,

(an_extfn_value *)&rs_info, EXTFN_RESULT_SET_DESCRIBE ) == 0 )

{

// failed

free( col_info ); free( col_data ); return;

}

一旦描述了结果集,就可以返回结果集行。以下代码段显示了如何返回结果集的行。 它使用 SAP Sybase IQ C API 为先前由 C API 执行的 SQL 查询读取行。由 SAP Sybase IQ C API 返回的行被发送回调用环境,一次发回一行。返回各行之前,必须先填充列数 据值结构的数组。列数据值结构包括列索引、指向数据值的指针、数据长度和附加标 志。

image

a_sqlany_data_value *value = (a_sqlany_data_value *) malloc( columns * sizeof(a_sqlany_data_value) );


while( capi.sqlany_fetch_next( sqlany_stmt ) )

{

for( int i = 0; i < columns; i++ )

{

if( capi.sqlany_get_column( sqlany_stmt, i, &value[i] ) )

{

col_data[i].column_index = i + 1; col_data[i].column_data = value[i].buffer; col_data[i].data_length =

(a_sql_uint32)*(value[i].length);

col_data[i].append = 0; if( *(value[i].is_null) )

{

// Received a NULL value col_data[i].column_data = NULL;

}

}

}

if( extapi->set_value( arg_handle,

EXTFN_RESULT_SET_ARG_NUM,

(an_extfn_value *)&rs_info, EXTFN_RESULT_SET_NEW_ROW_FLUSH ) == 0 )


image

{

// failed

free( value ); free( col_data ); free( col_data );

extapi->set_value( arg_handle, 0, &retval, 0 ); return;

}

}




--------------------------------------华丽的分割线-------------------------------------------------------------------------
之前就已经研发成功了能够从Sybase SQL Anywhere的DB文件中恢复数据的工具:ReadASADB。
此工具支持ASA v5.0,v6.0,v7.0,v8.0,v9.0,v10.0,v11.0,v12.0等版本。
恢复Sybase SQL Anywhere的工具在国内应该算首创。

ReadASADB功能
能够从损坏的SQL Anywhere数据文件(.db)和UltraLite数据文件(.udb)上提取数据的非常规恢复工具

  1. 适用于所有的SQL Anywhere版本    包括:5.x,6.x,7.x,8.x,9.x,10.x,11.x,12.x
  2. 适用于所有的UltraLite版本
  3. 能够恢复出来表结构和数据
  4. 能够恢复自定义数据类型
  5. 能够恢复存储过程等对象的语法
  6. 能够导出到目标数据库
  7. 能够导出到SQL文件并生成导入脚本
  8. 支持多种字符集  包括:cp850、cp936、gb18030、utf8等
  9. 能够恢复未加密或者简单加密类型的数据
  10. 简单易用
  11. 限制:不支持AES加密的数据文件
请参考:研发成功了从Sybase SQL Anywhere的DB文件上恢复数据的工具
            SQL Anywhere数据库非常规恢复工具ReadASADB使用介绍

ReadASADB适用场景

各种误操作:

  1. 误截断表(truncate table)
  2. 误删除表(drop table)
  3. 错误的where条件误删数据
  4. 误删除db或log文件
  5. 误删除表中的字段

本工具的应用场景:

1.因为物理磁盘故障、操作系统、系统软件方面或者掉电等等原因导致的Sybase SQL Anywhere数据库无法打开的情况;
2.误操作,包括truncate table,drop table,不正确的where条件导致的误删除等;
Sybase SQL Anywhere无法打开时,比较常见的错误是:Assertion failed。
如:
1、Internal database error *** ERROR *** Assertion failed:201819 (8.0.1.2600) Checkpoint log: invalid bitmap page -- transaction rolled back
2、Internal database error *** ERROR *** Assertion failed:201819 (8.0.1.2600) Page number on page does not match page requested -- transaction rolled back
3、Internal database error *** ERROR *** Assertion failed:200502 (9.0.2.2451) Checksum failure on page 23 -- transaction rolled back
4、File is shorter than expected
5、Internal database error *** ERROR *** Assertion failed: 201116 Invalid free list index page found while processing checkpoint log -- transaction rolled back
6、*** ERROR *** Assertion failed: 51901 Page for requested record not a table page or record not present on page等等。
+-------------------------------------华丽的分割线-------------------------------------------------------------------------