文章 姚 鑫 · 三月 22, 2021 1m read

第十二章 使用嵌入式SQL(六)

第十二章 使用嵌入式SQL(六)

持久类方法中的嵌入式SQL

下面的示例显示了一个持久类,其中包含一个类方法和一个实例方法,两者都包含嵌入式SQL:

Class Sample.MyClass Extends %Persistent [DdlAllowed]
 { 
 ClassMethod NameInitial(Myval As %String) As %String [SqlProc]
  {
     &sql(SELECT Name INTO :n FROM Sample.Stuff WHERE Name %STARTSWITH :Myval)
        IF SQLCODE<0 {WRITE "SQLCODE error ",SQLCODE  RETURN %msg}
        ELSEIF SQLCODE=100 {WRITE "Query returns no results"  RETURN}
   WRITE "Hello "  RETURN n
  }
 Method CountRows() As %Integer
  {
   &sql(SELECT COUNT(*) INTO :count FROM Sample.Stuff)
        IF SQLCODE<0 {WRITE "SQLCODE error ",SQLCODE  RETURN %msg}
        ELSEIF SQLCODE=100 {WRITE "Query returns no results"  RETURN}
   WRITE "Number of rows is "  RETURN count
  }
 }
```

类方法的调用如下:

```java
 WRITE ##class(Sample.MyClass).NameInitial("G")
```

实例方法的调用如下:

```java
  SET x=##class(Sample.MyClass).%New()
  WRITE x.CountRows()
```

要成功编译这些方法,不必存在诸如表和字段之类的SQL实体。由于检查SQL实体是否存在是在运行时执行的,因此嵌入式SQL方法应包含`SQLCODE`测试逻辑。

以测试嵌入式SQL中指定的SQL实体是否存在,而无需执行代码。验证嵌入式SQL代码中对此进行了描述。

# 验证嵌入式SQL代码

可以通过两种方式验证嵌入式SQL代码而无需执行代码:

- 使用`/compileembedded = 1`限定符编译包含嵌入式SQL代码的例程。
- 使用`$SYSTEM.OBJ.GenerateEmbedded()`方法编译多个嵌入式SQL例程。
- 使用管理门户网站SQL界面的“显示计划”选项测试嵌入式SQL代码。

## 使用`/compileembedded`限定符进行编译

可以通过使用`$SYSTEM.OBJ`类的编译类方法并在`qspec`参数中指定`/ compileembedded = 1`限定符来验证嵌入式SQL代码。
- `$SYSTEM.OBJ.Compile()`编译指定的类以及该类中的所有例程。
- `$SYSTEM.OBJ.CompileList()`编译指定类的列表以及这些类中的所有例程。
- `$SYSTEM.OBJ.CompilePackage()`编译指定包(架构)中的所有类/例程。
- `$SYSTEM.OBJ.CompileAll()`编译当前名称空间中的所有类/例程。
- `$SYSTEM.OBJ.CompileAllNamespaces()`编译所有命名空间中的所有类/例程。

要显示`qspec`限定词(包括`/compileembedded`)的列表,请调用:

```java
  DO $SYSTEM.OBJ.ShowQualifiers()
```
## 使用Show Plan进行测试

可以使用Management Portal SQL界面来验证嵌入式SQL代码,而无需执行该代码。此操作既可以验证SQL语法,也可以检查指定的SQL实体是否存在。

从Management Portal System Explorer选项中,选择SQL选项以显示`Execute Query code`区域。

1. 输入嵌入式SQL查询。例如,`SELECT Name INTO:n from Sample.MyTest或DECLARE MyCursor CURSOR FOR SELECT Name,Age INTO:n,:a FROM Sample.MyTest,age> 21`,仅供只读。
2. 按下显示计划按钮以检查代码。如果代码有效,则“显示计划”将显示一个查询计划。如果代码无效,则“显示计划”将显示`SQLCODE`错误值和消息。

![image](5E344B5B4525418B8298575E3E3975F8)

请注意,如果缺少`INTO`子句,`Show Plan`验证将不会发出错误,因为可以在`FETCH`语句中指定`INTO`子句。如果`INTO`子句包含错误或位于错误的位置,则`Show Plan`将发出适当的错误。

不能使用“执行”按钮执行嵌入式SQL代码。

# 审核嵌入式SQL

InterSystems IRIS支持对嵌入式SQL语句的可选审核。满足以下两个要求时,将执行嵌入式SQL审核:

1. `%System /%SQL / EmbeddedStatement`系统审核事件在系统范围内启用。默认情况下,未启用此系统审核事件。要启用,请依次转到管理门户,系统管理,安全性,审核,然后配置系统事件。
2. 包含嵌入式SQL语句的例程必须包含`#SQLCompile Audit`宏预处理程序指令。如果此伪指令设置为`ON`,则在执行时将审核编译例程中跟在其后的任何嵌入式SQL语句。

审核将信息记录在审核数据库中。要查看审核数据库,请依次转到管理门户,系统管理,选择安全性,审核,然后查看审核数据库。可以将“事件名称”过滤器设置为Embedded Statement,以将“查看审核数据库”限制为“嵌入式SQL”语句。审核数据库列出了时间(本地时间戳记),用户,PID(进程ID)和描述,它们指定了嵌入式SQL语句的类型。例如,SQL SELECT语句。

![image](3C72D10A806342B4B0AE26A4D6733D3F)

通过选择事件的详细信息链接,可以列出其他信息,包括事件数据。事件数据包括执行的SQL语句和该语句的任何输入参数的值。例如:
```sql
SELECT TOP :n Name,ColorPreference INTO :name,:color FROM Sample.Stuff WHERE Name %STARTSWITH :letter 
Parameter values: 
n=5 
letter="F"

InterSystems IRIS还支持对动态SQL语句(事件名称= DynamicStatement)以及ODBC和JDBC语句(事件名称= XDBCStatement)进行审核。