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 事件 » 同步事件

 

download_cursor 表事件

定义游标以选择远程数据库中要下载并插入或更新的行。

参数

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

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

SQL 脚本的参数名称

说明

顺序

s.last_table_download

TIMESTAMP。表的上一次下载时间。

1

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

s.username

VARCHAR(128)。MobiLink 用户名。

2

缺省操作

无。

注释

MobiLink 服务器打开一个只读游标,并使用此游标读取要下载到远程数据库中的行列表。此脚本应该包含适当的 SELECT 语句。

您可以为远程数据库的每个表编写一个 download_cursor 脚本。

为了优化 UltraLite 客户端同步过程中下载阶段的性能,当主键值的范围超出了设备上的当前行时,您应按照主键对下载游标中的行进行排序。例如,下载大型参考表时将从这种优化中受益。

每个 download_cursor 脚本必须包含一个 SELECT 语句或对含有 SELECT 语句的过程的调用。MobiLink 服务器将使用此语句在统一数据库中定义游标。

该脚本必须选择与远程数据库中相应的表中的列对应的所有列。统一数据库中的列可以与远程数据库中相应的列具有不同的名称,但是列的类型必须相互兼容。

必须按照远程数据库中对应列的定义顺序来选择列。

注意,download_cursor 允许级联删除。因此,您可以从数据库中删除记录。

为了避免下载不必要的行,您应该在 download_cursor 脚本的 WHERE 子句中包括以下行:

AND last_table_download > '1900/1/1'

对于 Java 和 .NET 应用程序,此脚本必须返回有效的 SQL。

如果您因为正在进行影响下载性能的大量更新而考虑在 download_cursor 脚本中使用 READPAST 表提示,请考虑为下载改用快照隔离。READPAST 表提示如果在 download_cursor 脚本中使用可能会引起问题。使用基于时间戳的下载时,READPAST 提示会造成行遗漏丢失,还可能造成某行永远不会下载到远程数据库。例如:

  • 将某行添加到统一数据库并提交。该行有一个时间为昨天的 last_modified 列。

  • 同一行被更新但不提交。

  • last_download 时间为上周的远程数据库进行同步。

  • 如果 download_cursor 脚本试图使用 READPAST 选择行,则会跳过该行。

  • 更新该行的事务回退。远程数据库的下一个上次下载时间提前为今天。

从此时开始,除非进行更新,否则该行永远不会被下载。可能的解决方案是实现 modify_next_last_download_timestamp 脚本并将上次下载时间设置为最早打开的事务的开始时间。

另请参见
SQL 示例

以下示例来自于 Oracle 安装,但语句对于所有支持的数据库都有效。该示例将下载自从用户上次下载数据以来更改过且与 emp_name 列中的用户名相匹配的所有行。

CALL ml_add_table_script( 
  'Lab',
  'ULOrder',
  'download_cursor',
  'SELECT order_id, 
    cust_id, 
    prod_id, 
    emp_id, 
    disc, 
    quant, 
    notes, 
    status
   FROM ULOrder 
   WHERE last_modified >= {ml s.last_table_download} 
    AND emp_name = {ml s.username}' )
Java 示例

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

CALL ml_add_java_table_script(
   'ver1',
   'ULCustomer',
   'download_cursor',
   'ExamplePackage.ExampleClass.downloadCursor ' )

以下是 Java 方法 downloadCursor 示例。它返回一条 SQL 语句,用于下载 last_modified 列大于或等于上次下载时间的行。

public String downloadCursor( 
  java.sql.Timestamp ts, 
  String user )  {
  return( "SELECT cust_id, cust_name FROM ULCustomer 
             WHERE last_modified >= ' " 
   + ts + " ' ");
}
.NET 示例

以下对 MobiLink 系统过程的调用在同步脚本版本 ver1 和表 table1 时将名为 DownloadCursor 的 .NET 方法注册为 download_cursor 表事件的脚本。

CALL ml_add_dnet_table_script(
 'ver1', 
 'table1', 
 'download_cursor',
 'TestScripts.Test.DownloadCursor'
)

以下是 .NET 方法 DownloadCursor 示例。它用名为 rows.txt 的文件的内容填充临时表。然后它返回一个游标,该游标使 MobiLink 将临时表中的行发送到远程数据库。此语法对于 SQL Anywhere 统一数据库有效。

public string DownloadCursor( 
  DateTime ts, 
  string user ) {
  DBCommand stmt   = curConn.CreateCommand();
  StreamReader input  = new StreamReader( "rows.txt" );
  string sql    = input.ReadLine();
  stmt.CommandText = "DELETE FROM dnet_dl_temp";
  stmt.ExecuteNonQuery();
  while( sql != null ){
    stmt.CommandText = "INSERT INTO dnet_dl_temp VALUES " + sql;
    stmt.ExecuteNonQuery();
    sql = input.ReadLine();
  }
  return( "SELECT * FROM dnet_dl_temp" );
}