清除过滤器
文章
Michael Lei · 九月 15, 2022
Spring Boot 是最常用来创建 REST API 和微服务的 Java 框架。 它可用于部署 Web 应用程序、可执行 Web 应用程序或桌面自包含应用程序,其中应用程序和其他依赖项打包在一起。 Spring Boot 允许执行许多功能,请参见:
注:要了解有关 SpringBoot 的信息,请参见官方网站 - https://spring.io/quickstart
要创建具有一个或多个微服务的 Web api 应用程序,可以使用 Spring IDE for Eclipse/VSCode,并使用向导配置上述将在应用程序中使用的技术,请参见:
![](/sites/default/files/inline/images/images/image(1388).png)
您可以选择技术并创建项目。 所有技术都将通过 maven 导入。 它就像一个可视化的 zpm。
所创建的项目有一个类用于为应用程序提供支持,其中包含所有所需内容(Web 和应用程序服务器,以及所有依赖项、微服务概念)。
此项目的完整源代码在以下 open exchange 项目中: https://openexchange.intersystems.com/package/springboot-iris-crud。
首先要配置 IRIS JDBC 驱动程序和 IRIS Hibernate 支持,为此,请将 jar 文件复制到 resources 文件夹,请参见:
![](/sites/default/files/inline/images/images/image(1390).png)
打开 pom.xml 以配置这些 jar 文件的依赖项,请参见:
<dependency>
<groupId>com.intersystems</groupId>
<artifactId>intersystems-jdbc</artifactId>
<version>3.2.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/intersystems-jdbc-3.2.0.jar</systemPath>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-iris</artifactId>
<version>1.0.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/hibernate-iris-1.0.0.jar</systemPath>
</dependency>
现在可以在 application.properties 中配置与 IRIS 数据库的连接,请参见:
spring.datasource.username=_SYSTEM
spring.datasource.url=jdbc:IRIS://iris:1972/USER
spring.datasource.password=SYS
spring.jpa.properties.hibernate.default_schema=dc_Sample
#spring.jpa.hibernate.ddl-auto=update
spring.datasource.driver-class-name=com.intersystems.jdbc.IRISDriver
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false
spring.jpa.database-platform=org.hibernate.dialect.InterSystemsIRISDialect
spring.datasource.sql-script-encoding=utf-8
server.tomcat.relaxed-query-chars=|,{,},[,]
spring.jpa.show-sql=false
spring.jpa.properties.hibernate.format_sql=true
下一步是创建一个映射到 IRIS 表的持久化 Java 类,请参见:
package community.intersystems.springboot.app.model;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import com.fasterxml.jackson.annotation.JsonFormat;
@Entity
@Table(name = "Product")
public class Product implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue (strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String description;
private Double height;
private Double width;
private Double weight;
@Column(name="releasedate")
@Temporal(TemporalType.DATE)
@JsonFormat(pattern = "dd/MM/yyyy")
private Date releaseDate;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Double getHeight() {
return height;
}
public void setHeight(Double height) {
this.height = height;
}
public Double getWidth() {
return width;
}
public void setWidth(Double width) {
this.width = width;
}
public Double getWeight() {
return weight;
}
public void setWeight(Double weight) {
this.weight = weight;
}
public Date getReleaseDate() {
return releaseDate;
}
public void setReleaseDate(Date releaseDate) {
this.releaseDate = releaseDate;
}
}
最后一步是创建一个仓库接口,以将您的持久化类作为 REST 服务公开(以 HATEOAS 模式),您无需执行 crud 操作,只需编写以下代码:
package community.intersystems.springboot.app.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import community.intersystems.springboot.app.model.Product;
public interface ProductRepository extends JpaRepository<Product, Long> {
}
现在,将您的应用程序作为 Spring Boot 应用程序运行:
![](/sites/default/files/inline/images/images/image(1389).png)
等待内部服务器启动,然后打开 localhost:8080。 Spring boot 将打开一个 API REST HAL 浏览器。 请参见以下图像记录:
![IRIS 与 Hibernate 配合运行](https://github.com/yurimarx/springboot-iris-crud/raw/master/iris-hibernate.gif)
更多详细信息,请参见我的应用程序示例。 我将所有内容一起打包成一个 Docker 项目,其中包含 2 个服务:IRIS 和 SpringBoot。
HATEOAS 模式非常适合 api url、路径和导航,更多详细信息,请自行百度。
祝使用愉快!
文章
Hao Ma · 十一月 22, 2022
命名规范,英文叫"name convention", 是对写代码取名字的一些”共识“。也就是说, 你可以不遵守,但大家都选择了遵守,照者一个规范来。为什么呢?因为有社区,大家要共享代码, 你不照着规矩来, 别人会鄙视你, 懒的用你的代码。
ObjectScript以前没什么社区,大家各写各的, 使用ObjectScript的大公司也没谁把自己的代码拿出来共享。因此,个人开发者基本就是参考官方InterSystems的命名规范。举个例子, 比如以下的代码:
```java
Class Ens.Util.ResponseBodyMethods
{
property NoFailWhileDisconnected as %Boolean;
property FirstName as %String;
parameter SETTINGS = "ReplyCodeActions";
method OnKeepalive(pAdapterStatus As %Status) as %String
{
return "okay"
}
}
```
我来简单总结一下:
- **包名和类名**:Pascal格式,也就是首字母大写。其中%开头的是官方独占,
- **Property名字**:首字母大写
- **method Name**:同上。但出入参用的是驼峰格式,也就是第一个单词小写,后面单词大写开头。
- **Parameter Name**:常量。
官方的代码都是这个规范吗? 大体上是,但也有例外, 比如%xsd包,包名类名全小写, 像这样: %xsd.string。这个从Caché年代就这样,我是不明白为什么这个包这么特殊。
到了IRIS上,更多瞎写了, 比如这个: [%SYSTEM.external.SQL](https://docs.intersystems.com/iris20222/csp/documatic/%25CSP.Documatic.cls?LIBRARY=%25SYS&CLASSNAME=%25SYSTEM.external.SQL)。不光是它,我发现很多和“external“相关的包名,都开始用小写了,写在代码里是这样的: %system.external.help(), %system.dotnet.SQL.addPath()。后面一个为什么SQL大小,dotnet小写,我也是没想明白。
然后,重要的来了。
InterSystems Developer Community贴出了这样的[community代码命名规范](https://community.intersystems.com/post/objectscript-package-manager-naming-convention)。它是怎么被推广的呢? 通过zpm,也就是社区里的代码ObjectScript的包管理工具。曾经一度你要参加社区的代码比赛,就必须使用zpm打包,而zpm对使用这个代码规范有硬要求,所以这个convention得到了一定程度的接受,能看到越来越多的开发者这么写代码了。
原文上面有链接,这里说最重要的:
**package名字全小写,class名字用首字母大写**。比如class会定义成:
```java
class company.project.subpackage.TheClass{
...
}
```
这基本上是借鉴Java。作者也说了:*The approach borrowed from the naming convention for java classes.* 作者还做了个解释:全小写的Package名字避免了和class或者interface的名字冲突。这句话我不是很明白。
我觉得网友只所以接受它,纯粹就是java和python用惯了,烦大写的类名。 如果都是c++, c#的程序员,估计这个命名规范还得有得吵。
我这里只说了包名类名, 其他的method, property, 变量的命名什么的,还包括github上repo起名字的规范, 有兴趣去原文看看吧。
我是挺喜欢这个规范的。
唯一有点不满意的是:Java中定义Package name 和class name不是连着写在一起的,比如下面:
```java
package org.springframework.asm;
public abstract class AnnotationVisitor {
...
}
```
所以你很少能看到包名和类名连写在一起的情况,所以小写的小写, 大写的大写,都不挨着。而ObjectScript的类定义一定要写全了, 上面的定义如果在ObjectScript里就是:
```java
public class org.springframework.asm.AnnotationVisitor {
...
}
```
因此这样的写法会有个视觉上的大小写的落差。
我属于没事找事的。
结论: 社区有了命名规范,矮骡子们纷纷表示支持。
按这个convention,Tony老师如果去写一个示例代码贡献给社区的话,可能是这样的
```java
class com.dhc.tony.demo.xml.TestUtils
{
property noFailWhileDisconnected as %Boolean;
property firstname as %String;
parameter SETTINGS = "ReplyCodeActions";
method onKeepalive(pAdapterStatus As %Status) as %String
{
return "okay"
}
}
```
我们目前还都是首字母大写的驼峰 之后是要统一改用zpm的命名规范吗。。。
文章
Michael Lei · 八月 26, 2021
# SAM - 设置和添加非 IRIS 目标指标的技巧和提示
SAM(系统警报和监视)以“功能齐全”的 docker-compose 容器集的形式提供,只要启动就可以开始以默认的仪表板监视 IRIS 实例。 使用初始配置就可以很好地了解 SAM 功能并开始对 IRIS 系统进行基本监视。 但是,当开始监视多个系统并收集大量指标数据时,需要更改一些默认设置。 为了从 SAM 获取更多价值,您还会想要添加来自其他数据源(目标)的指标。 以下技巧将帮助您在生产环境中部署 SAM,从多个目标收集指标并将这些指标组合到您自己的仪表板和图表中。 此外,您还将看到一些可能有助于探索 SAM 容器和应用程序的命令。
> *注意:*我应该指出,其中一些技巧和提示可能不是最佳做法;这更像是一个日志,记录了我第一次如何配置 SAM 来监视相同系统上的多个服务器和非 IRIS 目标的基准。 如果您有建议,请在评论中指教 ;) 所以,记住本帖可能会随着时间的推移而有所变化,让我们开始吧;
---
在下面的技巧中,有重启 docker 以及启动和停止 SAM 的操作。 请通读这些技巧,确定哪些适合您,然后按照下面的相同顺序执行。
## 1. 确保有足够的空间用于 SAM 数据库
默认情况下,docker 容器将文件存储在根 (/) 文件系统。 SAM 不需要很多 CPU 或内存资源;但是,指标收集将占用空间。
> 指标需要的存储容量“视情况而定”。 虽然在开始监视之前可能无法明确数据库大小,但大致上,在抓取周期为 15 秒的情况下,监视 10 个 IRIS 虚拟机以及操作系统指标大约消耗 50GB 存储。
策略包括:增加监视实例的根存储,或更改数据库的卷位置。 我使用了以下命令来更改运行 docker 的虚拟机上的 docker 目录。 也许是杀鸡用了牛刀,但很管用。
- 停止 docker 并将 docker 文件复制到空间充足的文件系统(本例中为 /data/docker/data)。 见下面的示例:
```other
[root@mysamserver lib]# sudo systemctl stop docker
[root@mysamserver lib]# pwd
/var/lib
[root@mysamserver lib]# cp -rp docker /data/docker/data
[root@mysamserver lib]#
[root@mysamserver lib]# rm -rf docker
```
- 在 docker 配置文件中更新卷路径。 注意此文件还有一个网络设置“bip”(请参见注释:...)
```swift
cat /etc/docker/daemon.json
{
"data-root": "/data/docker/data",
"bip": "192.168.0.1/24"
}
```
- 重启 docker
```swift
sudo systemctl daemon-reload
sudo systemctl restart docker
systemctl status docker.service
```
## 2. 设置 SAM
我假定您已在测试系统上设置 SAM,并熟悉它的基本操作:添加集群和实例,以及查看系统指标。 建议您花 20 分钟时间查看我在虚拟全球峰会 2020 上的展示,以了解安装步骤的概述,以及添加多个目标的运行指标时 SAM 的外观。 要观看此会议,请使用以下链接(您需要使用您的电子邮件注册):
[DEV007 系统警报和监视](https://intersystems.6connex.com/event/virtual-summit/en-us/contents/434680/share?rid=Lobby&nid=804450)
登录到 SAM 门户并配置一些 IRIS 实例。 这会填充配置文件并提供向导。
`http://mysamserver:8080/api/sam/app/index.csp#/`
> 注意:如果要添加多个实例,或者希望用脚本执行此步骤,可以通过 API 添加实例。 请参见文档。
## 3. 升级到生产许可证
SAM 随附了一个 IRIS 社区版许可证。 有几个限制,包括 IRIS.DAT 限制为 10GB。 10GB 不足以长时间从多个目标收集数据。 请联系您的 InterSystems 联系人以获取生产许可证。 在没有编辑器的情况下,在精简的容器中更新许可证可能很棘手,我只是在 IRIS 容器上登录一个交互式会话,然后使用以下命令更新许可证密钥:
- 打开 shell,切换目录至 mgr 文件夹(iris.key 文件的默认位置)
```swift
docker exec -it sam_iris_1 bash
cd /dur/iconfig/mgr
```
- 使用 unix“here 文档”更新密钥。 在“>”后面粘贴密钥文本。 在密钥文本后面,输入“>EOF”以提交命令。 然后输入“exit”退出 shell。
```other
cat
[ConfigFile]
FileType=InterSystems License Rev-A.1
LicenseID=999999
[License]
LicenseCapacity=InterSystems IRIS 2020.2 Server for SAM:etc etc, the key you were sent by your InterSystems contact.
>EOF
exit
```
- 然后使用提供的 docker-compose shell 脚本停止再启动 SAM:
```swift
./stop.sh
./start.sh
```
- 可以通过访问系统管理门户或登录到 iris 实例并检查 messages.log 来检查许可证是否一切正常。
```shell
docker exec -it sam_iris_1 bash
cd /dur/iconfig/mgr
cat messages.log
```
## 4. 在目标上安装其他 prometheus 导出程序
例如,prometheus 节点导出程序可显示各种硬件和内核相关的指标。
[节点导出程序文档](https://prometheus.io/docs/guides/node-exporter/)
通过请求(抓取)实例端点的指标,测试节点导出程序是否正常工作:
```swift
curl my_target_server_name:9100/metrics
```
您应该看到类似下面的信息:
```swift
mylaptop:~ mo$ my_target_server_name:9100/metrics | more
HELP go_gc_duration_seconds A summary of the GC invocation durations.
# TYPE go_gc_duration_seconds summary
go_gc_duration_seconds{quantile="0"} 4.8862e-05
go_gc_duration_seconds{quantile="0.25"} 7.5898e-05
go_gc_duration_seconds{quantile="0.5"} 9.2974e-05
go_gc_duration_seconds{quantile="0.75"} 0.000130664
go_gc_duration_seconds{quantile="1"} 0.000358762
go_gc_duration_seconds_sum 303.291715258
go_gc_duration_seconds_count 2.572586e+06
# HELP go_goroutines Number of goroutines that currently exist.
# TYPE go_goroutines gauge
go_goroutines 9
:
: many many metrics will be displayed
```
注意您可以对您的 IRIS 实例执行同样操作:
```swift
mylaptop:~ mo$ curl my_target_server_name:52776/api/monitor/metrics | more
iris_cpu_pct{id="AUXWD"} 0
iris_cpu_pct{id="CSPDMN"} 0
iris_cpu_pct{id="CSPSRV"} 0
iris_cpu_pct{id="ECPCliR"} 0
iris_cpu_pct{id="ECPCliW"} 0
iris_cpu_pct{id="ECPSrvR"} 0
iris_cpu_pct{id="ECPSrvW"} 0
:
: many many metrics will be displayed
```
## 5. 编辑配置文件以添加对新目标的抓取
例如,前一个技巧中的 node-exporter 实例。 配置文件将位于 SAM 的安装位置。 如下所示,可以看到 grafana 和 prometheus `yml` 配置文件。
```plaintext
[root@mysamserver sam-1.0.0.115-unix]# ls
config docker-compose.yml readme.txt start.sh stop.sh
[root@mysamserver sam-1.0.0.115-unix]# tree -x config
config
├── alertmanager
│ └── isc_alertmanager.yml
├── grafana
│ ├── dashboard.json
│ ├── dashboard-provider.yml
│ ├── datasource.yml
│ └── grafana.ini
├── nginx
│ └── nginx.conf
└── prometheus
├── isc_alert_rules.yml
└── isc_prometheus.yml
4 directories, 8 files
```
## 5.1 添加目标到 prometheus
以下示例是使用 SAM 中的配置 GUI 屏幕创建的 `isc_prometheus.yml` 文件。 该文件包含两个集群。 一个集群监视 sam 实例本身,另一个集群监视五个 IRIS 实例。
```yaml
alerting:
alertmanagers:
- static_configs:
- targets:
- alertmanager:9093
global:
evaluation_interval: 15s
scrape_interval: 15s
remote_read:
- url: http://iris:52773/api/sam/private/db/read
remote_write:
- url: http://iris:52773/api/sam/private/db/write
rule_files:
- ./isc_alert_rules.yml
scrape_configs:
- job_name: SAM
metrics_path: /api/monitor/metrics
scheme: http
static_configs:
- labels:
cluster: "1"
targets:
- mysaminstance.mycompany.com:8080
- labels:
cluster: "2"
targets:
- myiristarget1:52776
- myiristarget2:52776
- myiristarget3:52776
- myiristarget4:52776
- myiristarget5:52776
```
- 要添加对其他运行 node-exporter 的目标的抓取,请将以下内容添加到 `isc_prometheus.yml` 文件的底部。 注意 API `metrics_path` 与 IRIS 不同。
```yaml
alerting:
alertmanagers:
- static_configs:
- targets:
- alertmanager:9093
global:
evaluation_interval: 15s
scrape_interval: 15s
remote_read:
- url: http://iris:52773/api/sam/private/db/read
remote_write:
- url: http://iris:52773/api/sam/private/db/write
rule_files:
- ./isc_alert_rules.yml
scrape_configs:
- job_name: SAM
metrics_path: /api/monitor/metrics
scheme: http
static_configs:
- labels:
cluster: "1"
targets:
- iscsydsam.iscinternal.com:8080
- labels:
cluster: "2"
targets:
- myiristarget1:52776
- myiristarget2:52776
- myiristarget3:52776
- myiristarget4:52776
- myiristarget5:52776
- job_name: node_shard1
metrics_path: /metrics
scheme: http
static_configs:
- labels:
cluster: "2"
group: node
targets:
- myiristarget1:9100
- job_name: node_shard2
metrics_path: /metrics
scheme: http
static_configs:
- labels:
cluster: "2"
group: node
targets:
- myiristarget2:9100
- job_name: node_shard3
metrics_path: /metrics
scheme: http
static_configs:
- labels:
cluster: "2"
group: node
targets:
- myiristarget3:9100
- job_name: node_shard4
metrics_path: /metrics
scheme: http
static_configs:
- labels:
cluster: "2"
group: node
targets:
- myiristarget4:9100
- job_name: node_shard5
metrics_path: /metrics
scheme: http
static_configs:
- labels:
cluster: "2"
group: node
targets:
- myiristarget5:9100
```
- 然后使用提供的 docker-compose shell 脚本停止再启动 SAM:
```swift
./stop.sh
./start.sh
```
SAM 现在从您通过 GUI 添加的 IRIS 实例以及相同实例上的 node-exporter 中收集指标。
# 6. 增加 Prometheus 收集指标的天数
在 SAM 的第一版中,您可以在 GUI 中更改收集指标的天数。 但是,我在显示所有指标时遇到一个问题。 在我弄清楚发生了什么之前,我更改了 Prometheus 中的保留天数,否则 SAM 将收集数据,但是您在 Grafana 的 Prometheus 查询中看不到指标。
在文件 `docker-compose.yml` 中用来安装 SAM 的层,更改 Prometheus 启动时设置的保留天数,例如在 `prometheus` 部分中,更新 `storage.tsdb.retention.time` 参数以匹配所需的保留天数:
```swift
prometheus:
command:
- --web.enable-lifecycle
- --config.file=/config/isc_prometheus.yml
- --storage.tsdb.retention.time=30d
```
> 注意:在 SAM 的第一版中,最长保留天数为 30 天。 然后使用提供的 docker-compose shell 脚本停止再启动 SAM:
```swift
./stop.sh
./start.sh
```
## 7. 创建您自己的仪表板
您可以向现有仪表板添加面板,也可以创建新的仪表板以满足您的监视需求。 这是一个很大的主题,所以留到下一个帖子再说。 不过,这里先帮助您上手。
在 SAM 屏幕上使用 `View in Grafana`(在 Grafana 中查看)按钮切换到 Grafana。
![DraggedImage.png](https://res.craft.do/user/full/635e53bd-527a-1620-0e31-f8c3bdff1139/doc/CB3E6427-4D46-40C7-93DF-9E1FE801E814/C1AAEA2C-B8AF-4CF6-AB18-DD562971A9BC_2)
打开 Grafana 后,可以创建或编辑仪表板;
![DraggedImage-1.png](https://res.craft.do/user/full/635e53bd-527a-1620-0e31-f8c3bdff1139/doc/CB3E6427-4D46-40C7-93DF-9E1FE801E814/BC370FDF-308A-4917-9262-42AE286BDE8B_2)
网上有许多查询导出程序(如 node-exporter)的示例。
> 当可以显示 IRIS 系统指标(SAM 中的默认设置)、IRIS 应用程序指标(您需要将这些指标构建到应用程序中)以及其他指标(如 node-exporter 或由供应商创建的任何数量的指标)时,真正强大的功能才体现出来。 例如,[使用 SAM 和 cAdvisor 监视 Docker 容器](https://community.intersystems.com/post/monitor-docker-containers-using-sam-and-cadvisor)
文章
姚 鑫 · 六月 30, 2021
# 第二十三章 执行XSLT转换概述
XSLT(Extensible StyleSheet Language Transformations,可扩展样式表语言转换)是一种基于XML的语言,用于描述如何将给定的XML文档转换为另一个XML或其他“人类可读”的文档。可以使用`%XML.XSLT`和`%XML.XSLT2`包中的类来执行`XSLT 1.0`和`2.0`转换。
注意:使用的任何XML文档的XML声明都应该指明该文档的字符编码,并且文档应该按照声明的方式进行编码。如果未声明字符编码, IRIS将使用本书前面的“输入和输出的字符编码”中描述的默认值。如果这些默认值不正确,请修改XML声明,使其指定实际使用的字符集。
# 在IRIS中执行XSLT转换概述
IRIS提供两个XSLT处理器,每个处理器都有自己的API:
- `Xalan`处理器支持`XSLT 1.0`。`XML.XSLT`包为该处理器提供API。
- `Saxon`处理器支持`XSLT 2.0`。`%XML.XSLT2`程序包为该处理器提供API。
`XML.XSLT2` API通过到`XSLT 2.0`网关的连接向`Saxon`发送请求。网关允许多个连接。这意味着,例如,可以将两个独立的 IRIS进程连接到网关,每个进程都有自己的一组编译样式表,同时发送转换请求。
使用Saxon处理器,编译的样式表和`isc:Evaluate`缓存是特定于连接的;必须管理自己的连接才能利用这两个特性。如果打开连接并创建编译样式表或计算填充`isc:Evaluate`缓存的转换,则在该连接上计算的所有其他转换都将访问编译样式表和`isc:Evaluate`缓存条目。如果打开新连接,其他连接(及其编译的样式表和缓存)将被忽略。
这两个处理器的API相似,不同之处在于`%XML.XSLT2`中的方法使用另一个参数来指定要使用的网关连接。
要执行`XSLT`转换,请执行以下操作:
1. 如果使用的是`Saxon`处理器,请按照下一节所述配置`XSLT`网关服务器。或使用默认配置。
如果使用的是`Xalan`处理器,则不需要网关。
系统会在需要时自动启动网关。或者也可以手动启动它。
2. 如果使用的是`Saxon`处理器,则可以选择创建`%Net.Remote.Gateway`的实例,表示到`XSLT`网关的单个连接。
请注意,当使用`Saxon`处理器时,要利用已编译的样式表和`isc:Evaluate`缓存,这一步是必需的。
3. 可以选择创建已编译的样式表并将其加载到内存中。请参阅本章后面的“创建编译样式表”。如果使用的是`Saxon`处理器,请确保在创建编译后的样式表时指定网关参数。
如果打算重复使用同一样式表,则此步骤非常有用。然而,此步骤也会消耗内存。当不再需要编译的样式表时,请务必将其删除。
4. 调用适用API的转换方法之一。如果使用的是`Saxon`处理器,则在调用`Transform`方法时可以选择指定网关参数。
5. 可以选择调用其他转换方法。如果使用的是`Saxon`处理器,则在调用`Transform`方法时可以选择指定网关参数;这使能够使用相同的连接计算另一个转换。此转换将访问与此连接相关联的所有编译样式表和`isc:Evaluate`缓存条目。如果打开新连接,其他连接(及其编译的样式表和缓存)将被忽略。
Studio还提供了一个向导,可以使用该向导测试XSLT转换;本章稍后将对此进行介绍。
# 配置、启动和停止XSLT 2.0网关
当使用`Saxon`处理器(执行`XSLT 2.0`转换)时, IRIS使用`XSLT 2.0`网关(后者使用Java)。要配置此网关,请执行以下操作:
1. 在管理门户中,选择 System Administration > Configuration > Connectivity > XSLT 2.0 Gateway Server.
2. 选择Go。
![image](/sites/default/files/inline/images/1_49.png)
系统将显示XSLT网关服务器页面。
左侧区域显示配置详细信息,右侧区域显示最近的活动。
![image](/sites/default/files/inline/images/2_29.png)
3. 在左侧区域中,可以选择指定以下设置:
- Port Number -`XSLT 2.0`网关独占使用的TCP端口号。此端口号不得与服务器上的任何其他本地TCP端口冲突。
默认值为 IRIS SuperServer端口号加`3000`。如果此数字大于`65535`,则系统使用`54773`。
- Java Version - 使用的Java版本。
- Log File - 日志文件的路径名。如果忽略此设置,则不执行日志记录。如果指定了文件名但忽略了目录,则将日志文件写入系统管理器的目录。
- Java Home Directory -包含Java bin目录的目录路径。如果服务器上没有默认Java,或者如果想使用不同的Java,请指定此选项。
要查看默认Java,请在服务器上的Shell中执行以下命令:
```
java -version
```
- JVM Arguments - Java虚拟机要使用的任何其他参数。
此区域还显示`JAVA_HOME`环境变量的当前值。
请注意,在网关运行时,不能编辑这些值中的任何一个。
4. 如果已进行更改,请选择保存以保存更改。或选择重置以。
5. (可选)选择测试以测试更改。
在此页面上,还可以执行以下操作:
- 启动网关。要执行此操作,请选择右侧区域中的Start。
请注意, IRIS会在需要时自动启动网关。不需要手动启动网关。
- 关闭网关。要执行此操作,请选择右侧区域中的Stop(停止)。
# 重用XSLT网关服务器连接(XSLT 2.0)
如果使用的是`Saxon`处理器,InterSystems IRIS将使用之前配置的`XSLT 2.0`网关。为了与此网关通信,InterSystems IRIS在内部创建一个`XSLT`网关连接(`%Net.Remote.Gateway`的实例)。默认情况下,系统创建一个连接,将其用于转换,然后丢弃该连接。打开新连接会产生开销,因此为多个转换维护一个连接可提供最佳性能。此外,必须维护自己的连接,以便利用已编译的样式表和`isc:Evaluate`缓存。
要重用XSLT网关连接,请执行以下操作:
1. 调用`%XML.XSLT2.Transformer`的`StartGateway()`方法:
```
set status=##class(%XML.XSLT2.Transformer).StartGateway(.gateway)
```
此方法启动XSLT 2.0网关(如果它尚未运行),并返回`%Net.Remote.Gateway`的实例作为输出。请注意,该方法还返回状态。
在`%Net.Remote.Gateway`实例表示与网关的连接。
`StartGateway()`有一个可选的第二个参数`useSharedMemory`。如果此参数为真(缺省值),则与`localhost`或`127.0.0.1`的连接将使用共享内存(如果可能)。要强制连接仅使用`TCP/IP`,请将此参数设置为False。
2. 检查上一步返回的状态:
```java
if $$$ISERR(status) {
quit
}
```
3. 创建任何已编译的样式表。执行此操作时,请将网关参数指定为`%Net.Remote.GatewayInstance`的实例在步骤1中创建。
4. 根据需要调用`%XML.XSLT2.Transformer`的`Transform`方法(`TransformFile()`、`TransformFileWithCompiledXSL()`、`TransformStream()`和`TransformStreamWithCompiledXSL()`)。执行此操作时,请将网关参数指定为在步骤1中创建的`%Net.Remote.Gateway`的实例。
5. 如果不再需要给定的编译样式表,请在调用`%XML.XSLT2.CompiledStyleSheet`的`ReleaseFromServer()`方法:
```java
Set status=##class(%XML.XSLT2.CompiledStyleSheet).ReleaseFromServer(compiledStyleSheet,,gateway)
```
重要提示:当不再需要已编译的样式表时,请务必使用此方法。
6. 当不再需要XSLT网关连接时,调用`%XML.XSLT2.Transformer`的`StopGateway()`方法,并将网关连接作为参数传递:
```java
set status=##class(%XML.XSLT2.Transformer).StopGateway(gateway)
```
此方法丢弃连接并重置当前设备。它不会停止`XSLT 2.0`网关。
重要提示:当不再需要连接时,请务必使用此方法。
有关示例,请参见XSLT2中的`Example10()`方法。`Samples`命名空间中的`Examples`。
# 排除XSLT 2.0网关服务器连接故障
当XSLT 2.0网关打开时,InterSystems IRIS和网关服务器之间的连接可能会变得无效。例如,如果出现网络错误或在InterSystems IRIS连接到网关服务器后重新启动网关服务器,则连接可能无法正常关闭。因此,可能会遇到错误。
可以通过连续调用XSLT网关连接对象的`%LostConnectionCleanup()`方法和`%reconnect`方法,尝试将InterSystems IRIS重新连接到网关服务器。
如果希望在断开连接时自动重新连接到网关服务器,请将网关连接对象的`AttemptReconnect`属性设置为true。
# 创建编译的样式表
如果打算重复使用同一样式表,则可能需要编译该样式表以提高速度。请注意,此步骤会消耗内存。当不再需要编译的样式表时,请务必将其删除。
要创建编译的样式表,请执行以下操作:
- 如果使用的是`Xalan`处理器(对于`XSLT 1.0`),请使用`%XML.XSLT.CompiledStyleSheet`的以下类方法之一:
- `CreateFromFile()`
- `CreateFromStream()`
- 如果使用的是`Saxon`处理器(用于`XSLT 2.0`),请在使用`%XML.XSLT2.CompiledStyleSheet`的以下类方法之一:
- `CreateFromFile()`
- `CreateFromStream()`
另请注意,将需要创建一个XSLT网关连接;请参阅“重用XSLT网关服务器连接(`XSLT 2.0`)”。
对于所有这些方法,完整的参数列表按顺序如下:
1. source - 样式表。
对于`CreateFromFile()`,此参数是文件名。对于`CreateFromStream()`,此参数是一个流。
2. compiledStyleSheet - 编译后的样式表,作为输出参数返回。
这是样式表类(`%XML.XSLT.CompiledStyleSheet`或`%XL.XSLT2.CompiledStyleSheet`,视情况而定)的实例。
3. errorHandler - 编译样式表时使用的可选自定义错误处理程序。
对于这两个类中的方法,这是`%XML.XSLT.ErrorHandler`实例。
4. (仅适用于`%XML.XSLT2.CompiledStyleSheet`)网关-`%Net.Remote.Gateway`的实例
```
//将tXSL设置为等于适当流的OREF
Set tSC=##class(%XML.XSLT.CompiledStyleSheet).CreateFromStream(tXSL,.tCompiledStyleSheet)
If $$$ISERR(tSC) Quit
```
文章
Qiao Peng · 十月 9, 2023
英国国民医疗保健服务(NHS)简介
国民医疗保健服务(NHS)是英国的公共资助的医疗保健系统的总称,覆盖英格兰的、苏格兰和威尔士。它是世界上第二大单一付款人医疗保健系统,针对英国常住居民提供免费的、全面的卫生服务。这些卫生服务不仅是医疗服务,还包含社区护理服务、精神健康、临终关怀等。
NHS是最大的分级诊疗体系:先看全科医生或急诊,再由他们转诊到医院看专科医生、住院或者手术。它管理着9千万患者记录和6千5百万份病历;每天有100万的就诊、200万电子处方和75万电子转诊。
NHS有200万员工,是世界最大的、非军队的单一机构。一直被评为让英国人最自豪的英国机构,击败了皇室、武装部队和英国广播公司。
NHS面临的挑战和应对
作为政府买单的全国性医疗保健系统,提高治疗效果、提升效率、降低费用是NHS始终面临的挑战。
NHS广泛使用InterSystems的TrakCare作为电子病历系统以获得统一的、最新的患者视图;使用HealthShare作为医疗机构间健康信息共享和交换平台,合并和共享患者信息、治疗计划和临终愿望计划,让授权的医护人员查看患者完整、及时的护理记录小结;使用InterSystems IRIS医疗行业版支撑包括基于机器学习的辅助决策的创新应用,例如对阿尔茨海默氏症的早期发现与诊断。NHS还提供全国的电子处方服务 - 直接将电子处方发送到患者选择的药房,和电子转诊服务。
但NHS仍有很多纸质流程和众多的旧有系统,数字化程度和数据的互操作能力有限。例如NHS使用了21种不同的电子系统来记录患者的数据。这些系统之间不能很好地沟通,因此治疗患者的医生可能无法了解有效治疗患者所需的所有信息。约十分之一的就诊中,医院和全科医生无法获得患者之前的健康记录。“医院和全科医生通常没能在正确的时间、正确的地点获得正确患者的正确信息。这可能导致错误和事故,从而威胁患者的生命。“
确保信息使用者在正确的时间、正确的地点获得正确患者的正确信息,是有效决策所需的关键要素。需要获取患者信息的不仅有医生和护士,还包括患者自己。这就是战略性的互操作,它不仅是技术问题,更是一个社会问题。
在COVID-19大流行前,NHS为了实现这些目标,制定了数字化(digitise)、连接(connect)、转型(transform)的数字化转型战略:
将服务数字化:让医疗护理服务提供者和患者在需要时可以安全地访问信息。它承诺到2024年将整个NHS数字化。
将它们连接起来以支持服务集成:连接的健康和护理系统意味着数据可以在 IT 系统、医疗护理提供者和机构之间无缝流动。由此产生的信息洞察有助于根据人群的需求定制服务,实现更有针对性的护理并减少不必要的干预。
通过这些基础实现服务转型:数字技术的真正价值不是来自于将现有实践数字化,而是来自于使用它来彻底改变服务。要设计健康和社会护理服务,以使遭受健康不平等的人受益并其尽可能具有包容性,将确保对健康结果产生最大的积极影响。例如NHS的综合护理计划服务(Coordinate My Care),是一项临床服务,将被动的护理服务转变为计划性护理,将急诊和意外入院转变为离家更近的选择性、计划性、成本更低的护理,将患者被动参加转变为患者主动参与。
COVID-19为NHS带来了新的挑战 - 数字化需求的全面提速。自全球 COVID-19 大流行和国家封锁措施以来,卫生和社会护理提供者都采用数字技术作为护理渠道:虚拟会诊、视频会诊、虚拟COVID-19病房。数字化也已扩展到为患者家中提供 iPad,使他们能够远程进行测试,从而降低暴露于COVID-19的风险并为NHS临床医生节省时间。NHS也计划在未来五年内将面对面门诊预约减少多达三分之一。
所有这一切都对系统的互操作能力和基于互操作能力上的服务创新提出了很高的要求,不仅是功能和法规上的,也是响应速度上的 - 在满足法规和标准的同时快速交付的需求。而FHIR恰逢其时地为NHS的这些需求和数字化转型战略赋能。
NHS的FHIR案例
在英国,INTEROPen是一个开放合作组织,致力于加速制定医疗保健和社会保健领域互操作性的开放标准,建立数字信息无缝流动的健康和护理社区。它由NHS、行业供应商、标准化组织和个人组成, InterSystems 是INTEROPen的创始成员和供应商联席主席。INTEROPen定义并推动采用基于 HL7 FHIR 的开放互操作性标准,它基于FHIR R4建立了英国第一个UK Core的国家级Profile和一系列FHIR实施指南(Implementation Guide),并每年举办四到六场黑客马拉松,使成员组织的开发人员能够测试标准和 API,然后再使用这些标准和 API 来连接基于真实临床场景的系统。
NHS正借助INTEROPen,努力简化不同的标准和流程,让服务创新者获得他们需要的东西,以符合各种技术和临床要求,确保关键信息在正确的时间到达正确的人。
NHS最新的努力都基于FHIR标准和UK Core,并定义了一组开放式 FHIR API,用于所有全科医生系统。基于 FHIR 的互操作性帮助NHS简化和自动化流程,释放宝贵的资源来专注于患者护理。
在FHIR基础上,NHS已经实现了这些服务:
患者服务:
让患者自己就可以查询个人记录、药嘱再配、预约、使用电子转诊服务等。患者可以选择何时何地看专家,实施以来,降低了一半的患者预约爽约风险。电子处方服务将处方数据安全快速地传给患者选择的药房,每年为NHS节省2亿3千万英镑。
患者也可以通过苹果手机的Apple Health应用,使用FHIR API安全、私密地大规模访问他们个人的NHS健康信息。
事件通知:
FHIR 消息传递和 InterSystems 技术正在通过NHS网络推动临床事件通知。包括父母在内的用户可以订阅事件并接收每个患者的通知。事件管理系统接收 FHIR 消息、存储它们,并根据订阅偏好通知每个订阅者。事件类型包括疫苗接种、儿科发育里程碑或常规筛查检查等。
信息实时更新:
NHS救护车出诊时,除了出诊原因,通常医生对患者的情况一无所知。通过FHIR API,NHS从全科医生系统收集患者信息并提供完整的html版本的小结,让医生在救护车到达前就了解患者的诊断、当前用药、过敏、就诊历史等信息,帮助医生确定更好的处置决定,并评估是否需要住院治疗。
药物管理:
住院时协调用药是困难和耗时的,加上转录用药和过敏信息可能发生的错误,这带来巨大的患者安全风险。
同时,传统的药物清单概念,无论是医生开出的药物清单、药房分配的药物清单,还是患者说他们目前服用的药物清单,它们看起来都一样。而FHIR 引入了一种新的药物管理架构,它的药物模块包括 9 种不同的 FHIR 资源——结构化数据的自描述单元以及对其他资源或数据源的引用。它们允许在不同系统之间进行更有意义和有用的药物信息交换。
使用FHIR药物模块,通过FHIR API,NHS从全科医生系统收集药物和过敏信息:
使用UK Core的 “药物可编码概念”或“药物资源” 传输药物信息
使用UK Core的FHIR剂量语法IG(FHIR Dose Syntax Implementation Guidance)将每剂量的药物量转换为简单的编码量
使用 SNOMED CT 和 NHS的dm+d 字典代码传输药物和过敏/不耐受信息
并及时、准确地将当前用药直接列入InterSystems TrakCare电子病历的患者当前用药列表。对于未编码的药物和过敏数据,InterSystems TrakCare这些信息作为自由文本存储在患者记录中,并允许临床医生将其修正为结构化和编码数据输入 TrakCare。开药时,TrakCare 可视化规则会在有非结构化过敏记录时提醒开药者。
通过这些基于FHIR的药物管理,NHS帮助医生更好、更快地协调住院用药,降低用药错误(这是最常见的医疗错误类型)带来的患者安全风险。
护理平稳过渡:
当患者从医院到护理中心再回到家中继续康复或照料,从一个医生转到另一个医生时,不完整的信息导致治疗连续性不佳、患者安全风险、效率不足、不必要的患者再入院和患者教育失败。NHS颁布了基于FHIR的治疗文档传递标准,它是一个结构化的、编码的文档。当患者从医院、急诊科、门诊预约或择期手术出院时,它由急症医院提供,通过FHIR API发送给全科医生。全科医生直接在患者记录中就可以查看到这些患者信息,无需打开另外的文档查找和阅读,这种及时的信息共享有助于实现不间断的患者护理。
另外,NHS还将FHIR应用在术前评估、知情同意、管理高危慢阻肺等业务场景中。
NHS的经验和教训
NHS在借助FHIR推动战略互操作时给我们带来的经验和教训:
战略互操作不仅是技术问题,更是社会问题
借这个机会转变临床和护理流程、服务
合作
它需要借助合作产生的标准实现,要所有利益相关方一起参与 – 需求方拉动、提供方推动
确保参与方都充分理解需求和标准,并理解标准需要不断进化
临床模型 (需求)-> FHIR Profiles (设计) -> 实施指南 (实施)-> API(实施)
组织测试,用来检验标准
务实
关注在交付有用的事情上 – 它要足够好,但不需要完美,不要过分工程化
尽快试错
很多国家在采纳FHIR,但这个过程会比我们想象的长
不要过分扩展FHIR,先从最小规模的扩展开始
文章
Claire Zheng · 二月 1, 2021
Hi, 大家好!
我们在开发者社区上发布问题的目的是获得答案。
以下是一个非常简单的准则文档,介绍如何提出问题会获得回答。
当您发布问题时,您需要填写 3 个字段:标题、正文和组。 以及标签。
1. 标题
一个好的标题应该包含问题的简短描述,长度不应超过 80-90 个符号。
但是简短并不表示只有一个词。 以下这些就不是很好的问题标题:Cache、Ensemble、Peace、World。
好问题示例:
使用 SQL 查询列表属性
使用 Record Mapper 时如何忽略 CSV 文件上的Headers
在 Cache´SQL 中使用 $CASE 或 $SELECT 功能
标题中的字母应该大写吗? 按照 英语 的规则——是的!这肯定会提高问题的感知度。
2. 正文
正文应该包含英语或/和 Caché Objecsript、SQL、JS 或其他语言的问题描述。 使用 代码块 突出显示 Caché ObjectScript。
提供产品版本总是有帮助的(在终端中输入 $zversion)。
正文中应该只有一个问题。 如果有两个问题,请发布两个不同的问题。
3. 组
组是必选标签,有助于将您的问题归类到一个 InterSystems 产品(Caché、Ensemble、HealthShare)、技术(DeepSee、iKnow)或服务(在线学习、WRC)。
4. 标签
使用标签可邀请(订阅了不同标签的)专家关注您的问题。 在这里,您可以选择关于开发、测试、变更管理、部署和环境的不同标签。
好问题通常很快就会得到回答。 您可以通过“回答”计数器上的绿色前景注意到已回答的问题。
一定要 将回答标记为已接受(将问题标记为已解决) ,当然前提是回答适合您。
当然,这不是如何提出好问题的完整建议列表。 请在本帖中发表您的意见和想法。
文章
姚 鑫 · 六月 6, 2021
# Caché 网络实用工具
# [第一章 发送HTTP请求☆☆☆☆☆](https://yaoxin.blog.csdn.net/article/details/117108190)
# [第二章 设置和获取HTTP标头☆☆☆☆☆](https://yaoxin.blog.csdn.net/article/details/117148255)
# [第三章 发送HTTP请求☆☆☆☆☆](https://yaoxin.blog.csdn.net/article/details/117195938)
# [第四章 收发电子邮件☆](https://yaoxin.blog.csdn.net/article/details/117214514)
# [第五章 向邮件添加附件☆](https://yaoxin.blog.csdn.net/article/details/117248548)
# [第六章 从POP3服务器提取电子邮件☆](https://yaoxin.blog.csdn.net/article/details/117278414)
# [第七章 从POP3服务器提取电子邮件☆](https://yaoxin.blog.csdn.net/article/details/117320147)
# [第八章 处理收到的电子邮件☆](https://yaoxin.blog.csdn.net/article/details/117350781)
# [第九章 创建、编写和阅读MIME邮件☆](https://yaoxin.blog.csdn.net/article/details/117378600)
# [第十章 使用FTP☆☆☆☆☆](https://yaoxin.blog.csdn.net/article/details/117394438)
# [第十一章 发送和接收IBM WebSphere MQ消息☆](https://yaoxin.blog.csdn.net/article/details/117409322)
# [第十二章 IBM WebSphere MQ检索邮件☆](https://yaoxin.blog.csdn.net/article/details/117435132)
# [第十三章 使用SSH☆](https://yaoxin.blog.csdn.net/article/details/117459391)
# [第十四章 其他InterSystems %Net工具☆☆☆](https://yaoxin.blog.csdn.net/article/details/117508484)
# [第十五章 Caché WebSocket☆☆☆](https://yaoxin.blog.csdn.net/article/details/117548341)
# 前言
手册帮助程序员使用%Net包中的一些关键类,这些类为许多有用的Internet协议提供了易于使用的接口。因为这个包的类文档相当广泛,所以本手册提供了一个快速、有条理的概述,而不是深入研究每个参数、属性和方法。熟悉本手册中提到的协议和第三方工具。
# 预告
下一期系列将用一个月的时间连载,**《Caché XML》**,敬请期待。
# 交流群
- QQ群号:410039091
- 笔者QQ:454115408
- 公众号:技术理科直男
- [intersys版主:姚鑫](https://cn.community.intersystems.com/user/236891/posts)
![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f9VqwzNP-1608850948003)(3E1D939266954ED48BDAEA9B8086B11E)\]](https://img-blog.csdnimg.cn/20201225070433434.png)
# 大型免费课程,进群410039091获取课程目录
- 适合所有阶段程序员,总有一款你遗漏的知识点!
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210606224558577.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3lhb3hpbjUyMTEyMw==,size_16,color_FFFFFF,t_70#pic_center)
公告
jieliang liu · 三月 3, 2022
欢迎来到2月22日的社区新闻发布!
我们很高兴为InterSystems的开发者介绍我们全新的社区活动日历:
🎯 https://community.intersystems.com/events
在这个日历中,你将看到特区活动的历史。了解现在或即将发生的活动,查看过去的活动,并观看社区的网络研讨会和聚会的录音。
让我们仔细看看如何使用它。
要进入DC日历,请点击 "活动 "顶部菜单,进入 "活动日历 “部分:
在这个日历中,你会发现现有的和过去的活动,这些活动可以被分为不同的类别:
所有活动
网络研讨会
开发者聚会
比赛
通过点击 "预览模式 "中的事件,你将看到它的公告:
随意使用 "列表模式",它显示事件预告,并有一个选项可以将任何可用的事件添加到你的日历中:
你也可以在右边的小日历中选择任何日期,了解当天有什么活动安排或发生:
此外,你可以通过点击 "新事件 "按钮创建你自己的事件。你将被自动转到事件创建页面。
❗️ 将 "Event"标签添加到帖子中,将打开用于创建活动的特殊字段。
当你在字段中填写了活动名称、注册链接和时间后,你的活动将自动在主页面的 "活动 "块中突出显示。
此外,在你的活动公告中,你会看到:– 带有注册链接的特殊块– 用于快速添加事件到你的日历的按钮
欢迎添加更多关于你的活动的细节,添加简短的描述/直接链接加入/位置。
希望你喜欢我们的更新!
您可以将改进要求和错误报告提交到 DC GitHub. 或者在本帖的评论中发表你的建议。
请继续关注我们的新消息!
文章
Vivi Zhu · 五月 29, 2022
北京协和医院现公开招聘信息类技术岗位。有关事项公告如下:岗位1:运维工程师任职要求:1.年龄30岁以下,本科及以上学历,计算机相关专业;2.熟悉计算机软硬件技术,熟练排除各种软硬件的故障;有基本的网络知识,了解DNS、DHCP原理,熟练使用Ping、tracert等简单命令;3.有2年以上桌面运维工作经验者优先。
岗位2:数据库管理员任职要求:1. 本科及以上学历,计算机相关专业;2. 精通InterSystems Caché数据库,精通MySQL,SQL Server,熟悉Oracle,精通SQL脚本编写;有丰富数据库管理、运维调优经验;3. 5年以上数据库运维管理经验;4. 有医疗行业经验优先。
岗位3:开发工程师任职要求:1. 本科及以上学历,计算机及相关专业,有2年及以上JAVA WEB软件实际开发工作经验,有JVM调优经验者优先;2. 熟悉SSM和SSH框架;有SpringBoot或者SpringCloud实际开发经验;3. 熟悉html5,css,js 等前端开发技术;对jquery、vue等相关技术熟悉;熟悉websocket等相关技术;4. 熟练使用MySQL,SQL Server,熟悉Oracle,有一定的SQL优化经验;5. 熟练使用各种集成开发环境,Eclipse,Idea,SVN,GIT等,熟悉Linux操作系统。
招聘程序(一)个人应聘2022年6月27日24点前登录北京协和医院官网(学术版)招聘栏注册申请。(二)组织面试在资格审查的基础上按1:3的比例确定面试人选,根据综合成绩确定拟录人选。(三)体检考察对拟录人选进行体检和考察。(四)签订协议体检及考察合格人员签订协议。
官方招聘链接为 https://jobs.pumch.cn/JobManage/WebShowJobDetail.aspx?JobId=bf9dcde8-a3de-4fab-805e-f2582255056d
文章
Michael Lei · 六月 14, 2023
本文是 SqlDatabaseChain 的简单快速入门(我所做的)。
希望大家会感兴趣。
非常感谢:
sqlalchemy-iris 作者@Dmitry Maslennikov
您的项目使我的试验变得可能。
文章脚本使用 openai API,因此请注意不要在外部共享您不打算共享的表信息和记录。
如果需要,可以插入本地模型。
创建一个新的虚拟环境
mkdir chainsql
cd chainsql
python -m venv .
scripts\activate
pip install langchain
pip install wget
# Need to connect to IRIS so installing a fresh python driver
python -c "import wget;url='https://raw.githubusercontent.com/intersystems-community/iris-driver-distribution/main/DB-API/intersystems_irispython-3.2.0-py3-none-any.whl';wget.download(url)"
# And for more magic
pip install sqlalchemy-iris
pip install openai
set OPENAI_API_KEY=[ Your OpenAI Key ]
python
初始测试
from langchain import OpenAI, SQLDatabase, SQLDatabaseChain
db = SQLDatabase.from_uri("iris://superuser:******@localhost:51775/USER")
llm = OpenAI(temperature=0, verbose=True)
db_chain = SQLDatabaseChain.from_llm(llm, db, verbose=True)
db_chain.run("How many Tables are there")
错误结果
sqlalchemy.exc.DatabaseError: (intersystems_iris.dbapi._DBAPI.DatabaseError) [SQLCODE: <-25>:<Input encountered after end of query>]
[Location: <Prepare>]
[%msg: < Input (;) encountered after end of query^SELECT COUNT ( * ) FROM information_schema . tables WHERE table_schema = :%qpar(1) ;>]
[SQL: SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public';]
(Background on this error at: https://sqlalche.me/e/20/4xp6)
←[32;1m←[1;3mSELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'public';←[0m>>>
开发者之间的对话
IRIS 不喜欢以分号结尾的 SQL 查询。
现在做什么? ?
想法:我告诉 LangChain 帮我修理SQL如何
太酷了,我们开工吧 !!
测试二
from langchain import OpenAI, SQLDatabase, SQLDatabaseChain
from langchain.prompts.prompt import PromptTemplate
_DEFAULT_TEMPLATE = """Given an input question, first create a syntactically correct {dialect} query to run, then look at the results of the query and return the answer.
Use the following format:
Question: "Question here"
SQLQuery: "SQL Query to run"
SQLResult: "Result of the SQLQuery"
Answer: "Final answer here"
The SQL query should NOT end with semi-colon
Question: {input}"""
PROMPT = PromptTemplate(
input_variables=["input", "dialect"], template=_DEFAULT_TEMPLATE
)
db = SQLDatabase.from_uri("iris://superuser:******@localhost:51775/USER") llm = OpenAI(temperature=0, verbose=True)
llm = OpenAI(temperature=0, verbose=True)
db_chain = SQLDatabaseChain(llm=llm, database=db, prompt=PROMPT, verbose=True)
db_chain.run("How many Tables are there")
结果二
SQLQuery:←[32;1m←[1;3mSELECT COUNT(*) FROM information_schema.tables←[0m
SQLResult: ←[33;1m←[1;3m[(499,)]←[0m
Answer:←[32;1m←[1;3mThere are 499 tables.←[0m
←[1m> Finished chain.←[0m
'There are 499 tables.'
我就说很快吧
参考资料:
https://walkingtree.tech/natural-language-to-query-your-sql-database-using-langchain-powered-by-llms/
https://python.langchain.com/en/latest/modules/chains/examples/sqlite.html#sqldatabasesequentialchain
https://python.langchain.com/en/latest/modules/agents/plan_and_execute.html
文章
姚 鑫 · 八月 14, 2021
# 第101章 属性关键字 - InitialExpression
指定此属性的初始值。
# 用法
要指定此属性的初始值,请使用以下语法:
```java
Property name As classname [ InitialExpression = initialexpression ];
```
其中,`initialexpression`是用大括号括起来的常量或ObjectScript表达式。
# 详解
此关键字指定属性的初始值。该值是在创建新实例时由类的`%New()`方法分配的。(如果属性是瞬态的的,则其初始值由创建实例时`%New()`调用的代码或实例从磁盘加载到内存时`%OpenId()`调用的代码确定。)
初始表达式的值必须适合给定的属性类型。
表达式可以是任意复杂的,有以下限制:
- 初始表达式不能引用其他属性。也就是说,诸如{`..therPropertyname`}这样的表达式无效。
- 初始表达式不能实例化对象,也不能包括对象引用。
- 初始表达式不能调用实例方法(只能调用类方法)。
- 必须在ObjectScript中指定初始表达式。
- 表达式执行的代码不应报告错误。InterSystems IRIS不提供处理表达式返回的错误的方法。
- 如果表达式执行的代码导致发生其他处理,则InterSystems IRIS不提供处理该处理结果的方法。
子类继承`InitialExpression`关键字的值并可以重写它。
# 默认
`InitialExpression`关键字的默认值为`NULL`。
# 示例
下面显示了几个使用ObjectScript表达式的示例:
```java
Property DateTime As %Date [ InitialExpression = {$zdateh("1966-10-28",3)} ];
Property MyString As %String [ InitialExpression = {$char(0)} ];
/// 此参数使用参数值进行初始化
Property MyProp As %String [ InitialExpression = {..#MYPARM} ];
/// 这是由一个类方法初始化的
Property MyProp2 As %Numeric [ InitialExpression = {..Initialize()} ];
```
# 第102章 属性关键字 - Internal
指定此属性定义是否为内部定义(不显示在类文档中)。
# 用法
要指定此属性为内部属性,请使用以下语法:
```java
Property propertyname As classname [ Internal ];
```
否则,请省略此关键字或将该词放在该关键字之前。
# 详解
类文档中不显示内部类成员。如果希望用户看到某个类,但不能看到其所有成员,则此关键字非常有用。
# 默认
如果省略此关键字,则此属性将显示在类文档中。
# 第103章 属性关键字 - Inverse
指定此关系的反面。关系属性需要。不用于其他属性。
# 用法
要在相关类中指定与该关系属性相反的关系属性,请使用以下语法:
```java
Relationship Chapters As Chapter [ Cardinality = cardinality; Inverse = inverse ];
```
其中,`Inverse`是相关类中属性的名称。
# 详解
此关键字指定关系的反向方的名称,即相关类中对应关系属性的名称。反向属性必须存在于相关类中,并且具有正确的基数值。
关系属性需要`Inverse`关键字。非关系属性会忽略它。
# 默认
没有默认值。定义关系时,必须指定逆序关键字。
# 示例
```java
Relationship Chapters As Chapter [ Cardinality = many; inverse = Book ];
```
# 第104章 属性关键字 - MultiDimensional
指定此属性具有多维数组的特征。
# 用法
要指定此属性具有多维数组的特征,请使用以下语法:
```java
Property Data [ Multidimensional ];
```
否则,省略此关键字或将单词Not放在关键字的前面。
# 详解
多维属性不同于其他属性,如下所示:
- IRIS不为其提供属性方法。
- 当对象被验证或保存时,它被忽略。
- 它不会保存到磁盘,除非应用程序包含专门保存它的代码。也就是说,属性也是自动瞬态的。
- 它不能暴露给Java或其他客户端。
- 它不能存储在或通过SQL表公开。
多维属性很少见,但它提供了一种有用的方法来临时包含关于对象状态的信息。
# 默认
如果省略此关键字,则属性不是多维的。
文章
Michael Lei · 二月 9, 2023
嗨,大家好
在本文中,我列出了 5 个有用的 SQL 函数,并附有解释和查询示例👇🏻这5个功能是
COALESCE合并
RANK排序
DENSE_RANK密集排序
ROW_NUMBER行号
SUM()获取运行总计的函数
那么让我们从 COALESCE 函数开始
#合并
COALESCE 函数按从左到右的顺序计算表达式列表,并返回第一个非 NULL 表达式的值。如果所有表达式的计算结果为 NULL,则返回 NULL。
以下语句将首先返回非空值,即“intersystems”
SELECT COALESCE ( NULL , NULL , NULL , 'intersystems' , NULL , 'sql' )
让我们创建下表以获取更多示例
CREATE TABLE EXPENSES( TDATE DATE NOT NULL , EXPENSE1 NUMBER NULL , EXPENSE2 NUMBER NULL , EXPENSE3 NUMBER NULL , TTYPE CHAR ( 30 ) NULL )
现在让我们插入一些虚拟数据来测试我们的功能
INSERT INTO sqluser.expenses (tdate, expense1,expense2,expense3,ttype ) SELECT {d '2023-01-01' }, 500 , 400 , NULL , 'Present' UNION ALL SELECT {d '2023-01-01' }, NULL , 50 , 30 , 'SuperMarket' UNION ALL SELECT {d '2023-01-01' }, NULL , NULL , 30 , 'Clothes' UNION ALL SELECT {d '2023-01-02' }, NULL , 50 , 30 , 'Present' UNION ALL SELECT {d '2023-01-02' }, 300 , 500 , NULL , 'SuperMarket' UNION ALL SELECT {d '2023-01-02' }, NULL , 400 , NULL , 'Clothes' UNION ALL SELECT {d '2023-01-03' }, NULL , NULL , 350 , 'Present' UNION ALL SELECT {d '2023-01-03' }, 500 , NULL , NULL , 'SuperMarket' UNION ALL SELECT {d '2023-01-04' }, 200 , 100 , NULL , 'Clothes' UNION ALL SELECT {d '2023-01-06' }, NULL , NULL , 100 , 'SuperMarket' UNION ALL SELECT {d '2023-01-06' }, NULL , 100 , NULL , 'Clothes'
选择数据
现在通过使用 COALESCE 函数,我们将首先从 expense1、expense2 和 expense 3 列中检索非 NULL 值
SELECT TDATE, COALESCE (EXPENSE1,EXPENSE2,EXPENSE3), TTYPE FROM sqluser.expenses ORDER BY 2
#RANK vs DENSE_RANK vs ROW_NUMBER 函数
RANK() — 为同一窗口框架内的每一行分配一个排序整数,从 1 开始。如果多行包含相同的窗口函数字段值,则排序整数可以包含重复值。
ROW_NUMBER() — 为同一窗口框架内的每一行分配一个唯一的顺序整数,从 1 开始。如果多行包含相同的窗口函数字段值,则每一行都分配一个唯一的顺序整数。
DENSE_RANK() 离开 重复排名后没有间隙。
在 SQL 中,您可以通过多种方式为行分配排名,我们将通过示例深入探讨。再次考虑与之前相同的示例,但现在我们想知道最高费用是多少。
我们想知道我在哪里花的钱最多。有不同的方法可以做到这一点。我们可以使用所有 ROW_NUMBER() , RANK() 和 DENSE_RANK() 三个函数 。我们将使用所有三个函数对上一个表进行排序,并使用以下查询查看它们之间的主要区别是什么:
下面是我们的查询:
这三个功能之间的主要区别在于它们处理相同值的方式。我们将进一步深入探讨它们的差异:
RANK()----从 1 开始为每一行返回一个唯一的数字。当数值相等时,如果没有定义第二个条件,它会任意分配一个数字。
ROW_NUMBER() -----从1开始为每一行返回一个唯一的数字,除非数值相同,否则它将分配相同的数字。同样,重复的排名后会有空格。
DENSE_RANK()----- 重复排名后不留空格。
#计算运行总计
运行总计可能是最有用的窗口函数之一,尤其是当您想要可视化增长时。使用SUM()的窗口函数,我们可以计算累积聚合。
为此,我们只需要使用聚合器SUM()对变量求和,但使用 TDATE 列对该函数进行排序。
您可以观察到相应的查询如下:
正如您在上表中看到的那样,现在我们有了随着日期过去所花金额的累计汇总。
结论
SQL 很棒。上面使用的函数在处理数据分析、数据科学和任何其他与数据相关的领域时可能很有用。
这就是为什么我们应该注意不断提高 SQL 技能的原因。
谢谢
文章
Michael Lei · 五月 1, 2022
临床研究必须与健康数据相连
就在不久以前,临床科研人员还需要依靠三联的纸质NCR表格,手工收集从堆积如山的手写电子病历中提炼出来的病人数据。从又大又重的《医师案头参考》(PDR)撕下几页,通过传真机发送给FDA,用于药物安全报告。业内专业人士接受了大量的培训,以确保数据经过源文件验证、双键处理,并在经过看似无休止的查询以纠正错误之后,保证其符合目的。
值得庆幸的是,随着电子健康档案的广泛采用,健康数据的数字化,这一过程得到了极大的改善。但是,鉴于临床研究进展缓慢,特别是精美的Excel表格仍由人工数据摘要完成,该领域早该有更多的技术变革,特别是围绕释放医疗互操作性的全部好处。如果我们能做到这一点,生命科学公司将有机会利用宝贵的健康数据来确保病人的安全,优化新药的疗效,并使临床开发过程更加高效,减少错误。
我们可能会比你想象的更快地将临床研究与健康数据联系起来。为什么?火神计划(Project Vulcan)正在进行中。这个项目组是最近在HL7的FHIR加速器项目中创建的,它已经召集了来自医疗、技术和生命科学领域的30多个利益相关的组织个和机构,利用FHIR这个医疗专用互操作性标准来进行临床和转化研究。自从我们在去年年初加入后,我们高兴的看到火神计划成员制定的早期想法越来越接近于功能现实。
但是,医疗互操作性究竟如何能使同时用药跟踪(在同一时间段内给予两种或多种药物)或不良事件报告(捕捉可能与药物有关的疾病)以及其他临床研究领域受益?这些答案让我们看到了未来。
互操作性彻底改变了不良事件报告
每个新药的批准都是从安全开始的。如果研究人员不能完成临床试验的第一和第二阶段,他们甚至没有机会在更大的人群中研究其药物的疗效。但要证明一种治疗方法是安全的,这就提出了严峻的挑战。
几十年来,业内人士已经知道,一些不良事件在临床试验中被忽略了。比方说,一个研究对象在其心脏病专家的照料下测试一种新的心脏候选药物时,出现了皮疹并去看皮肤科医生。一个月后,当该受试者来到他们的下一次研究访问时,他们可能忘记告知研究团队他们最近的诊断--由正在测试的研究药物引起的新皮疹。
现在,太多时候,故事就在这里结束。这条信息--以及与之相关的、可能说明药物安全性的所有信息--已经消失。其他真实世界的数据也是如此,比如病人服用的额外药物,但由未参与研究的护理团队成员开出。或者仅仅是网络外的访问和程序。
然而,如果火神计划成功,研究人员将有更好的机会通过参与者的电子病历健康档案和临床研究数据记录之间的联系来捕捉这些关键信息。
基于FHIR的互操作性还可以简化不良事件报告,使患者的完整快照可以向关键利益相关者提供重要数据。任何人--患者、研究人员或监管机构--都不会再担心出现问题,而这些问题本可以通过与真实世界的数据建立可靠的联系而轻松避免。
互操作性支持表型数据共享Phenopackets(开放的可计算的生物信息Phenopackets.org)和临床实验方案日程
除了电子病历数据可以为临床试验提供信息外,火神项目的目标之一是,希望借助于FHIR,临床试验中收集的数据可以被更广泛地访问, 而且可以用于采取行动。全球基因组学与健康联盟(GA4GH)的表型数据交换标准有望使业界分享脱敏后(去掉身份识别)的病例级病人信息,以用于登记册、知识库出版物和期刊。
任何从事临床试验的人都知道,尽管对实现研究目标至关重要,但临床试验的分步指南,很容易出现疏忽和偏离计划的情况。主要的问题是什么?就是人为失误。但通过 "火神计划",基于FHIR的分步指南活动安排表很快就能实现调度自动化,减少对手工数据输入的需求,并提高研究程序的一致性。
我们已准备好将FHIR引入临床研究
FHIR已经在推进互操作性和消除障碍。在InterSystems,我们每天都能看到FHIR对互操作性的影响,无论是通过创建用于临床决策支持的移动端APP,还是通过医院不同部门和医疗机构之间的数据无缝流动。这就是我们将FHIR纳入我们的技术栈的原因。
当火神项目实现其目标时,InterSystems将准备好立即为临床研究带来快速、无缝的数据交换。我们没有任何理由推迟更安全、更有效的药物的到来。
作者是:InterSystems公司生命科学顾问Matthew Stannard
原文--https://www.intersystems.com/pulse-blog/unlocking-benefits-of-healthcare-interoperability
文章
姚 鑫 · 八月 7, 2021
# 第七十三章 方法关键字 - Requires
指定用户或进程调用此方法必须拥有的权限列表。
# 用法
要指定此方法应限于具有指定权限的用户或进程,请使用以下语法:
```java
Method name(formal_spec) As returnclass [ Requires = privilegelist ]
{ //implementation }
```
其中,`privilegelist` 要么是单个特权,要么是用引号括起来的以逗号分隔的特权列表。
每个权限都采用`resource:permission`的形式,其中`permission`是`Use`、`Read`或`Write`(或单字母缩写`U`、`R`或`W`)。
若要为一个资源`resource`指定多个权限,请使用单字母缩写。
# 详情
用户或进程必须拥有权限列表中的所有权限才能调用该方法。
调用没有指定权限的方法会导致``错误。
如果方法从超类继承了`Requires`关键字,则可以通过设置关键字的新值将其添加到所需特权的列表中。
不能以这种方式删除所需的特权。
# 默认
如果忽略此关键字,则调用此方法不需要特殊权限。
# 示例
下面的方法需要对`Sales`数据库的读权限和对`Marketing`数据库的写权限。
(注意,如果一个数据库有写权限,它会自动有读权限。)
```java
ClassMethod UpdateTotalSales() [ Requires = "%DB_SALES: Read, %DB_MARKETING: Write" ]
{
set newSales = ^["SALES"]Orders
set totalSales = ^["MARKETING"]Orders
set totalSales = totalSales + newSales
set ^["MARKETING"]Orders = totalSales
}
```
若要为一个资源指定多个权限,请使用单字母缩写。
以下两种方法在功能上是等价的:
```java
ClassMethod TestMethod() [ Requires = "MyResource: RW" ]
{
write "You have permission to run this method"
}
ClassMethod TestMethodTwo() [ Requires = "MyResource: Read, MyResource: Write" ]
{
write "You have permission to run this method"
}
```
# 第七十四章 方法关键字 - ReturnResultsets
指定此方法是否返回结果集(以便`ODBC`和`JDBC`客户机能够检索它们)。
# 用法
要指定该方法返回至少一个结果集,请使用以下语法:
```java
ClassMethod name(formal_spec) As returnclass [ ReturnResultsets, SqlName = CustomSets, SqlProc ]
{ //implementation }
```
否则,忽略此关键字或将单词`Not`紧接在关键字之前。
# 详解
此关键字指定该方法至少返回一个结果集。如果方法可能返回一个或多个结果集,则将此关键字设置为`true`。如果没有,`xDBC`客户端将无法检索结果集。
# 默认
如果省略此关键字,`xDBC`客户端将无法检索结果集。
# 第七十五章 方法关键字 - ServerOnly
指定此方法是否将被投影到Java客户端。
# 用法
将方法投影到`Java`客户端,请使用以下语法:
```java
Method name(formal_spec) As returnclass [ ServerOnly=n ]
{ //implementation }
```
其中`n`为下列其中之一:
- `0`表示该方法可以映射。
- `1`表示该方法不会被映射。
# 详解
该关键字指定方法不会被投影到`Java`客户机。
# 提示
要查看类的哪些方法是`server-only`的,请在终端中使用以下实用程序:
```java
do dumpMethods^%occLGUtil("Sample.Person")
```
参数是完全限定类名。
该实用程序生成一个报告,该报告指出关于每个方法的基本信息:该方法是否为存根,该方法是否仅为服务器,以及(如果该方法是从某个属性派生的)派生该方法的属性。
# 默认
如果忽略这个关键字,这个方法如果是存根方法就不会被投影(但是如果不是存根方法就会被投影)。
```java
DHC-APP>do dumpMethods^%occLGUtil("Sample.Person")
Method=%%OIDGet UseStub=0 serveronly=1
Method=%%OIDIsValid UseStub=1 serveronly=0 PropName=%%OID MethodName=IsValid
Method=%%OIDSet UseStub=1 serveronly=1 PropName=%%OID MethodName=Set
Method=%1Check UseStub=0 serveronly=1
Method=%AcquireLock UseStub=0 serveronly=1
Method=%AddJrnObjToSyncSet UseStub=0 serveronly=1
Method=%AddToSaveSet UseStub=0 serveronly=1
```
# 第七十六章 方法关键字 - SoapAction
指定当通过HTTP将此方法作为`web方法`调用时,要在`HTTP`头中使用的`SOAP`操作。仅适用于定义为`web服务`或`web客户端`的类。
# 用法
要指定将此方法用作`web方法`时在HTTP头中使用的`SOAP`操作,请使用以下语法:
```java
Method name(formal_spec) As returnclass [ WebMethod, SoapAction = soapaction ]
{ //implementation }
```
其中`soapaction`是下列之一:
- `“[default]”—SOAP`操作的默认值,即`NAMESPACE/Package.Class.Method`
- `"customValue"` -使用`customValue`作为`SOAP`操作。
该值应该是标识`SOAP`请求意图的`URI`。
如果指定了一个自定义的值,它必须在`web服务`的每个`web方法`中是唯一的,或者你必须为每个`web方法`指定`SoapRequestMessage`关键字(并且为该关键字使用唯一的值)。
- "" -使用空值作为`SOAP`操作。这种情况很少见。
# 详情
`web方法`的`SOAP`动作通常用于路由请求`SOAP消息`。
例如,防火墙可以使用它来适当地过滤`SOAP请求消息`。
InterSystems IRIS `web服务`使用`SOAP操作`(与消息本身结合)来确定如何处理请求消息。
该关键字允许指定在作为`web方法`调用此方法时使用的HTTP `SOAP`动作。
对于`SOAP 1.1`, `SOAP`动作包含在`SOAPAction HTTP`报头中。
对于`SOAP 1.2`,它包含在`Content-Type` HTTP报头中。
# 默认
如果忽略`SoapAction`关键字,`SOAP`动作的形式如下:
```java
NAMESPACE/Package.Class.Method
```
其中`NAMESPACE`是`web服务`的`NAMESPACE`参数的值,`Package.Class`是`web服务`类的名称,`Method`是`web方法`的名称。
# WSDL的关系
`SoapAction`关键字影响`web服务`的`WSDL`中`的`部分。
例如,以下web方法:
```java
Method Add(a as %Numeric,b as %Numeric) As %Numeric [ SoapAction = MySoapAction,WebMethod ]
{
Quit a + b
}
```
对于这个`web服务`,`WSDL`的``部分如下所示:
```xml
```
默认情况下,如果方法没有指定`SoapAction`关键字,``元素可能会像下面这样:
```xml
```
如果使用`SOAP`向导从`WSDL`生成 `web服务`服务或客户端,将此关键字设置为适合于该`WSDL`的关键字。
# 对消息的影响
对于前面显示的`web方法`,`web服务`期望收到以下形式的请求消息(对于SOAP 1.1):
```xml
POST /csp/gsop/ROBJDemo.BasicWS.cls HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; InterSystems IRIS;)
Host: localhost:8080
Connection: Close
Accept-Encoding: gzip
SOAPAction: MySoapAction
Content-Length: 379
Content-Type: text/xml; charset=UTF-8
...
```
默认情况下,如果方法没有指定`SoapAction`关键字,`SoapAction`行可能会像下面这样:
```xml
SOAPAction: http://www.mynamespace.org/ROBJDemo.BasicWS.Add
```
注意,对于`SOAP 1.2`,细节略有不同。
在这种情况下,`web服务`期望收到如下形式的请求消息:
```xml
POST /csp/gsop/ROBJDemo.BasicWS.cls HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; InterSystems IRIS;)
Host: localhost:8080
Connection: Close
Accept-Encoding: gzip
Content-Length: 377
Content-Type: application/soap+xml; charset=UTF-8; action="MySoapAction"
...
```
文章
姚 鑫 · 三月 9, 2021
# 第六章 SQL定义和使用视图
视图是一种虚拟表,由执行时通过`SELECT`语句或几个`SELECT`语句的`UNION`从一个或多个物理表中检索到的数据组成。 `SELECT`可以通过指定表或其他视图的任意组合来访问数据。因此,存储了视图的视图提供了物理表的所有灵活性和安全性特权。
InterSystemsIRIS®数据平台上的InterSystems SQL支持在视图上定义和执行查询的功能。
注意:不能对以只读方式安装的数据库中存储的数据创建视图。
无法在通过ODBC或JDBC网关连接链接的`Informix`表中存储的数据上创建视图。这是因为InterSystems IRIS查询转换对这种类型的查询使用FROM子句中的子查询。 `Informix`不支持`FROM`子句子查询。
# 创建一个视图
可以通过几种方式定义视图:
- 使用SQL `CREATE VIEW`命令(在DDL脚本中或通过JDBC或ODBC)。
- 使用管理门户的“创建视图”界面。
视图名称:不合格的视图名称是一个简单的标识符:`MyView`。合格的视图名称由两个简单的标识符组成,即模式名称和视图名称,以句点分隔:`MySchema.MyView`。视图名称和表名称遵循相同的命名约定,并对不合格的名称执行相同的架构名称解析。同一模式中的视图和表不能具有相同的名称。
可以使用`$SYSTEM.SQL.ViewExists()`方法确定视图名称是否已存在。此方法还返回投影视图的类名称。可以使用`$SYSTEM.SQL.TableExists()`方法确定表名是否已存在。
视图可用于创建表的受限子集。以下嵌入式SQL示例创建一个视图,该视图限制了可以通过该视图访问的原始表的行(通过`WHERE`子句)和列(假设`Sample.Person`包含两个以上的列):
```java
/// d ##class(PHA.TEST.SQL).View()
ClassMethod View()
{
&sql(CREATE VIEW Sample.VSrStaff
AS SELECT Name AS Vname,Age AS Vage
FROM Sample.Person WHERE Age>75)
IF SQLCODE=0 {
WRITE "创建一个视图",!
} ELSEIF SQLCODE=-201 {
WRITE "视图已经存在",!
} ELSE {
WRITE "SQL报错: ",SQLCODE," ",%msg,!
}
}
```
```java
DHC-APP>d ##class(PHA.TEST.SQL).View()
创建一个视图
```
以下嵌入式SQL示例基于`SalesPeople`表创建一个视图,并创建一个新的计算值列`TotalPay`:
```java
/// d ##class(PHA.TEST.SQL).View1()
ClassMethod View1()
{
&sql(CREATE VIEW Sample.VSalesPay AS
SELECT Name,(Salary + Commission) AS TotalPay
FROM Sample.SalesPeople)
IF SQLCODE=0 {
WRITE "创建一个视图",!
} ELSEIF SQLCODE=-201 {
WRITE "视图已经存在",!
} ELSE {
WRITE "SQL报错: ",SQLCODE," ",%msg,!
}
}
```
## 管理门户创建视图界面
可以从管理门户创建视图。转到InterSystems IRIS管理门户。在系统资源管理器中,选择SQL。使用页面顶部的Switch选项选择一个名称空间;这将显示可用名称空间的列表。选择名称空间后,单击“操作”下拉列表,然后选择“创建视图”。
这将显示“创建视图”窗口,其中包含以下字段:
- 模式:可以决定将视图包含在现有模式中,也可以创建一个新模式。如果选择选择现有模式,则会提供一个现有模式的下拉列表。如果选择创建新架构,请输入架构名称。在这两种情况下,如果省略模式,则InterSystems IRIS都会使用系统范围内的默认模式名称。
- 视图名称:有效的视图名称。不能对同一模式中的表和视图使用相同的名称。
- 使用`Check Option`:选项为`READONLY`,`LOCAL`,`CASCADED`。
- 将视图的所有特权授予`_PUBLIC`:如果选中,则此选项为该视图授予所有用户执行特权。默认设置是不授予所有用户访问该视图的权限。
- 查看文字:可以通过以下三种方式中的任意一种来指定查看文字:
- 在“查看文本”区域中键入SELECT语句。
- 使用查询生成器创建`SELECT`语句,然后按OK将此查询提供给“查看文本”区域。
- 如果在Management Portal SQL界面的左侧选择了一个缓存查询名称(例如`%sqlcq.USER.cls4`),然后调用`Create View`,则该缓存查询将提供给“视图文本”区域。请注意,在保存视图文本之前,必须在“视图文本”区域中用实际值替换主机变量引用。
## 视图和相应的类
定义视图时,InterSystems IRIS会生成一个相应的类。按照名称转换规则,SQL视图名称用于生成相应的唯一类名称。 Management Portal SQL界面显示现有视图的“目录详细信息”,包括此类名称。
# 修改视图
在Management Portal SQL界面中,可以选择一个现有视图以显示该视图的“目录详细信息”。 “目录详细信息视图信息”选项显示“编辑视图”链接,该链接提供了用于编辑视图文本(视图的`SELECT`语句)的界面。它还提供了一个下拉列表,以将“带检查选项”选择为无,`READONLY`,`LOCAL`或`CASCADED`。
# 可更新的视图
可更新的视图是可以在其上执行`INSERT`,`UPDATE`和`DELETE`操作的视图。仅当满足以下条件时,才认为视图是可更新的:
- 视图查询的`FROM`子句仅包含一个表引用。该表引用必须标识可更新的基表或可更新的视图。
- 视图查询的`SELECT`列表中的值表达式必须全部是列引用。
- 视图的查询中不得指定`GROUP BY`,`HAVING`或`SELECT DISTINCT`。
- 该视图不是投影为视图的类查询。
- 视图的类不包含类参数`READONLY = 1`(如果视图定义包含`WITH READ ONLY`子句,则为`true`)。
## WITH CHECK选项
为了防止在视图上执行`INSERT`或`UPDATE`操作,而该操作会导致基础基表中的行不属于派生视图表的一部分,InterSystems SQL在视图定义中支持`WITH CHECK OPTION`子句。此子句只能与可更新视图一起使用。
`WITH CHECK OPTION`子句指定可更新视图上的任何`INSERT`或`UPDATE`操作必须对照视图定义的WHERE子句验证结果行,以确保插入或修改的行将成为派生视图表的一部分。
例如,以下DDL语句定义了一个可更新的`GoodStudent`视图,其中包含所有具有高`GPA`(平均绩点)的学生:
```java
CREATE VIEW GoodStudent AS
SELECT Name, GPA
FROM Student
WHERE GPA > 3.0
WITH CHECK OPTION
```
由于视图包含`WITH CHECK OPTION`,因此任何尝试在`GPA`值小于或等于3.0的`GoodStudent`视图中插入或更新行都将失败(此类行将不表示“好学生”)。
有两种类型的`WITH CHECK`选项:
- `WITH LOCAL CHECK`选项意味着只检查`INSERT`或`UPDATE`语句中指定的视图的`WHERE`子句。
- 与级联检查选项(和级联检查选项)意味着视图的`WHERE`子句中指定的`INSERT`或`UPDATE`语句以及所有视图检查基于这一观点,无论外表或与当地检查没有其他选项在这些视图定义条款。
如果指定了`just WITH CHECK`选项,默认值是级联的。
在更新或插入期间,在为基础表的字段计算了所有默认值和触发的计算字段之后,并在常规表验证(必需字段、数据类型验证、约束等)之前,检查`WITH CHECK`选项条件。
在`WITH CHECK`选项验证通过后,插入或更新操作继续进行,就像在基表本身上执行插入或更新一样。
检查所有约束,拉出触发器,等等。
如果在`INSERT`或`UPDATE`语句中指定了`%NOCHECK`选项,则不检查`WITH CHECK`选项的有效性。
有两个与`WITH CHECK`选项验证相关的`SQLCODE`值(插入/更新会导致派生视图表中不存在一行):
- `SQLCODE -136`-`INSERT`中视图的`WITH CHECK OPTION`验证失败。
- `SQLCODE -137`-视图的`WITH CHECK OPTION`验证在`UPDATE`中失败。
# 只读视图
只读视图是不能在其上执行`INSERT`,`UPDATE`和`DELETE`操作的视图。任何不符合可更新视图标准的视图都是只读视图。
视图定义可以指定`WITH READ ONLY`子句,以强制其成为只读视图。
如果尝试针对只读视图编译/准备`INSERT`,`UPDATE`或`DELETE`语句,则会生成`SQLCODE -35`错误。
# 查看ID:%VID
InterSystems IRIS为视图或`FROM`子句子查询返回的每一行分配一个整数视图`ID`(`%VID`)。与表行`ID`号一样,这些视图行`ID`号是系统分配的,唯一的,非空的,非零的和不可修改的。该`%VID`通常对用户不可见,并且仅在明确指定时返回。它以数据类型`INTEGER`返回。因为`%VID`值是顺序整数,所以如果视图返回有序数据,它们将更有意义。视图与TOP子句配对时,只能使用`ORDER BY`子句。以下嵌入式SQL示例创建一个名为`VSrStaff`的视图:
```java
/// d ##class(PHA.TEST.SQL).View()
ClassMethod View()
{
&sql(CREATE VIEW Sample.VSrStaff
AS SELECT Name AS Vname,Age AS Vage
FROM Sample.Person WHERE Age>75)
IF SQLCODE=0 {
WRITE "创建一个视图",!
} ELSEIF SQLCODE=-201 {
WRITE "视图已经存在",!
} ELSE {
WRITE "SQL报错: ",SQLCODE," ",%msg,!
}
}
```
下面的示例返回`VSrStaff`视图定义的所有数据(使用`SELECT *`),并且还指定应返回每一行的视图`ID`。与表行`ID`不同,使用星号语法时不显示视图行`ID`。仅当在`SELECT`中明确指定时才显示:
```java
SELECT *,%VID AS ViewID FROM Sample.VSrStaff
```
`%VID`可用于进一步限制`SELECT`从视图返回的行数,如以下示例所示:
```java
SELECT *,%VID AS ViewID FROM Sample.VSrStaff WHERE %VID BETWEEN 5 AND 10
```
**因此,可以使用`%VID`代替`TOP`(或除`TOP`之外)来限制查询返回的行数。通常,`TOP`子句用于返回数据记录的一小部分。 `%VID`用于返回大多数或所有数据记录,以小的子集返回记录。此功能可能很有用,尤其是对于移植Oracle查询(`%VID`轻松映射到Oracle ROWNUM)而言。但是,与`TOP`相比,用户应了解使用`%VID`时的一些性能限制:**
- `%VID`不执行第一行时间优化。 `TOP`优化为尽快返回第一行数据。 `%VID`优化以尽快返回完整的数据集。
- 如果查询指定排序的结果,则`%VID`不会执行有限的排序(这是`TOP`进行的特殊优化)。该查询首先对完整的数据集进行排序,然后使用`%VID`限制返回数据集。 `TOP`是在排序之前应用的,因此`SELECT`只能执行有限的排序,仅涉及有限的行子集。
为了节省第一行优化和有限排序优化的时间,可以将`FROM`子句子查询与`TOP`和`%VID`结合使用。在`FROM`子查询中指定上限(在本例中为10)作为`TOP`的值,而不是使用`TOP ALL`。使用`%VID`在`WHERE`子句中指定下限(在这种情况下,`> 4`)。以下示例使用此策略返回与上一个视图查询相同的结果:
```sql
SELECT *,%VID AS SubQueryID
FROM (SELECT TOP 10 Name,Age
FROM Sample.Person
WHERE Age > 75
ORDER BY Name)
WHERE %VID > 4
```
即使显式指定了`%PARALLEL`关键字,也无法对指定`%VID`的查询执行并行执行。
# List视图属性
`INFORMATION.SCHEMA.VIEWS`持久类显示有关当前名称空间中所有视图的信息。它提供了许多属性,包括视图定义,视图的所有者以及创建和最后修改视图时的时间戳。这些属性还包括视图是否可更新,如果可更新,是否使用检查选项定义。
在嵌入式SQL中指定时,`INFORMATION.SCHEMA.VIEWS`需要`#include%occInclude`宏预处理程序指令。 `Dynamic SQL`不需要此伪指令。
`VIEWDEFINITION`属性(`SqlFieldName = VIEW_DEFINITION`)以字符串形式返回当前名称空间中所有视图的视图字段名称和视图查询表达式。例如,
```sql
SELECT View_Definition FROM INFORMATION_SCHEMA.VIEWS
```
返回诸如`“(vName,vAge)SELECT Name,Age FROM Sample.Person WHERE Age> 21”`的字符串。当从Management Portal SQL执行查询界面发出时,此字符串的显示仅限于前100个字符,其中不包括空格和换行符,并且(如有必要)附加表示省略号的省略号(`...`)。否则,发出此查询将为每个视图返回最多`1048576`个字符的字符串,在视图字段列表和查询文本之间有一个换行符,并保留了视图查询表达式中指定的空格,并(如有必要)附加了省略号(`...`)表示内容被截断。
以下示例返回当前名称空间中所有视图的视图名称(Table_Name字段)和所有者名称:
```sql
SELECT Table_Name,Owner FROM INFORMATION_SCHEMA.VIEWS
```
以下示例返回当前名称空间中所有非系统视图的所有信息:
```sql
SELECT * FROM INFORMATION_SCHEMA.VIEWS WHERE Owner != '_SYSTEM'
```
`INFORMATION.SCHEMA.VIEWCOLUMNUSAGE`持久性类显示当前名称空间中每个视图的源表字段的名称:
```sql
SELECT * FROM INFORMATION_SCHEMA.VIEW_COLUMN_USAGE WHERE View_Name='VSrStaff'
```
可以使用管理门户网站SQL界面中的“目录详细信息”选项卡为单个视图显示与`INFORMATION.SCHEMA.VIEWS`相同的信息。视图的“目录详细信息”包括每个视图字段的定义(数据类型,最大长度,最小值/最大值等),以及`INFORMATION.SCHEMA`视图类未提供的详细信息。 “目录详细信息”视图信息显示还提供了用于编辑视图定义的选项。
# 列出视图依赖
`INFORMATION.SCHEMA.VIEWTABLEUSAGE`持久类显示当前名称空间中的所有视图及其依赖的表。在下面的示例中显示:
```sql
SELECT View_Schema,View_Name,Table_Schema,Table_Name FROM INFORMATION_SCHEMA.VIEW_TABLE_USAGE
```
可以调用`%Library.SQLCatalog.SQLViewDependsOn`类查询以列出指定视图所依赖的表。可以为此类查询指定`schema.viewname`。如果仅指定视图名称,则它将使用系统范围的默认架构名称。调用者必须具有指定视图的特权才能执行此类查询。在下面的示例中显示:
```java
/// d ##class(PHA.TEST.SQL).View3()
ClassMethod View3()
{
SET statemt=##class(%SQL.Statement).%New()
SET cqStatus=statemt.%PrepareClassQuery("%Library.SQLCatalog","SQLViewDependsOn")
IF cqStatus'=1 {
WRITE "%PrepareClassQuery failed:" DO $System.Status.DisplayError(cqStatus) QUIT
}
SET rset=statemt.%Execute("vschema.vname")
DO rset.%Display()
}
```
```sql
DHC-APP>d ##class(PHA.TEST.SQL).View3()
Dumping result #1
SCHEMA TABLE_NAME
0 Rows(s) Affected
```
此`SQLViewDependsOn`查询列出了视图所依赖的表,并列出了表架构和表名。如果调用者没有该视图所依赖的表的特权,则该表及其模式将列为``。这允许没有表特权的调用者确定视图所依赖的表数量,而不是表的名称。