

# Amazon RDS for Db2 的外部存储过程
<a name="db2-external-stored-procedures"></a>

您可以创建外部例程，并将其作为外部存储过程注册到您的 Amazon RDS for Db2 数据库。目前，RDS for Db2 只支持对外部存储过程使用基于 Java 的例程。

## 基于 Java 的外部存储过程
<a name="db2-external-stored-procedures-java"></a>

基于 Java 的外部存储过程是作为外部存储过程注册到 RDS for Db2 数据库的外部 Java 例程。

**Topics**
+ [基于 Java 的外部存储过程的限制](#db2-external-stored-procedures-java-limitations)
+ [配置基于 Java 的外部存储过程](#db2-external-stored-procedures-java-configuring)

### 基于 Java 的外部存储过程的限制
<a name="db2-external-stored-procedures-java-limitations"></a>

在开发外部例程之前，请考虑以下限制和局限性。

要创建外部例程，请务必使用 Db2 提供的 Java 开发工具包（JDK）。有关更多信息，请参阅 [Java software support for Db2 database products](https://www.ibm.com/docs/en/db2/11.5?topic=servers-java-software-support-db2-database-products)。

您的 Java 程序只能在 `/tmp` 目录中创建文件，而 Amazon RDS 不支持对这些文件启用可执行文件或设置用户 ID（SUID）权限。您的 Java 程序也无法使用套接字系统调用或以下系统调用：
+ \$1sysctl
+ acct
+ afs\$1syscall
+ bpf
+ capset
+ chown
+ chroot
+ create\$1module
+ delete\$1module
+ fanotify\$1init
+ fanotify\$1mark
+ finit\$1module
+ fsconfig
+ fsopen
+ fspick
+ get\$1kernel\$1syms
+ getpmsg
+ init\$1module
+ mount
+ move\$1mount
+ nfsservctl
+ open\$1by\$1handle\$1at
+ open\$1tree
+ pivot\$1root
+ putpmsg
+ query\$1module
+ quotactl
+ reboot
+ security
+ setdomainname
+ setfsuid
+ sethostname
+ sysfs
+ tuxcall
+ umount2
+ uselib
+ ustat
+ vhangup
+ vserver

有关 Db2 的外部例程的其它限制，请参阅 IBM Db2 文档中的 [Restrictions on external routines](https://www.ibm.com/docs/en/db2/11.5?topic=routines-restrictions-external) 。

### 配置基于 Java 的外部存储过程
<a name="db2-external-stored-procedures-java-configuring"></a>

要配置外部存储过程，请使用外部例程创建一个 .jar 文件，将其安装在 RDS for Db2 数据库上，然后将它注册为外部存储过程。

**Topics**
+ [步骤 1：启用外部存储过程](#db2-external-stored-procedures-java-enable)
+ [步骤 2：使用外部例程安装 .jar 文件](#db2-external-stored-procedures-java-install-jar)
+ [步骤 3：注册外部存储过程](#db2-external-stored-procedures-java-register)
+ [步骤 4：验证外部存储过程](#db2-external-stored-procedures-java-validate)

#### 步骤 1：启用外部存储过程
<a name="db2-external-stored-procedures-java-enable"></a>

要启用外部存储过程，请在与数据库实例关联的自定义参数组中，将参数 `db2_alternate_authz_behaviour` 设置为以下值之一：
+ `EXTERNAL_ROUTINE_DBADM` – 隐式向任何具有 `DBADM` 权限的用户、组或角色授予 `CREATE_EXTERNAL_ROUTINE` 权限。
+ `EXTERNAL_ROUTINE_DBAUTH` – 允许具有 `DBADM` 权限的用户向任何用户、组或角色授予 `CREATE_EXTERNAL_ROUTINE` 权限。在这种情况下，任何用户、组或角色都不会被隐式授予此权限，即使是具有 `DBADM` 权限的用户也一样。

有关此设置的更多信息，请参阅 IBM Db2 文档中的 [GRANT (database authorities) statement](https://www.ibm.com/docs/en/db2/11.5?topic=statements-grant-database-authorities)。

您可以使用 Amazon Web Services 管理控制台、Amazon CLI 或 Amazon RDS API 创建和修改自定义参数组。

##### 控制台
<a name="db2-external-stored-procedures-java-enable-console"></a>

**在自定义参数组中配置 db2\$1alternate\$1authz\$1behaviour 参数**

1. 如果您想要使用的自定义数据库参数组不同于数据库实例正在使用的自定义数据库参数组，就必须创建一个新的数据库参数组。如果您使用自带许可（BYOL）模型，请确保新的自定义参数组包含 IBM ID。有关这些 ID 的信息，请参阅 [Db2 的自带许可（BYOL）的 IBM ID](db2-licensing.md#db2-prereqs-ibm-info)。有关创建数据库参数组的详细信息，请参阅 [在 Amazon RDS 中创建数据库参数组](USER_WorkingWithParamGroups.Creating.md)。

1. 在自定义参数组中设置 `db2_alternate_authz_behaviour` 参数的值。有关修改参数组的更多信息，请参阅[在 Amazon RDS 中修改数据库参数组中的参数](USER_WorkingWithParamGroups.Modifying.md)。

##### Amazon CLI
<a name="db2-external-stored-procedures-java-enable-cli"></a>

**在自定义参数组中配置 db2\$1alternate\$1authz\$1behaviour 参数**

1. 如果您想要使用的自定义数据库参数组不同于数据库实例正在使用的自定义数据库参数组，请运行 [https://docs.amazonaws.cn/cli/latest/reference/rds/create-db-parameter-group.html](https://docs.amazonaws.cn/cli/latest/reference/rds/create-db-parameter-group.html) 命令创建一个自定义参数组。如果您使用自带许可（BYOL）模型，请确保新的自定义参数组包含 IBM ID。有关这些 ID 的信息，请参阅 [Db2 的自带许可（BYOL）的 IBM ID](db2-licensing.md#db2-prereqs-ibm-info)。

   包括以下必需选项：
   + `--db-parameter-group-name` - 您正在创建的参数组的名称。
   + `--db-parameter-group-family` – Db2 引擎版本和主要版本。有效值为 `db2-se-11.5` 和 `db2-ae-11.5`。
   + `--description` – 此参数组的描述。

   有关创建数据库参数组的详细信息，请参阅 [在 Amazon RDS 中创建数据库参数组](USER_WorkingWithParamGroups.Creating.md)。

   以下示例显示如何为参数组系列 `db2-se-11.5` 创建名为 `MY_EXT_SP_PARAM_GROUP` 的自定义参数组。

   对于 Linux、macOS 或 Unix：

   ```
   aws rds create-db-parameter-group \
   --region us-east-1 \
   --db-parameter-group-name MY_EXT_SP_PARAM_GROUP \
   --db-parameter-group-family db2-se-11.5 \ 
   --description "test db2 external routines"
   ```

   对于：Windows

   ```
   aws rds create-db-parameter-group ^
   --region us-east-1 ^
   --db-parameter-group-name MY_EXT_SP_PARAM_GROUP ^
   --db-parameter-group-family db2-se-11.5 ^ 
   --description "test db2 external routines"
   ```

1. 通过运行 [https://docs.amazonaws.cn/cli/latest/reference/rds/modify-db-parameter-group.html](https://docs.amazonaws.cn/cli/latest/reference/rds/modify-db-parameter-group.html) 命令修改您的自定义参数组中的 `db2_alternate_authz_behaviour` 参数。

   包括以下必需选项：
   + `--db-parameter-group-name` – 您创建的参数组的名称。
   + `--parameters` – 参数名称、值和参数更新应用方法的数组。

   有关修改参数组的更多信息，请参阅[在 Amazon RDS 中修改数据库参数组中的参数](USER_WorkingWithParamGroups.Modifying.md)。

   以下示例说明如何通过将 `db2_alternate_authz_behaviour` 的值设置为 `EXTERNAL_ROUTINE_DBADM` 来修改参数组 `MY_EXT_SP_PARAM_GROUP`。

   对于 Linux、macOS 或 Unix：

   ```
   aws rds modify-db-parameter-group \
       --db-parameter-group-name MY_EXT_SP_PARAM_GROUP \
       --parameters "ParameterName='db2_alternate_authz_behaviour',ParameterValue='EXTERNAL_ROUTINE_DBADM',ApplyMethod=immediate"
   ```

   对于：Windows

   ```
   aws rds modify-db-parameter-group ^
       --db-parameter-group-name MY_EXT_SP_PARAM_GROUP ^
       --parameters "ParameterName='db2_alternate_authz_behaviour',ParameterValue='EXTERNAL_ROUTINE_DBADM',ApplyMethod=immediate"
   ```

##### RDS API
<a name="db2-external-stored-procedures-java-enable-api"></a>

**在自定义参数组中配置 db2\$1alternate\$1authz\$1behaviour 参数**

1. 如果您想要使用的自定义数据库参数组不同于数据库实例正在使用的自定义数据库参数组，请使用 Amazon RDS API [https://docs.amazonaws.cn/AmazonRDS/latest/APIReference/API_CreateDBParameterGroup.html](https://docs.amazonaws.cn/AmazonRDS/latest/APIReference/API_CreateDBParameterGroup.html) 操作创建一个新的数据库参数组。如果您使用自带许可（BYOL）模型，请确保新的自定义参数组包含 IBM Db2 ID。有关这些 ID 的信息，请参阅 [Db2 的自带许可（BYOL）的 IBM ID](db2-licensing.md#db2-prereqs-ibm-info)。

   包括以下必需参数：
   + `DBParameterGroupName`
   + `DBParameterGroupFamily`
   + `Description`

   有关创建数据库参数组的详细信息，请参阅 [在 Amazon RDS 中创建数据库参数组](USER_WorkingWithParamGroups.Creating.md)。

1. 修改您使用 RDS API [https://docs.amazonaws.cn/AmazonRDS/latest/APIReference/API_ModifyDBParameterGroup.html](https://docs.amazonaws.cn/AmazonRDS/latest/APIReference/API_ModifyDBParameterGroup.html) 操作创建的自定义参数组中的 `db2_alternate_authz_behaviour` 参数。

   包括以下必需参数：
   + `DBParameterGroupName`
   + `Parameters`

   有关修改参数组的更多信息，请参阅[在 Amazon RDS 中修改数据库参数组中的参数](USER_WorkingWithParamGroups.Modifying.md)。

#### 步骤 2：使用外部例程安装 .jar 文件
<a name="db2-external-stored-procedures-java-install-jar"></a>

创建 Java 例程后，创建 .jar 文件，然后运行 `db2 "call sqlj.install_jar('file:file_path',jar_ID)"` 来将它安装到 RDS for Db2 数据库上。

以下示例展示了如何创建 Java 例程并将其安装到 RDS for Db2 数据库上。该示例包括可用于测试该过程的简单例程的示例代码。本示例作出以下假设：
+ Java 代码是在安装了 Db2 的服务器上编译的。这是最佳实践，因为不使用 IBM 提供的 JDK 进行编译可能会导致无法解释的错误。
+ 服务器对于 RDS for Db2 数据库进行了本地编目。

如果您想使用以下示例代码尝试该过程，请复制它并将它保存到名为 `MYJAVASP.java` 的文件中。

```
import java.sql.*;
public class MYJAVASP
{
public static void my_JAVASP (String inparam) throws SQLException, Exception
{
try
{
// Obtain the calling context's connection details.
Connection myConn = DriverManager.getConnection("jdbc:default:connection");
String myQuery = "INSERT INTO TEST.TEST_TABLE VALUES (?, CURRENT DATE)";
PreparedStatement myStmt = myConn.prepareStatement(myQuery);
myStmt.setString(1, inparam);
myStmt.executeUpdate();
}
catch (SQLException sql_ex)
{
throw sql_ex;
}
catch (Exception ex)
{
throw ex;
}
}
```

以下命令编译 Java 例程。

```
~/sqllib/java/jdk64/bin/javac MYJAVASP.java
```

以下命令创建 .jar 文件。

```
~/sqllib/java/jdk64/bin/jar cvf MYJAVASP.jar MYJAVASP.class
```

以下命令连接到名为 `MY_DB2_DATABASE` 的数据库并安装 .jar 文件。

```
db2 "connect to MY_DB2_DATABASE user master_username using master_password" 

db2 "call sqlj.install_jar('file:/tmp/MYJAVASP.jar','MYJAVASP')"
db2 "call sqlj.refresh_classes()"
```

#### 步骤 3：注册外部存储过程
<a name="db2-external-stored-procedures-java-register"></a>

在 RDS for Db2 数据库上安装 .jar 文件后，通过运行 `db2 CREATE PROCEDURE` 或 `db2 REPLACE PROCEDURE` 命令将其注册为存储过程。

以下示例说明如何连接到数据库，并将在上一步中创建的 Java 例程注册为存储过程。

```
db2 "connect to MY_DB2_DATABASE user master_username using master_password"

create procedure TESTSP.MYJAVASP (in input char(6))
specific myjavasp
dynamic result sets 0
deterministic
language java
parameter style java
no dbinfo
fenced
threadsafe
modifies sql data
program type sub
external name 'MYJAVASP!my_JAVASP';
```

#### 步骤 4：验证外部存储过程
<a name="db2-external-stored-procedures-java-validate"></a>

使用以下步骤来测试在上一步中注册的示例外部存储过程。

**验证外部存储过程**

1. 在下面的示例中创建一个类似于 `TEST.TEST_TABLE` 的表。

   ```
   db2 "create table TEST.TEST_TABLE(C1 char(6), C2 date)"
   ```

1. 调用新的外部存储过程。该调用返回的状态为 `0`。

   ```
   db2 "call TESTSP.MYJAVASP('test')"
   Return Status = 0
   ```

1. 查询您在步骤 1 中创建的表，来验证存储过程调用的结果。

   ```
   db2 "SELECT * from TEST.TEST_TABLE"
   ```

   此查询将生成类似于下面示例的输出：

   ```
   C1     C2
   ------ ----------
   test   02/05/2024
   ```