Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 11.0.1 (中文) » MobiLink - 服务器管理 » MobiLink 事件 » 同步事件

 

handle_error 连接事件

每当 MobiLink 服务器遇到 SQL 错误时执行。

参数

在下表中,说明部分提供 SQL 数据类型。如果您使用 Java 或 .NET 编写脚本,则应该使用相应的数据类型。请参见SQL-Java 数据类型SQL-.NET 数据类型

在 SQL 脚本中,可以使用名称或问号指定事件参数,但不能在一个脚本中混合使用名称和问号。如果使用问号,则参数必须按照如下所示的顺序并且仅当没有指定任何后继参数时才是可选的(例如,如果您想使用参数 2,则必须使用参数 1)。如果使用命名参数,则可以按照任何顺序指定任意参数子集。

SQL 脚本的参数名称

说明

顺序

s.action_code

INTEGER。这是一个 INOUT 参数。

1

s.error_code

INTEGER

2

s.error_message

TEXT

3

s.remote_id VARCHAR(128)。MobiLink 远程 ID。只有在使用命名参数时才能引用远程 ID。 不适用

s.username

VARCHAR(128)。MobiLink 用户名。

4

s.table

VARCHAR(128)。如果脚本不是表脚本,则表名为空。

5

缺省操作

在未定义 handle_error 脚本或此脚本导致错误时,缺省操作代码为 3000:回退当前事务并取消当前同步。

注释

MobiLink 服务器传递当前的操作代码。最初,对于每一组由一个单独的 SQL 操作引起的错误,该值都设置为 3000。通常情况下,每个 SQL 操作只会出现一个错误,但也可能出现多个。在一组错误中每出现一次错误时都会调用一次 handle_error 脚本。传递到第一个错误的动作代码是 3000,后续调用是在前一次调用所返回的动作代码中传递的。MobiLink 使用多个调用所返回的数值中的最大值。

您可以修改脚本中的操作代码并返回一个值以指示 MobiLink 如何继续。操作代码将告知 MobiLink 服务器下一步该做什么。在调用此脚本之前,MobiLink 服务器将操作代码设置为缺省值,该缺省值的大小取决于错误的严重程度。您可以使用脚本修改此值。脚本必须返回或设置一个操作代码。

操作代码参数可以使用以下值:

  • 1000   跳过当前行并继续执行。

  • 3000   回退当前事务并取消当前同步。这是缺省操作代码,在未定义 handle_error 脚本或此脚本导致错误时使用此代码。

  • 4000   回退当前事务,取消同步并关闭 MobiLink 服务器。

错误代码和消息可用于标识错误的性质。如果错误是作为同步的一部分发生的,则提供用户名。否则该值为空。

当 MobiLink 在上载事务期间处理插入、更新或删除脚本时或当其读取下载行时,如果发生 ODBC 错误,则 MobiLink 服务器执行此脚本。如果 ODBC 错误在其它时间发生,则 MobiLink 服务器调用 report_error 或 report_ODBC_error 脚本并中止同步。

如果在操作某特定表时发生错误,则提供表名称。否则该值为空。表名称是客户端应用程序中表的名称。此名称在统一数据库中是否存在直接对应的名称取决于同步系统的设计。

handle_error 事件的 SQL 脚本必须作为存储过程执行。

可以使用以下方法中的一种从 handle_error 脚本返回值:

  • 将操作参数传递给存储过程的 OUTPUT 参数:

    CALL my_handle_error( {ml s.action_code}, {ml s.error_code}, {ml s.error_message}, {ml s.username}, {ml s.table} )
  • 使用过程或函数返回值设置操作代码:

    {ml s.action_code} = CALL my_handle_error( {ml s.error_code}, {ml s.error_message}, {ml s.username}, {ml s.table} )

    大多数 RDBMS 会使用 RETURN 语句设置过程或函数的返回值。

CustDB 示例应用程序中包含用于各种数据库管理系统的错误处理程序。

另请参见
SQL 示例

以下示例在 SQL Anywhere 统一数据库中运行。它允许您的应用程序忽略冗余插入。

以下对 MobiLink 系统过程的调用将 ULHandleError 存储过程指派给 handle_error 事件。

CALL ml_add_connection_script(
    'ver1',
    'handle_error',
    'CALL ULHandleError(
      {ml s.action_code}, 
      {ml s.error_code}, 
      {ml s.error_message}, 
      {ml s.username}, 
      {ml s.table} )' )

以下 SQL 语句创建 ULHandleError 存储过程。

CREATE PROCEDURE ULHandleError(
   INOUT action integer,
   IN error_code integer,
   IN error_message varchar(1000),
   IN user_name varchar(128),
   IN table_name varchar(128) )
BEGIN
  -- -196 is SQLE_INDEX_NOT_UNIQUE
  -- -194 is SQLE_INVALID_FOREIGN_KEY
  IF error_code = -196 or error_code = -194 then
      -- ignore the error and keep going
      SET action = 1000;
  ELSE
      -- abort the synchronization
      SET action = 3000;
  END IF;
END
Java 示例

以下对 MobiLink 系统过程的调用在同步脚本版本 ver1 时将名为 handleError 的 Java 方法注册为 handle_error 连接事件的脚本。

CALL ml_add_java_connection_script(
    'ver1',
    'handle_error',
    'ExamplePackage.ExampleClass.handleError' )

以下是 Java 方法 handleError 示例。它根据传入的数据处理错误。同时还确定结果错误代码。

public String handleError(
  ianywhere.ml.script.InOutInteger actionCode,
  int errorCode,
  String errorMessage,
  String user,
  String table ) {
  int newAC;
  if( user == null ) {
    newAC = handleNonSyncError( errorCode,
    errorMessage ); }
  else if( table == null ) {
    newAC = handleConnectionError( errorCode,
    errorMessage, user ); }
  else {
    newAC = handleTableError( errorCode,
    errorMessage, user, table ); 
  }
  // Keep the most serious action code.
  if( actionCode.getValue() < newAC ) {
    actionCode.setValue( newAC ); 
  }
}
.NET 示例

以下对 MobiLink 系统过程的调用在同步脚本版本 ver1 时将名为 HandleError 的 .NET 方法注册为 handle_error 连接事件的脚本。

CALL ml_add_dnet_connection_script(
  'ver1',
  'handle_error',
  'TestScripts.Test.HandleError' )

以下是 .NET 方法 HandleError 示例。

public string HandleError() (
  ref int actionCode,
  int errorCode,
  string errorMessage,
  string user,
  string table ) {
  int new_ac;
  if( user == null ) {
    new_ac = HandleNonSyncError( errorCode,
    errorMessage ); }
  else if( table == null ) {
    new_ac = HandleConnectionError( errorCode,
    errorMessage, user ); }
  else {
    new_ac = HandleTableError( errorCode,
    errorMessage, user, table ); 
  }
  // Keep the most serious action code.
  if( actionCode < new_ac ) {
    actionCode = new_ac; 
  }
}