清除过滤器
文章
Muhammad Waseem · 八月 11, 2022
嗨社区,
这篇文章公开介绍我的 iris-fhir-client 客户端应用。
iris-fhir-client 可以可以借助嵌入式 python 连接到任何开放的 FHIR 服务器 fhirpy 图书馆.
通过终端和使用 CSP Web 应用程序获取资源信息。
查看和激活注册服务器
连接到 IRIS 终端
docker-compose exec iris iris session iris
应用程序将默认注册 InterSystems FHIR Accelerator Service 和 SmartHealthIT Open FHIR Server,两者都可以使用。使用以下命令列出已注册的服务器
do ##class(dc.FhirClient).ServerList()
InterSystems FHIR 加速器服务处于激活状态。 为了选择 SmartHealthIT 打开 FHIR 服务器,通过传递服务器 ID 使用 dc.FhirClient 类的 SetFhirServer 函数
do ##class(dc.FhirClient).SetFhirServer(2)
注册的 FHIR 服务器
要注册新服务器,请使用 dc.FhirClient 类的 RegisterServer() 函数class(dc.FhirClient).RegsterServer("Server Name","Endpoint","ApiKey"[optional],"EndpointOAuth"[optional]
do ##class(dc.FhirClient).RegisterServer("INTERSYSTEMS FHIR Server","http://localhost:52773/csp/healthshare/samples/fhir/r4/","","")
从 FHIR 服务器获取资源
要检索当前服务器的所有资源,请使用 dc.FhirClient 类的 ListResources() 方法
do ##class(dc.FhirClient).ListResources()
为了显示任何资源的记录数,通过传递 dc.FhirClient 的 Resource 使用 CountResource() 方法下面的命令将从激活的 FHIR 服务器获取患者资源计数器
set count = ##class(dc.FhirClient).CountResource("Patient")
write count
要检索所有创建的资源及其计数,只需将 1 传递给 ListResource() 函数
do ##class(dc.FhirClient).ListResources(1)
要获取资源的详细信息,请通过传递 dc.FhirClient 类的 Resource 使用 GetResource()下面的命令将从激活的FHIR 服务器中检索所有患者
do ##class(dc.FhirClient).GetResource("Patient")
下面的命令将从激活的 FHIR 服务器中检索所有观察结果
do ##class(dc.FhirClient).GetResource("Observation")
从 FHIR 服务器获取特定患者的资源
下面的命令将从激活的 FHIR 服务器中检索针对 Patinet ID 1 的观察详细信息
do ##class(dc.FhirClient).GetPatientResources("Observation","1")
从 CSP Web 应用程序查看 FHIR 服务器信息
导航 http://localhost:55037/csp/fhirclient/index.csp索引页面将显示激活的服务器中患者、观察、从业者和就诊次数以及患者和注册服务器的详细信息
索引页面将显示 FHIR 服务器列表,其中选择了激活的服务器。 从列表中选择其他服务器以查看所选服务器的详细信息
将鼠标悬停到患者 ID 并选择以获取患者资源的详细信息
此页面将显示一些患者资源的数量以及患者观察的详细信息
谢谢
文章
Michael Lei · 四月 17, 2022
# 在IRIS容器里添加VSCode
设置可重复的开发环境的最简单的方法之一是使用容器。我发现在快速迭代时,在我的开发环境容器里托管一个vscode实例是非常方便的。因此,我创建了一个快速的容器脚本,将一个基于浏览器的vscode添加到IRIS容器中。这应该适用于大多数2021.1以上的容器。[我的代码库可以在这里找到](https://github.com/nickmitchko/Hosting-vscode-in-a-container)
> 带VSCode 且预连接好的InterSystems IRIS 容器
| Cred | Value |
|--------------|:--------:|
| User | _SYSTEM |
| Password | SYS |

## 概要
这个项目创建了一个IRIS容器,在同一个IRIS容器中提供了vscode的托管(web-based)版本。这提供了:
* 同样的容器代码编辑
* 预连接到容器内的IRIS 实例
* 管理门户里的链接
* 自动启动IDE
# 快速启动
1. [下载](https://github.com/nickmitchko/Hosting-vscode-in-a-container/archive/refs/heads/master.zip) 或者 `git clone https://github.com/nickmitchko/Hosting-vscode-in-a-container.git`
2. 在项目根目录下, 运行 `docker build . -t vscode-irishealth-ml:latest --no-cache`
3. 执行 `docker-compose up`
* 不使用 docker compose? 请看 [这里](#No-Docker-Compose)
4. 浏览 [管理门户](http://localhost:52773/csp/sys/%25CSP.Portal.Home.zen)
5. 用用户名和密码登陆
6. 在Favorites 面板里点击 VSCODE 链接 on the favorites pane
7. 依据提示在VScode里使用相同的用户名/密码 来连接到IRIS 实例
```bash
# New folder for project
mkdir vscode-iris
cd vscode-iris
# Clone repo here
git clone https://github.com/nickmitchko/Hosting-vscode-in-a-container.git .
# Build image
docker build . -t vscode-irishealth-ml:latest --no-cache
# Only Run (A) or (B)
#
# (A) Run compose file
docker-compose up
# OR (B) if you want a daemon
docker-compose up -d
```
## 添加持久化
如果想要一个持久化IRIS实例, 去掉docker-compose.yml 文件中16-20行里的注释 . 这样就在容器上增加了一个持久化存储的挂载。
```yml
volumes:
- "./durable/:/durable/"
environment:
- ISC_DATA_DIRECTORY=/durable/iconfig
```
## 改变基础镜像Base Image
这个镜像是建立在 InterSystems 开发者社区 zpm 镜像上 ([看这里](https://hub.docker.com/r/intersystemsdc/iris-community/tags)). 这些镜像包括了让我们从package repo 安装的zpm命令,只是仅有一个90天的社区版 license。
用于这个builds上的镜像标签image tag:
```dockerfile
FROM intersystemsdc/irishealth-ml-community:latest
```
如果你想改变镜像, 把docker 文件里的第一行改成你想要的镜像标签image tag (可以是一个自定义的IRIS instance 或者 [官方支持的](https://docs.intersystems.com/components/csp/docbook/DocBook.UI.Page.cls?KEY=PAGE_containerregistry#PAGE_containerregistry_public)). 例如:
```dockerfile
FROM containers.intersystems.com/intersystems/irishealth-community:2021.2.0.651.0
```
# 无 Docker-Compose
如果你没有用 docker compose, 你仍然可以如下运行容器:
```bash
# After building the container
# --after command is required
docker run --name vscode -d \
--publish 1972:1972 \
--publish 52773:52773 \
--publish 51773:51773 \
--publish 53773:53773 \
--publish 8080:8080 \
--publish 8888:8888 \
vscode-irishealth-ml:latest \
--after "/bin/bash /install/boot.sh"
```
公告
Michael Lei · 三月 21, 2022
# IRIS Healthtoolkit Service 软件即服务
[](https://youtu.be/lr2B7zSFkds "Video")
轻松实现HL7v2 转 FHIR, CDA 转 FHIR, FHIR 转 HL7v2 即服务.
这个项目的目标是提供 REST API 可以轻松转化不同的医疗行业格式。
在Rest body 发布需要的格式,在答案中获得新的格式。
*  InterSystems 消息转换公有云服务: https://aws.amazon.com/marketplace/pp/prodview-q7ryewpz75cq2 
*  视频(油管) : https://youtu.be/lr2B7zSFkds 
## 安装
克隆这个 repository
```
git clone https://github.com/grongierisc/iris-healthtoolkit-service.git
```
Docker
```
docker-compose up --build -d
```
## 使用
* 访问 : http://localhost:32783/swagger-ui/index.html
## API 细节
* HL7 转 FHIR
```
POST http://localhost:32783/api/hl7/fhir
```
* FHIR 转 HL7 ADT
```
POST http://localhost:32783/api/fhir/hl7/adt
```
* FHIR 转 HL7 ORU
```
POST http://localhost:32783/api/fhir/hl7/oru
```
* FHIR 转 HL7 vxu
```
POST http://localhost:32783/api/fhir/hl7/vxu
```
* CDA 转 FHIR
```
POST http://localhost:32783/api/cda/fhir
```
* FHIR repo
```
GET http://localhost:32783/api/fhir/metadata
```
## 支持的 HL7 inbound 格式 :
* ADT_A01, ADT_A02, ADT_A03, ADT_A04, ADT_A05, ADT_A06, ADT_A07, ADT_A08, ADT_A09, ADT_A10, ADT_A11, ADT_A12, ADT_A13, ADT_A17, ADT_A18, ADT_A23, ADT_A25, ADT_A27, ADT_A28, ADT_A29, ADT_A30, ADT_A31, ADT_A34, ADT_A36, ADT_A39, ADT_A40, ADT_A41, ADT_A45, ADT_A47, ADT_A49, ADT_A50, ADT_A51, ADT_A60
* BAR_P12
* MDM_T02, MDM_T04, MDM_T08, MDM_T11
* OMP_O09
* ORM_O01
* ORU_R01
* PPR_PC1, PPR_PC2, PPR_PC3
* RDE_O11
* SIU_S12, SIU_S13, SIU_S14, SIU_S15, SIU_S16, SIU_S17, SIU_S26
* VXU_V04
## 如何工作
这个项目基于SDA模型工作.
SDA (Summary Document Architecture) 是InterSystems系联公司的临床数据格式。
SDA FHIR 的对应关系在 [这里](https://docs.intersystems.com/irisforhealthlatest/csp/docbook/Doc.View.cls?KEY=HXFHIR_transforms), CDA -> SDA 的对应在[这里](https://docs.intersystems.com/irisforhealthlatest/csp/docbook/DocBook.UI.Page.cls?KEY=HXCDA).

文章
Michael Lei · 五月 17, 2021
我创建了 iris-fhir-portal 来参加当前竞赛 **[InterSystems IRIS for Health FHIR](https://community.intersystems.com/post/welcome-intersystems-iris-health-fhir-contest-developers),**本篇快速概述旨在介绍我的应用程序提供的功能。
iris-fhir-portal 的目标是说明使用 IRIS for Health 中的 FHIR 功能创建患者图表并让用户拥有自己的数据有多么简单。
## 功能
### 患者列表
在左侧面板上,有一个患者列表,顶部是一个筛选栏。

### 患者详细信息

表格提供以下信息:
* FHIR 患者 ID
* SSN(社会保障号码)
* 名字
* 姓氏
* 出生日期
* 性别
* 地址
* 城市
* 州/省
* 国家/地区
在患者详细信息表格后面,是一个包含四个信息块的可折叠项。 提供这些信息的 FHIR 资源为:
* AllergyIntolerance
* Observation
* 类别:vital-signs
* 类别:laboratory
* Immunization
右侧的徽章显示每个项目的结果总数。
附注:我在上一篇文章中写到了如何从 FHIR 资源获取所有这些信息。 https://community.intersystems.com/post/my-experience-working-fhir
例如,以下是实验室数据结果的屏幕截图:

为了以透明的方式处理患者数据,在页面末尾有一个模版,其中包含 FHIR 资源提供的所有信息。

####
#### 您可以在这里试用本应用程序!
如果您喜欢本应用程序,并认为我值得您投票,请为 iris-fhir-portal 投一票! 
****
问题
water huang · 四月 24, 2021
最近尝试使用 Set Ciphertext=##class(%SYSTEM.Encryption).RSAEncrypt(Plaintext,PublicKeyStr)来加密数据,但是加密失败,参考了以下资料https://community.intersystems.com/post/format-public-key-when-using-rsaencrypt-method-systemencryption-or-systemencryptionrsaencrypt
https://blog.ndpar.com/2017/04/17/p1-p8/
生成的公钥为
-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvl8YRMOJMUOyK5NzWo+8FD8dGR3DuPwn7M13If+rwYp18TEL58NneFdCL+Jjytx4axq+uhPuup5HtmEm22+PQTzFlXuAhXf3oUm4LQl4zgSb14D6gfqac9DqbVhm+aUjDfItFapM35/DH2cvc+rbBhu4Q5Y6kJwcUK0UbRv3swQIDAQAB-----END PUBLIC KEY-----
转换为pkcs1后的内容为
-----BEGIN RSA PUBLIC KEY-----MIGJAoGBANHPwS9+rVB1TJZM1UGLCBan3CY8TIDPkDAftkI504l68vdUWdPlmcN1YZzCGDK4+LvtzdqLXb/XSA3SxsUrA5toWSh45K7/jDzXRcb0AYiUTWGfpeMrHdcGNL07gVT11FM8M+0Jc5Sw6dvMKVXE9wzAxwgaJo0d8zW8Crbx6iI3AgMBAAE=-----END RSA PUBLIC KEY-----
文件保存为utf-8和ansi格式都不行。错误信息为
error:0906D06C:PEM routines:PEM_read_bio:no start line; 2016之后的版本,RSAEncrypt可以接收X.509证书或RSA公钥,而2016中RSAEncrypt接收证书参数。Ensemble2016上使用RSAEncrypt,如果拿不到证书,仅用公钥,请联系InterSystems 销售工程师。 好的,谢谢
问题
Michael Lei · 二月 14, 2023
您好,有没有一种简单的方法可以导出与Production相关的所有内容并在另一个实例中导入?
例如导出Production保存的 db、ns、映射、webapp 相关、资源、角色等 您可以使用InterSystems Package Manager(IPM)列出生产的所有成员,并通过IPM注册表或使用zpmhub将其分发到另一台机器(例如您的客户端)。
例如,您可以将多个EnsDemo产品安装为一个包:
用户>zpm“安装irishealth-ensdemo”
或者最近我发布了一个非常简单的CSV数据转换生产示例,您可以将其安装为一行:
USER>zpm "install esh-i14y-csv"
下面是如何在module.xml中描述生产的所有模块。
文章
Claire Zheng · 八月 17, 2021
当前医院面临更多互联互通需求,如预约挂号与分级诊疗、检验结果共享、医联体信息化、监管数据上报、临床辅助决策支持等,都需要对多源数据进行集成与整合。医疗机构内部和跨机构数据交换与共享,对互联互通提出新的要求。HL7 FHIR是国际上医疗行业实现数据交换和信息共享的标准之一,正在快速得到医疗行业广泛关注。InterSystems中国技术总监乔鹏在视频中分享了FHIR标准与国际互联互通的一些实践经验。
文章
姚 鑫 · 三月 4, 2021
# 第三章 SQL语言元素(一)
# 命令和关键字
InterSystems SQL命令(也称为SQL语句)以关键字开头,后跟一个或多个参数。其中一些参数可能是子句或函数,由它们自己的关键字标识。
- **InterSystems SQL命令没有命令终止符,除非在特殊情况下(例如SQL过程代码或触发代码),在这种情况下,SQL命令以单个分号(`;`)终止。否则,InterSystems SQL命令不需要或接受分号命令终止符**。在InterSystems SQL中指定分号命令终止符会导致`SQLCODE -25`错误。 TSQL的InterSystemsIRIS®数据平台实现(Transact-SQL)接受但不需要分号命令终止符。在将SQL代码导入Inter Systems SQL时,会去除分号命令终止符。
- **InterSystems SQL命令没有空格限制。如果命令项之间用空格隔开,则至少需要一个空格。** 如果命令项之间用逗号分隔,则不需要空格。算术运算符之前或之后不需要空格。可以在以空格分隔的项目之间,以逗号分隔的参数列表中的项目之间或在算术运算符之前或之后插入换行符或多个空格。
InterSystems SQL关键字包括命令名称,函数名称,谓词条件名称,数据类型名称,字段约束,优化选项和特殊变量。它们还包括`AND`,`OR`和`NOT`逻辑运算符,`NULL`列值指示符以及ODBC函数构造,例如`{d dateval}`和`{fn CONCAT(str1,str2)}`。
- 关键字不区分大小写。按照惯例,在本文档中,关键字用大写字母表示,但是InterSystems SQL没有大小写限制。
- 有许多关键字是SQL保留字。 InterSystems SQL仅保留那些不能明确解析的关键字。 SQL保留字可用作分隔符。
# 函数:内在的和外在的
- 内在的:InterSystems SQL支持大量内在的(系统提供的)函数。
这些函数包括数字函数、字符串函数以及日期和时间函数。
聚合函数是SQL固有函数,它计算列的所有值并返回单个聚合值。
- InterSystems SQL也可以支持用户提供的ObjectScript函数调用(外部函数),如下所示:
这种写法只能在mac routine里,类文件里编译报错。
```sql
MySQL
&sql(SELECT Name,$$MyFunc() INTO :n,:f FROM Sample.Person)
WRITE "name is: ",n,!
WRITE "function value is: ",f,!
QUIT
MyFunc()
SET x="my text"
QUIT x
```
如果将用户提供的(外部)函数的使用配置为系统范围的选项,则该SQL语句只能调用用户提供的(外部)函数。默认为“否”。默认情况下,尝试调用用户提供的函数会发出`SQLCODE -372`错误。可以使用`%SYSTEM.SQL类的SetAllowExtrinsicFunctions()`方法在系统范围内配置SQL对外部函数的使用。若要确定当前设置,请调用`$SYSTEM.SQL.CurrentSettings()`,该显示显示“允许在SQL语句中使用外部函数”选项。
不能使用用户提供的函数来调用`%routine`(名称以%字符开头的例程)。
尝试这样做会发出`SQLCODE -373`错误。
# 文字
InterSystems SQL文字具有以下语法:
```
literal ::=
number | string-literal
number ::=
{digit}[.]digit{digit}[E[+|-]digit{digit}]
digit ::=
0..9
string-literal ::=
std-string-literal | ObjectScript-empty-string
std-string-literal ::=
' {std-character-representation} '
std-character-representation ::=
nonquote-character | quote-symbol
quote-symbol ::=
''
ObjectScript-empty-string ::=
""
```
文字是一系列代表实际(文字)值的字符。它可以是数字或字符串。
- 数字不需要任何分隔符。它可以由数字0到9,小数点字符,指数符号以及加号和减号组成。数字中只能使用一个小数点字符。该小数点只能用于数字的基数部分,不能用于指数部分。小数点后不需要数字。允许前导零和尾随零。指数(科学符号)符号为字母E;大写字母E和小写字母E都可以接受,但是大写字母E是首选用法。加号或减号可以加一个底数或一个指数。多个加号和减号可以加上x个基数; SQL将这些符号视为运算符。 x只能有一个正负号。 SQL将此符号视为文字的一部分。请勿在数字中使用逗号或空格。
- 字符串文字包含一对分隔符,其中包含任何类型的字符串。首选的定界符是单引号字符。要将分隔符指定为字符串中的文字,请将该字符加倍;例如: `'Mary's office'`.
**空字符串是文字字符串;它由两个单引号字符(`''`)表示。 `NULL`不是文字值;它表示没有任何值。**
注意:在嵌入式SQL中,不允许在字符串文字中使用以`##`开头的一些字符序列,如“使用嵌入式SQL”一章的“文字值”中所述。此限制不适用于其他SQL调用,例如动态SQL。
# 字符串分割符
使用单引号(`'`)字符作为字符串定界符。 SQL兼容性支持双引号字符(`“`)的使用,但由于与定界标识符标准冲突,因此强烈建议不要使用。将一对双引号字符`""`解析为无效的定界标识符。并生成`SQLCODE -1`错误。
要在字符串中指定单引号字符作为字面字符,请指定一对这样的字符作为字面转义序列。
例如,`'a 'normal' string'`。
## 串联
双竖条(`||`)是首选的SQL连接操作符。
它可以用于连接两个数字、两个字符串或一个数字和一个字符串。
下划线(`_`)作为SQL连接操作符提供,以保证ObjectScript的兼容性。
此连接操作符只能用于连接两个字符串。
如果两个操作数都是字符串,并且两个字符串都具有相同的排序规则类型,则所得的级联字符串具有该排序规则类型。在所有其他情况下,连接的结果是排序类型`EXACT`。
# NULL和空字符串
使用`NULL`关键字表示没有指定值。
在SQL中,`NULL`始终是表示数据值因任何原因未指定或不存在的首选方式。
SQL零长度字符串(空字符串)由两个单引号字符指定。
空字符串(`"`)与空字符串是不同的。
空字符串是一个已定义的值,一个不包含字符的字符串,一个长度为0的字符串。
一个零长度的字符串在内部由非显示字符`$CHAR(0)`表示。
**注意:不建议使用SQL零长度字符串作为字段输入值或字段默认值。
使用`NULL`表示数据值的缺失。**
**在SQL编码中应避免使用SQL零长度字符串。
但是,由于许多SQL操作都会删除末尾的空格,所以只包含空格字符(空格和制表符)的数据值可能会导致SQL的零长度字符串。**
注意,不同的SQL length函数返回不同的值:`length`、`CHAR_LENGTH`和`DATALENGTH`返回SQL长度。
`$LENGTH`返回ObjectScript表示长度。
长度不计算尾随空格;
所有其他长度函数都计算末尾的空格。
# null 处理
NOT NULL数据约束要求字段必须接收一个数据值;
不允许指定NULL而不是值。
这个约束不阻止使用空字符串值。
`SELECT`语句的`WHERE`或`HAVING`子句中的`IS NULL`谓词选择空值;
它不选择空字符串值。
`IFNULL`函数计算一个字段值,如果字段值为`NULL`,则返回第二个参数中指定的值。
它不会将空字符串值视为非空值。
`COALESCE`函数从提供的数据中选择第一个非空值。
它将空字符串值视为非空值。
当`CONCAT`函数或`concenate`操作符(`||`)连接一个字符串和一个`NULL`时,结果是`NULL`。
如下面的例子所示:
```sql
SELECT {fn CONCAT('fred',NULL)} AS FuncCat, -- returns
'fred'||NULL AS OpCat -- returns
```
`AVG、COUNT、MAX、MIN`和`SUM`聚合函数在执行操作时忽略`NULL`值。
(`COUNT *`统计所有行,因为不可能有一个所有字段都为空值的记录。)
`SELECT`语句的`DISTINCT`关键字在其操作中包含`NULL`;
如果指定的字段有空值,`DISTINCT`返回一个空行.
`AVG`、`COUNT`和`MIN`、聚合函数受空字符串值的影响。
`MIN`函数将空字符串视为最小值,即使存在值为0的行。
`MAX`和`SUM`聚合函数不受空字符串值的影响。
## null 表达式
对大多数SQL函数提供`NULL`作为操作数将返回`NULL`。
任何以NULL作为操作数的SQL算术操作都返回`NULL`值。
因此,7 +零=零。
这包括二元运算加法(`+`)、减法(`-`)、乘法(`*`)、除法(`/`)、整数除法(`\`)和取模(`#`),以及一元符号运算符加号(`+`)和减号(`-`)。
算术操作中指定的空字符串将被视为0(零)值。
除法(`/`),整数除法(`\`),或对空字符串(`6/ "`)取模(`#`)会导致``错误。
## NULL的长度
在SQL中,`NULL`的长度是没有定义的(它返回`< NULL >`)。
然而,空字符串的长度被定义为长度为0。
如下面的例子所示:
```sql
SELECT LENGTH(NULL) AS NullLen, -- returns
LENGTH('') AS EmpStrLen -- returns 0
```
如本例所示,SQL `LENGTH`函数返回SQL长度。
可以使用`ASCII`函数将SQL的零长度字符串转换为`NULL`,示例如下:
```sql
SELECT LENGTH(NULL) AS NullLen, -- returns
LENGTH({fn ASCII('')}) AS AsciiEmpStrLen, -- returns
LENGTH('') AS EmpStrLen -- returns 0
```
但是,对标准`SQL`的某些系统间IRIS扩展对`NULL`和空字符串的长度的处理是不同的。
$LENGTH函数返回这些值的InterSystems IRIS内部表示:`NULL`表示为长度为0的已定义值,SQL空字符串表示为长度为0的字符串。
该功能与ObjectScript兼容。
```sql
SELECT $LENGTH(NULL) AS NullLen, -- returns 0
$LENGTH('') AS EmpStrLen, -- returns 0
$LENGTH('a') AS OneCharStrLen, -- returns 1
$LENGTH(CHAR(0)) AS CharZero -- returns 0
```
这些值的内部表示方式的另一个重要位置是`%STRING`、`%SQLSTRING`和`%SQLUPPER`函数,它们将空格附加到值中。
因为`NULL`实际上没有值,所以在它后面添加一个空格会创建一个长度为1的字符串。
但是一个空字符串确实有一个字符值,所以在它后面加上一个空格会创建一个长度为2的字符串。
如下面的例子所示:
```sql
SELECT CHAR_LENGTH(%STRING(NULL)) AS NullLen, -- returns 1
CHAR_LENGTH(%STRING('')) AS EmpStrLen -- returns 2
```
注意,这个例子使用的是`CHAR_LENGTH`,而不是`LENGTH`。
因为`LENGTH`函数删除了末尾的空格,所以`LENGTH(%STRING(NULL))`返回长度为0的字符串;
`LENGTH(%STRING("))`返回长度为2的字符串,**因为`%STRING`追加的是前导空格,而不是尾随空格。**
## ObjectScript和SQL
当SQL `NULL`输出到ObjectScript时,它由ObjectScript空字符串(`""`)表示,长度为0的字符串。
当SQL零长度字符串数据输出到ObjectScript时,它由包含`$CHAR(0)`的字符串表示,该字符串长度为1。
```sql
/// d ##class(PHA.TEST.SQL).Null()
ClassMethod Null()
{
&sql(SELECT NULL,'' INTO :a,:b)
WRITE !,"NULL length: ",$LENGTH(a) // returns 0
WRITE !,"empty string length: ",$LENGTH(b) // returns 1
}
```
```sql
DHC-APP>d ##class(PHA.TEST.SQL).Null()
NULL length: 0
empty string length: 1
```
在ObjectScript中,没有值通常用空字符串(`""`)表示。
当这个值被传递到嵌入式SQL中时,它会被视为空值,如下面的例子所示:
```sql
/// d ##class(PHA.TEST.SQL).Null1()
ClassMethod Null1()
{
SET x=""
SET myquery="SELECT NULL As NoVal,:x As EmpStr"
SET tStatement=##class(%SQL.Statement).%New()
SET qStatus=tStatement.%Prepare(myquery)
IF qStatus'=1 {WRITE "%Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT}
SET rset=tStatement.%Execute()
WHILE rset.%Next() {
WRITE "NoVal:",rset.%Get("NoVal")," length ",$LENGTH(rset.%Get("NoVal")),! // length 0
WRITE "EmpStr:",rset.%Get("EmpStr")," length ",$LENGTH(rset.%Get("EmpStr")),! // length 0
}
WRITE "End of data"
}
```
```sql
DHC-APP>d ##class(PHA.TEST.SQL).Null1()
NoVal: length 0
EmpStr: length 0
End of data
```
如果指定了一个未定义的输入主机变量,嵌入式SQL将其值视为`NULL`。
当将NULL或空字符串值从嵌入式SQL传递到ObjectScript时,`NULL`被转换为长度为0的字符串,空字符串被转换为长度为1的字符串。
如下面的例子所示:
```sql
/// d ##class(PHA.TEST.SQL).Null2()
ClassMethod Null2()
{
&sql(SELECT
NULL,
''
INTO :a,:b)
WRITE !,"The length of NULL is: ",$LENGTH(a) // length 0
WRITE !,"The length of empty string is: ",$LENGTH(b) // length 1
}
```
```sql
DHC-APP>d ##class(PHA.TEST.SQL).Null2()
The length of NULL is: 0
The length of empty string is: 1
```
在下面的例子中,SQL的空字符串加上一个空格被传递为长度为2的字符串:
```sql
/// d ##class(PHA.TEST.SQL).Null3()
ClassMethod Null3()
{
&sql(SELECT %SQLUPPER('')
INTO :y )
WRITE !,"SQL empty string length: ",$LENGTH(y)
}
```
```sql
DHC-APP> d ##class(PHA.TEST.SQL).Null3()
SQL empty string length: 2
``` good, mark Thank you! It's very useful for us while using InterSystems SQL. 学习了,谢谢大佬 很实用!感谢总结! 大佬,已被圈粉,长期追踪学习!
文章
Jingwei Wang · 一月 19, 2023
Python 已成为世界上使用最广泛的编程语言(来源:https://www.tiobe.com/tiobe-index/),SQL 作为数据库语言继续引领潮流。 Python 和 SQL 一起工作以提供 SQL 单独无法提供的新功能不是很好吗?毕竟,Python 拥有超过 380,000 个已发布的库(来源:https://pypi.org/),它们具有非常有趣的功能,可以在 Python 中扩展您的 SQL 查询。本文详细介绍了如何使用嵌入式 Python 在 InterSystems IRIS 数据库中创建新的 SQL 存储过程。
用作示例的 Python 库
本文将使用两个非常有用的库:Geopy 和 Chronyk。
Geopy 是一个用于将地理编码(地址和地理坐标的限定)应用于地址数据的库。有了它,就可以从街道名称中获取邮局格式的邮政编码和完整地址。非常有用,因为许多记录都有地址。
Chronyk 用于使用人类语言处理日期和时间。这非常有用,因为在内部,对于 IRIS 和 Python,日期是一个数字,表示自初始日期以来经过的时间量。对于人类来说,日期是 7 月 20 日,或者昨天,或者明天,或者两个小时前。 Chronyk 接受接收这样的日期,然后将其转换为通用日期格式。
InterSystems IRIS 中的 Python 支持
从 2021.1 版开始,可以使用 Python 以双向方式在 Python 和 IRIS (ObjectScript) 之间创建类方法、存储过程、互操作产品和Native调用。我不知道有任何其他数据平台可以如此深入地使用 Python。这个工作的要求是 Python 安装在与 IRIS 相同的物理或虚拟机或容器上。 更多详情请见:https://docs.intersystems.com/iris20221/csp/docbook/DocBook.UI.Page.cls?KEY=AFL_epython。对于安装 python 运行:
# install libraries required for python and pip
RUN apt-get -y update \
&& apt-get -y install apt-utils \
&& apt-get install -y build-essential unzip pkg-config wget \
&& apt-get install -y python3-pip
Python 库支持 InterSystems IRIS
为了使 InterSystems IRIS 能够使用 Python 库,必须将其安装在 <installdir>/mgr/python 中。其中 installdir 是安装 IRIS 的文件夹。要安装新包运行:
# use pip3 (the python zpm) to install geopy and chronyk packages
RUN pip3 install --upgrade pip setuptools wheel
RUN pip3 install --target /usr/irissys/mgr/python geopy chronyk
Pip3 是 Python 最受欢迎的包管理器和安装程序 Pip。
Python语言创建存储过程
在 InterSystems IRIS 中使用 Python 的一种可能性是使用 Python 创建存储过程。有两种可能性:
Python使用Create Function or Procedure的SQL语句创建存储过程;
使用 sqlProc 和 language=Python 标记在 ObjectScript 类中创建 ClassMethod。
Python使用Create Procedure的SQL语句创建存储过程
根据 InterSystems 文档,您还可以通过在 CREATE 语句中指定 LANGUAGE PYTHON 参数,使用嵌入式 Python 编写 SQL 函数或存储过程,如下所示(来源:https://docs.intersystems.com/iris20221/csp/ docbook/DocBook.UI.Page.cls?KEY=AEPYTHON#AEPYTHON_runpython_sql):
CREATE FUNCTION tzconvert(dt TIMESTAMP, tzfrom VARCHAR, tzto VARCHAR)
RETURNS TIMESTAMP
LANGUAGE PYTHON
{
from datetime import datetime
from dateutil import parser, tz
d = parser.parse(dt)
if (tzfrom is not None):
tzf = tz.gettz(tzfrom)
d = d.replace(tzinfo = tzf)
return d.astimezone(tz.gettz(tzto)).strftime("%Y-%m-%d %H:%M:%S")
}
当您运行这个新的 SQL 函数时:
SELECT tzconvert(now(), 'US/Eastern', 'UTC')
该函数返回如下内容:
2022-07-20 15:10:05
使用 sqlProc 和 language=Python 标记在 ObjectScript 类中创建 ClassMethod
我承认我最喜欢这种方法:使用 sqlProc 和 language=Python 标记创建一个 ClassMethod。在我看来,它更容易维护,文档更好,明显并且源代码版本管理更好。对于这种方法,我发布了一个示例应用程序:https://openexchange.intersystems.com/package/Python-IRIS-SQL-Procedures-Sample。我将用它来详细演示第二种方法。
示例应用程序安装
要安装示例应用程序,请按照以下步骤操作:
clone/git 将 repo 拉入任何本地目录
$ git clone https://github.com/yurimarx/iris-sql-python-sample.git
在此目录中打开一个 Docker 终端并运行:
$ docker-compose build
运行 IRIS 容器:
$ docker-compose up -d
另一种安装可能性是使用 ZPM:
zpm "install iris-sql-python-sample"
使用 Python 的存储过程示例
第一个示例是处理地址地理编码的存储过程,请参阅源代码:
ClassMethod GetFullAddress(Street As %String, City As %String, State As %String)
As %String [ Language = python, SqlName = GetFullAddress, SqlProc ]
{
import geopy.geocoders
from geopy.geocoders import Nominatim
geopy.geocoders.options.default_timeout = 7
geolocator = Nominatim(user_agent="intersystems_iris")
location = geolocator.geocode(Street + ", " + City + ", " + State, country_codes="US")
return location.address
}
看到使用 [Language = python, SqlProc] 标记声明了一个 ClassMethod(在 dc.pythonsql.Company 类中)。SqlName 标签允许在 SQL 语句中为新的存储过程设置一个名称。
转到管理门户,系统 > SQL 并运行以下代码:
SELECT
ID, City, Name, State, Street, Zip, dc_pythonsql.GetFullAddress(Street, City, State) As FullAddress
FROM dc_pythonsql.Company
现在不完整的地址返回为“完整”地址(完整且合格)。
注意:如果没有返回执行#class(dc.pythonsql.Company).CreateFiveCompanies()。它将创建五家公司用于测试。
该软件包可以与主要的开放和市场地理编码服务一起使用。在此示例中,我们使用开放服务 Nominatim,但也可以使用 Bing、Google、ArcGIS 等。在 https://geopy.readthedocs.io/en/stable/#module-geopy.geocoders 上查看可能性。
第二个例子是人性化格式的日期和时间包,Chronyk。
它允许您发送“明天”、“昨天”、“4 小时后”、“2022 年 7 月 4 日”等句子,并以通用日期格式获取结果。查看存储过程的创建:
类方法 GetHumanDate (语句 作为 %字符串) 作为 %细绳 [ 语言 = 蟒蛇, 数据库名称 = 获取人类日期, SQLProc ]
ClassMethod GetHumanDate(Sentence As %String) As %String [ Language = python, SqlName = GetHumanDate, SqlProc ]
{
from chronyk import Chronyk
t = Chronyk(Sentence)
return t.ctime()
}
在管理门户 > 系统 > SQL 中执行以下调用:
SELECT
ID, City, Name, State, Street, Zip, dc_pythonsql.GetHumanDate('yesterday') As Datetime
FROM dc_pythonsql.Company
如果你只想调用存储过程,你可以使用这个 SQL 语句:
select dc_pythonsql.GetHumanDate('yesterday') as Datetime
该库具有多种人性化日期和时间的可能性,请参阅 https://github.com/KoffeinFlummi/Chronyk。
所以,很容易创建 Python 存储过程,尽情享受吧!
文章
姚 鑫 · 八月 23, 2022
# 第十章 配置数据库(二)
# 本地数据库
“本地数据库”页面显示关于系统上的数据库的以下信息:
- `Name`—数据库名称。
- `Mirror`——如果数据库是镜像的,则镜像的名称;
- `Directory` - `IRIS.DAT` 文件的位置。
- `Size` 大小 (MB) — 以 `MB` 为单位的数据库大小。
- `Status` 状态 — 指定数据库是挂载、卸载还是卸载;如果已挂载,则指定它是否具有只读或读写权限。
- `Resource Name`资源名称 — 控制对数据库的访问的数据库资源的名称;
- `Encrypted` — 指定数据库是否加密;
- `Journal` 指定数据库是否被记录;
## 创建本地数据库
要创建本地数据库,请导航到本地数据库页面(系统管理 > 配置 > 系统配置 > 本地数据库)。
1. 单击创建新数据库以打开数据库向导。
2. 在文本框中输入数据库名称。数据库名称必须:
- 尚未在 `IRIS` 实例中使用
- 长度在 `1` 到 `30` 个字符之间
- 以字母字符或下划线开头;其余部分可以包括字母数字字符、破折号或下划线
3. 首次使用特定浏览器在 `IRIS` 实例中创建本地数据库时,必须
- 输入数据库目录的名称,在这种情况下,包含 `IRIS.DAT` 文件的目录在确认后将在 `c:\InterSystems\mgr` 中创建
- 单击文件夹图标浏览到现有目录,在这种情况下,将在该目录中创建 `IRIS.DAT` 文件
此后,默认情况下,将在与先前数据库目录相同的位置创建一个与提供的数据库名称相同的目录,其中包含 `IRIS.DAT` 文件。例如,如果首先在 `c:\InterSystems\mgr` 下的任何目录中创建数据库 `db22`,当再次单击 `Create New Database` 并在 `Enter the name of your database` 框中输入 `db33` 时,`c:\InterSystems\mgr\db33` 会自动填写到数据库目录文本框中。如果将其更改为 `c:\InterSystems\db33` 并创建 `db33`,则下次将填充基本目录 `c:\InterSystems`。
注意:不支持在配置数据库目录时使用符号链接。
4. 单击下一步继续配置数据库。如果指定的目录中已经存在 `IRIS.DAT` 文件,会收到警告,并且可以
- 单击完成以使用现有文件,在这种情况下,所有数据库特征都由 `IRIS.DAT` 文件确定。您通常会在从另一个实例复制或移动数据库时执行此操作,或者在同一系统上临时挂载在另一个实例中创建的数据库时执行此操作。
- 单击 `Back` 指定另一个目录,然后再次单击 `Next` 以在下一步中继续指定新数据库的特征。
5. 在 `Initial Size` 文本框中,键入数据库大小的兆字节数(默认值为 `1 MB`)。
**注意:不能创建或编辑数据库,使其大小大于可用的总磁盘空间。如果指定的大小在磁盘可用空间的 `90%` 以内,会收到警告并且必须确认操作。**
6. 从 `Block size for this database will be` 下拉列表中选择所需的块大小。默认情况下,所有新数据库都使用 `8 KB` 的块大小创建。
注意:请勿从下拉列表中选择 `8 KB` 以外的块大小,除非已阅读并理解大块大小注意事项`/`
7. 从 `Journal globals` 中选择是否要在此数据库中记录全局变量`?`下拉列表。
注意:如果将数据库配置为存储临时全局变量,将 `Journal globals` 属性设置为 `No` 与将临时全局变量存储在 IRSTEMP 中是不同的。
8. 如果激活了加密,可以通过选择是加密数据库来加密这个数据库?。
9. 如果实例是镜像的一部分,可以通过为 `Mirrored Database?` 选择 `Yes` 来将此数据库添加到镜像中。
10. 从此面板开始,可以单击下一步。继续配置数据库或完成以接受剩余的默认值。
11. 选择资源来控制对该数据库的访问:
- 默认值 — `%DB_%DEFAULT`
- 现有 - 从现有数据库资源列表中选择
- 新建 — 创建新的数据库资源(新名称默认为 `%DB_%` 数据库名称)
12. 单击下一步查看数据库属性列表。
13. 单击完成以添加数据库。
现在已准备好配置和管理新数据库。
**注意:为防止意外损坏数据库,不能打开或写入名为 `IRIS.DAT` 的操作系统文件,即使它不是已安装的数据库。**
文章
Lilian Huang · 七月 13, 2022
InterSystems Native SDK for Python是 InterSystems IRIS APIs 的轻量级接口,曾经只能通过 ObjectScript 使用。
准确地说,我对调用 ObjectScript 方法、类方法的能力特别感兴趣。 它可以工作,而且效果很好,但默认情况下,调用只支持标量参数:字符串、布尔值、整数和浮点数。
但如果你想:
- 传递或返回结构,例如字典或列表
- 传递或返回流
您需要编写一些粘合代码或使用这个project (使用 pip install edpy 安装)。 edpy 包会给你一个简单的签名:
call(iris, class_name, method_name, args)
它允许您调用任何 ObjectScript 方法并返回结果。
像这样导入它:
from edpy import iris
call accepts 4 required arguments:- iris - a reference to an established IRIS object- class_name - IRIS class to call- method_name - IRIS method to call- args - list of 0 or more arguments
参数
每个参数可以是以下其中之一:
string字符串(任意长度,如果大于 $$$MaxStringLength或 3641144 个符号,则会自动转换为流
boolean布尔值
integer整数
float 浮动
dict字典(转换为动态对象)
list or tuple列表或元组(转换为动态数组)
字典、列表和元组参数可以递归地包含其他字典、列表和元组(持续性内存)。
返回值
在返回值,我们期望是动态对象/数组或 JSON 字符串/流。 在这种情况下,edpy 会首先将其转换为 Python 字符串,并在可能的情况下将其解释为 Python 字典或列表。 否则,结果将按原样返回给调用者。
就是这样,但让我给你一些 ObjectScript 方法的例子,以及如何使用这个 Python 函数调用它们。
示例1: Pong
ClassMethod Test(arg1, arg2, arg3) As %DynamicArray{ return [(arg1), (arg2), (arg3)]}
调为:
>>> iris.call(iris_native, "User.Py", "Test", [1, 1.2, "ABC"])[1, 1.2, 'ABC']
这里没有惊喜。 参数被打包回一个数组并返回给调用者。
示例 2: 属性
ClassMethod Test2(arg As %DynamicObject) As %String{ return arg.Prop}
像这样调用:
>>> iris.call(iris_native, "User.Py", "Test2", [{"Prop":123}])123
现在进行更嵌入式的调用:
>>> iris.call(iris_native, "User.Py", "Test2", [{"Prop":{"Prop2":123}}])
{'Prop2': 123}
如果属性太长也没关系 - 流将用于将其发送到 IRIS 和/或返回:
ret = iris.call(iris_native, "User.Py", "Test2", [{"Prop":"A" * 10000000}])
>>> len(ret)
10000000
如果您需要保证InterSystems IRIS 端的流,您可以使用%Get:
set stream = arg.%Get("Prop",,"stream")
如果流是 base64 编码的,您可以使用以下命令自动对其进行解码:
set stream = arg.%Get("Prop",,"stream<base64")
示例 3: 字符串或流
ClassMethod Test3(arg As %Stream.Object) As %String
{
set file = ##class(%Stream.FileCharacter).%New()
set file.TranslateTable = "UTF8"
set filename = ##class(%File).ManagerDirectory() _ "test.txt"
do file.LinkToFile(filename)
if $isObject(arg) {
set sc = file.CopyFromAndSave(arg)
} else {
do file.Write(arg)
set sc = file.%Save()
}
if $$$ISERR(sc) {
set jsonret = {"status":0, "payload":($system.Status.GetErrorText(sc))}
} else {
set jsonret = {"status":1}
}
quit jsonret.%ToJSON()
}
这里我们将字符串或流写入 <mgr>test.txt。
>>> iris.call(iris_native, "User.Py", "Test3", ["😊"])
{'status': 1}
注意:在所有代码示例中输入为“ x1f642;“。
如果我打开文件,我会看到一个 😊 而不是两个 ?? - 所以我们保留编码。
>>> iris.call(iris_native, "User.Py", "Test3", ["🙂" * 10000000])
{'status': 1}
为简便起见,我将省略文件输出,但它就在那里。
最后,通过在内部传递一个动态对象或数组,您可以完全避免字符串/流二分法,即使您不知道该属性是比字符串限制短还是长。 在这种情况下,您始终可以像流一样获取可疑属性。
示例4: 返回流
ClassMethod Test4(arg As %DynamicArray) As %String
{
return arg.%Get(0)
}
看起来是这样:
>>> ret = iris.call(iris_native, "User.Py", "Test4", [["😊" * 10000000]])
>>> len(ret)
10000000
>>> ret[:5]
'😊😊😊😊😊'
还有一件事
还有一个 get_iris(ip="localhost", port=1972, namespace="USER", username="_SYSTEM", password="SYS") 函数可以让您获得一个工作的 IRIS 对象。
所以这里有一个完整的例子,如果你想自己尝试一下:
首先加载 User.Py class 并安装 edpy python 库:
pip install edpy
然后在python调用中:
from edpy import iris
iris_native = iris.get_iris()
iris.call(iris_native, "User.Py", "Test", [1, 1.2, "ABC"])
iris.call(iris_native, "User.Py", "Test2", [{"Prop":123}])
iris.call(iris_native, "User.Py", "Test2", [{"Prop":{"Prop2":123}}])
ret2 = iris.call(iris_native, "User.Py", "Test2", [{"Prop":"A" * 10000000}])
iris.call(iris_native, "User.Py", "Test3", ["😊"])
iris.call(iris_native, "User.Py", "Test3", ["😊" * 10000000])
ret4 = iris.call(iris_native, "User.Py", "Test4", [["😊" * 10000000]])
结论
适用于 Python 的 Native SDK 是一个强大的工具,为您提供对 InterSystems IRIS 的完整且不受限制的访问。 我希望这个项目可以为您节省一些时间来编组 InterSystems IRIS 调用。 是否有一些它不支持的方法参数组合? 如果是这样,请在评论中分享您是如何调用的。
链接:
Native SDK Docs
User.Py class
Repo
原文请参考链接:https://community.intersystems.com/node/521336
文章
姚 鑫 · 三月 6, 2021
# 第五章 SQL定义表
# 表名称和架构名称
可以通过定义表(使用`CREATE TABLE`)或通过定义投影到表的持久类来创建表:
- DDL:InterSystemsIRIS®数据平台使用CREATE TABLE中指定的表名来生成相应的持久类名,并使用指定的架构名来生成相应的包名。
- 类定义:InterSystemsIRIS®数据平台使用持久类名称来生成对应的表名,并使用包名称来生成对应的模式名。
由于以下原因,这两个名字之间的对应关系可能不相同:
- 持久化类和SQL表遵循不同的命名约定。
适用不同的有效字符和长度要求。
模式和表名不区分大小写;
包名和类名区分大小写。
系统自动将有效提供的名称转换为有效的对应名称,以确保生成的名称是惟一的。
- 持久化类名与对应的SQL表名之间的匹配是默认的。
可以使用`SqlTableName`类关键字来提供不同的SQL表名。
- **默认模式名可能与默认包名不匹配。
如果指定一个非限定的SQL表名或持久类名,系统将提供一个默认的模式名或包名。
初始的默认模式名是`SQLUser`;
初始默认包名为`“User”`。**
# 模式名称
表、视图或存储过程名称可以是限定的(`schema.name`),也可以是限定的(`name`)。
- 如果指定模式名(限定名),则指定的表、视图或存储过程将被分配给该模式。
如果模式不存在,则InterSystems SQL创建模式,并将表、视图或存储过程分配给它。
- 如果没有指定模式名(非限定名),InterSystems SQL将使用默认模式名或模式搜索路径分配模式,如下所述。
## 模式命名注意事项
模式名遵循标识符约定,需要特别注意非字母数字字符的使用。
模式名不应该指定为带分隔符的标识符。
**尝试指定“USER”或任何其他SQL保留字作为模式名会导致`SQLCODE -312`错误。**
`INFORMATION_SCHEMA`模式名和相应的信息。
模式包名在所有命名空间中保留。
用户不应该在这个模式/包中创建表/类。
当执行一个创建操作(比如`create TABLE`),指定一个还不存在的模式时,InterSystems IRIS将创建新的模式。
InterSystems IRIS使用模式名生成相应的包名。
由于模式及其对应包的命名约定不同,用户应该注意非字母数字字符的名称转换注意事项。
这些名称转换的注意事项与表不同:
- 初始字符:
- `%` (percent):指定%作为模式名的第一个字符,表示相应的包为系统包,其所有类为系统类。
这种用法需要适当的权限;
否则,这种用法会发出一个`SQLCODE -400`错误,`%msg`表示``错误。
- **`_`(下划线):如果模式名的第一个字符为下划线,则该字符将被对应包名中的小写`“u”`替换。
例如,模式名`_MySchema`生成名为`uMySchema`的包。**
- 后续的字符:
- **`_`(下划线):如果模式名第一个字符以外的其他字符是下划线,则该字符将被对应包名中的句点(`.`)替换。
由于句点是类的分隔符,下划线将模式分为包和子包。
因此,`My_Schema`生成包含包模式(`My.Schema`)的包My。**
- **`@`, `#`, `$` characters:如果模式名包含任何这些字符,这些字符将从相应的包名中剥离。
如果剥离这些字符会产生重复的包名,那么将进一步修改剥离的包名:将剥离的模式名的最后一个字符替换为顺序整数(以0开始),以产生唯一的包名。
因此,`My@#$Schema`生成`MySchema`包,然后创建`My#$Schema`生成`MySchem0`包。
同样的规则也适用于表名对应的类名。**
## 保留模式名
`INFORMATION_SCHEMA`模式名和相应的信息。
模式包名在所有命名空间中保留。
用户不应该在这个模式/包中创建表/类
在所有名称空间中保留`IRIS_Shard`模式名。
用户不应在此模式中创建表、视图或过程。
存储在`IRIS_Shard`模式中的项不会通过编目查询或`INFORMATION_SCHEMA`查询显示。
## 默认模式名称
- 在执行DDL操作(例如创建或删除表、视图、触发器或存储过程)时,会提供一个非限定名称作为默认的模式名。
架构搜索路径值将被忽略。
- 在执行DML操作时,例如通过选择、调用、插入、更新或删除访问现有表、视图或存储过程,将从模式搜索路径(如果提供了)提供一个不限定的名称。
如果没有架构搜索路径,或者没有使用架构搜索路径定位指定项,则提供默认的架构名称。
初始设置是对所有名称空间(系统范围)使用相同的默认模式名。
可以为所有命名空间设置相同的默认模式名,也可以为当前命名空间设置默认模式名。
如果创建了一个具有非限定名称的表或其他项,InterSystems IRIS将为其分配默认模式名和相应的持久类包名。
如果一个命名的或默认的模式不存在,InterSystems IRIS将创建模式(和包),并将创建的项分配给该模式。
如果删除模式中的最后一项,InterSystems IRIS将删除该模式(和包)。
下面的模式名解析描述适用于表名、视图名和存储过程名。
系统范围的初始默认模式名是`SQLUser`。
对应的持久类包名是`User`。
因此,非限定表名`Employee`或限定表名`SQLUser`。
`Employee`将生成类`User.Employee`。
因为`USER`是一个保留字,尝试用`USER`的模式名(或任何SQL保留字)指定限定名会导致`SQLCODE -1`错误。
**要返回当前默认模式名,请调用`$SYSTEM.SQL.DefaultSchema()`方法:**
```java
DHC-APP>WRITE $SYSTEM.SQL.DefaultSchema()
SQLUser
```
或者使用以下预处理器宏:
```java
#Include %occConstant
WRITE $$$DefSchema
```
可以使用以下任意一种方式更改默认模式名:
- 进入管理界面。
在系统管理中,选择Configuration,然后选择SQL和对象设置,然后选择SQL。
在这个屏幕上,可以查看和编辑当前系统范围内的默认模式设置。
这个选项设置系统范围的默认模式名。

这个系统范围的设置可以被当前命名空间的`SetDefaultSchema()`方法值覆盖。
- `$SYSTEM.SQL.SetDefaultSchema()`方法。默认情况下,此方法在系统范围内设置默认架构名称。但是,通过将布尔值第3个参数设置为1,可以仅为当前名称空间设置默认架构。当不同的名称空间具有不同的默认架构名称时,`DefaultSchema()`方法将返回当前名称空间的默认架构名称。
**注意:当更改默认的SQL模式名称时,系统将自动清除系统上所有名称空间中的所有缓存查询。
通过更改默认模式名称,可以更改所有包含非限定表、视图或存储过程名称的查询的含义。
强烈建议在安装InterSystems IRIS时建立默认的SQL模式名,以后不要修改。**
模式名用于生成相应的类包名。
因为这些名称有不同的命名约定,所以它们可能不相同。
可以通过将其设置为系统范围的默认模式来创建与SQL保留字同名的模式,但是不建议这样做。
名为`User`的默认模式根据类命名唯一性约定,生成相应的类包名称`User0`。
### `_CURRENT_USER`关键字
- 作为系统范围的默认模式名:如果指定`_CURRENT_USER`作为默认模式名,InterSystems IRIS将指定当前登录进程的用户名作为默认模式名。
`_CURRENT_USER`值是`$USERNAME` ObjectScript特殊变量值的第一部分。
如果`$USERNAME`包含一个名字和一个系统地址(`Deborah@TestSys`), `_CURRENT_USER`只包含名字片段;
这意味着`_CURRENT_USER`可以将相同的默认模式名分配给多个用户。
如果进程没有登录,`_CURRENT_USER`指定`SQLUser`作为默认的模式名。
如果指定`_CURRENT_USER/name`作为默认模式名,其中name是选择的任意字符串,那么InterSystems IRIS将当前登录进程的用户名分配为默认模式名。
如果进程没有登录,则name将用作默认的模式名。
例如,如果进程没有登录,`_CURRENT_USER/HMO`使用HMO作为默认模式名。
在`$SYSTEM.SQL.SetDefaultSchema()`中,指定`"_CURRENT_USER"`作为带引号的字符串。
- DDL命令中的模式名:如果在DDL语句中指定`_CURRENT_USER`作为显式的模式名,InterSystems IRIS将其替换为当前系统范围内的默认模式。
例如,如果系统范围的默认模式是`SQLUser`,则命令`DROP TABLE _CURRENT_USER`。
`OldTable SQLUser.OldTable`下降。
这是一种方便的方式来限定名称,以显式地指示应该使用系统范围的默认模式。
它在功能上与指定非限定名相同。
此关键字不能在DML语句中使用。
## 模式搜索路径
当访问一个现有的表(或视图,或存储过程)进行DML操作时,将从模式搜索路径中提供一个非限定的名称。
按照指定的顺序搜索模式,并返回第一个匹配项。
如果在搜索路径中没有找到匹配的模式,或者没有搜索路径,则使用默认的模式名。
(注意,`#Import`宏指令使用了不同的搜索策略,不会“失败”到默认的模式名。)
- 在嵌入式SQL中,可以使用`#SQLCompile Path`宏指令或`#Import`宏指令来提供架构搜索路径,系统间IRIS使用该路径来解析非限定名称。
`#SQLCompile Path`根据遇到的第一个匹配项解析不限定的名称。
如果搜索路径中列出的所有模式只有一个匹配项,则`#Import`解析非限定名。
- 下面的示例提供了包含两个模式名的搜索路径:
```java
#SQLCompile Path=Customers,Employees
```
- 在动态SQL中,可以使用`%SchemaPath`属性提供模式搜索路径,系统间IRIS使用该路径解析不限定的表名。
可以直接指定`%SchemaPath`属性,也可以将其指定为`%SQL`的第二个参数。
声明`%new()`方法。
下面的示例提供了包含两个模式名的搜索路径:
```java
SET tStatement = ##class(%SQL.Statement).%New(0,"Customers,Employees")
```
- 在SQL Shell中,可以设置`PATH SQL Shell`配置参数来提供架构搜索路径,系统间IRIS使用该路径解析不限定的名称。
如果非限定名与模式搜索路径中指定的任何模式或默认模式名不匹配,则会发出`SQLCODE -30`错误,例如:`SQLCODE: -30`消息:`Table 'PEOPLE' not found in schemas: CUSTOMERS,EMPLOYEES,SQLUSER`。
## 包含特定于平台的模式名
当创建一个基于odbc的查询以通过Mac上的Microsoft query从Microsoft Excel运行时,如果从可用的表列表中选择一个表,则生成的查询不包括该表的模式(相当于类的包)。
例如,如果选择从示例模式返回`Person`表的所有行,则生成的查询为:
```java
SELECT * FROM Person
```
**因为InterSystems IRIS将不限定的表名解释为`SQLUser`模式中的表名,所以该语句要么失败,要么从错误的表返回数据。
要纠正这一点,编辑查询(在SQL View选项卡上),显式引用所需的模式。
然后查询应该是:**
```java
SELECT * FROM Sample.Person
```
## List模式
`INFORMATION.SCHEMA`。
`SCHEMATA persistent`类列出当前名称空间中的所有模式。
下面的示例返回当前命名空间中的所有非系统模式名:
```java
SELECT SCHEMA_NAME
FROM INFORMATION_SCHEMA.SCHEMATA WHERE NOT SCHEMA_NAME %STARTSWITH '%'
```
Management Portal SQL界面的左侧允许查看模式(或匹配筛选器模式的多个模式)的内容。
# 表名
每个表在其模式中都有一个唯一的名称。
一个表有一个SQL表名和一个对应的持久化类名;
这些名称在允许的字符、区分大小写和最大长度方面有所不同。
如果使用SQL `CREATE TABLE`命令定义,则指定遵循标识符约定的SQL表名;
系统生成一个对应的持久化类名。
如果定义为持久类定义,则必须指定只包含字母和数字字符的名称;
这个名称既用作区分大小写的持久类名,也用作(默认情况下)对应的不区分大小写的SQL表名。
可选的`SqlTableName class`关键字允许用户指定不同的SQL表名。
当使用`CREATE TABLE`命令创建表时,InterSystems IRIS使用表名生成相应的持久化类名。
由于表及其对应类的命名约定不同,用户应该注意非字母数字字符的名称转换:
- 初始字符:
- `%` (percent): %作为表名的第一个字符是保留的,应该避免(参见标识符)。
如果指定了,`%`字符将从对应的持久化类名中剥离。
- `_`(下划线):如果表名的第一个字符是下划线,则该字符将从对应的持久化类名中剥离。
例如,表名`_MyTable`生成类名`MyTable`。
- 数字:表名的第一个字符不能是数字。
如果表名的第一个字符是标点符号,则第二个字符不能是数字。
这将导致一个`SQLCODE -400`错误,`%msg`值为`" error #5053:类名'schema.name' is invalid "`(没有标点字符)。
例如,指定表名`_7A`会生成`%msg " ERROR #5053: Class name 'User.7A' is invalid "`。
- 后续的字符:
- 字母:表名中至少包含一个字母。
表名的第一个字符或初始标点字符后的第一个字符必须是字母。
如果一个字符通过`$ZNAME`测试,它就是一个有效的字母;
`$ZNAME`字母验证因不同的地区而不同。
(注意,$ZNAME不能用于验证SQL标识符,因为标识符可能包含标点字符。)
- `_`(下划线),`@`,`#`,`$` characters:如果表名包含这些字符中的任何一个,这些字符将从对应的类名中剥离出来,并生成一个唯一的持久类名。
由于生成的类名不包括标点字符,因此不建议创建仅在标点字符上不同的表名。
- 表名在其模式中必须是唯一的。
如果试图创建一个名称仅与现有表大小写不同的表,将会产生`SQLCODE -201`错误。
同一个模式中的视图和表不能具有相同的名称。
尝试这样做会导致`SQLCODE -201`错误。
可以使用`$SYSTEM.SQL.TableExists()`方法确定一个表名是否已经存在。
可以使用`$SYSTEM.SQL.ViewExists()`方法确定视图名是否已经存在。
这些方法还返回与表或视图名称对应的类名。
管理门户SQL interface Catalog Details表信息选项显示与所选SQL表名称对应的类名。
试图指定`“USER”`或任何其他SQL保留字作为表名或模式名会导致`SQLCODE -312`错误。
要指定SQL保留字作为表名或模式名,可以指定名称作为带分隔符的标识符。
如果使用带分隔符的标识符指定包含非字母数字字符的表或模式名,InterSystems IRIS将在生成相应的类或包名时删除这些非字母数字字符。
适用以下表名长度限制:
- 唯一性:InterSystems IRIS对持久化类名的前189个字符执行唯一性检查。
对应的SQL表名可能超过189个字符,但是,当去掉非字母数字字符时,它必须在189个字符的限制内是唯一的。
InterSystems IRIS对包名的前189个字符执行唯一性检查。
- 建议最大长度:一般来说,一个表名不应该超过128个字符。
一个表名可能比96个字符长得多,但是在前96个字母数字字符中不同的表名更容易处理。
- 最大组合长度:包名和它的持久类名(加在一起时)不能超过220个字符。
这包括默认的模式(包)名(如果没有指定模式名)和分隔包名和类名的点字符。
当表名转换为对应的持久化类名时,删除超过220个字符时,模式和表名的组合长度可以超过220个字符。
# RowID字段
**在SQL中,每条记录都由一个唯一的整数值标识,这个整数值称为`RowID`。**
在InterSystems SQL中,不需要指定`RowID`字段。
当创建表并指定所需的数据字段时,会自动创建RowID字段。
这个`RowID`在内部使用,但没有映射到类属性。
默认情况下,只有当持久化类被投影到SQL表时,它的存在才可见。
在这个投影表中,将出现一个额外的`RowID`字段。
默认情况下,这个字段被命名为`“ID”`,并分配给第1列。
默认情况下,当在表中填充数据时,InterSystems IRIS将从1开始向该字段分配连续的正整数。`RowID`数据类型为`BIGINT(%Library.BigInt)`。为`RowID`生成的值具有以下约束:每个值都是唯一的。不允许使用`NULL`值。排序规则是精确的。**默认情况下,值不可修改。**
默认情况下,InterSystems IRIS将此字段命名为`“ ID”`。但是,此字段名称不是保留的。每次编译表时都会重新建立`RowID`字段名。如果用户定义了一个名为`“ ID”`的字段,则在编译表时,InterSystems IRIS会将`RowID`命名为`“ ID1”`。例如,如果用户随后使用`ALTER TABLE`定义了一个名为`“ ID1”`的字段,则表编译会将`RowID`重命名为`“ ID2”`,依此类推。在持久性类定义中,可以使用`SqlRowIdName`类关键字直接为此类投影到的表指定`RowID`字段名。由于这些原因,应避免按名称引用`RowID`字段。
InterSystems SQL提供了`%ID`伪列名称(别名),无论分配给`RowID`的字段名称如何,该伪列名称始终返回`RowID`值。 (InterSystems TSQL提供了`$IDENTITY`伪列名称,其作用相同。)
`ALTER TABLE`无法修改或删除`RowID`字段定义。
将记录插入表中后,InterSystems IRIS将为每个记录分配一个整数ID值。 `RowID`值始终递增。它们不被重用。因此,如果已插入和删除记录,则`RowID`值将按升序排列,但可能不连续。
- **默认情况下,使用`CREATE TABLE`定义的表使用`$SEQUENCE`执行`ID`分配,从而允许多个进程快速同时填充该表。当使用`$SEQUENCE`填充表时,会将`RowID`值序列分配给进程,然后该进程将顺序分配它们。因为并发进程使用它们自己分配的序列分配`RowID`,所以不能假定多个进程插入的记录按插入顺序排列。**
可以通过设置`SetDDLUseSequence()`方法,将InterSystems IRIS配置为使用`$INCREMENT`执行`ID`分配。若要确定当前设置,请调用`$ SYSTEM.SQL.CurrentSettings()`方法。
- 默认情况下,通过创建持久性类定义的表将使用`$INCREMENT`执行ID分配。在持久性类定义中,可以将`IdFunction`存储关键字设置为序列或增量;否则,可以设置为0。例如,`序列`。
在持久性类定义中,`IdLocation`存储关键字global(例如,对于持久性类`Sample.Person: ^ Sample.PersonD `)包含RowID计数器的最高分配值。 (这是分配给记录的最高整数,而不是分配给进程的最高整数。)请注意,此RowID计数器值可能不再与现有记录相对应。要确定是否存在具有特定RowID值的记录,请调用表的`%ExistsId()`方法。
通过`TRUNCATE TABLE`命令重置`RowID`计数器。即使使用`DELETE`命令删除表中的所有行,也不会通过`DELETE`命令将其重置。如果没有数据插入表中,或者已使用`TRUNCATE TABLE`删除所有表数据,则`IdLocation`存储关键字全局值未定义。
默认情况下,`RowID`值不可用户修改。尝试修改`RowID`值会产生`SQLCODE -107`错误。覆盖此默认值以允许修改`RowID`值可能会导致严重的后果,只有在非常特殊的情况下并应格外谨慎。 `Config.SQL.AllowRowIDUpdate`属性允许`RowID`值是用户可修改的。
## 基于字段的RowID
通过定义一个用于投影表的持久类,可以定义`RowID`以具有字段或字段组合中的值。为此,请使用`IdKey index`关键字指定一个索引。例如,一个表可以具有一个`RowID`,其`RowId`通过在`PatientName [IdKey]`上指定索引定义`IdxId`来与`PatientName`字段的值相同;或者可以通过指定索引定义`IdxId`来将`PatientName`和`SSN`字段的组合值在`(PatientName,SSN)[IdKey];`上。
- 基于字段的`RowID`效率比采用系统分配的连续正整数的`RowId`效率低。
- 在`INSERT`上:为构成`RowId`的字段或字段组合指定的值必须唯一。指定非唯一值将生成`SQLCODE -119`“在插入时唯一性或主键约束唯一性检查失败”。
- 在`UPDATE`上:默认情况下,组成`RowId`的每个字段的值都是不可修改的。尝试修改这些字段之一的值会生成`SQLCODE -107`“无法基于字段更新`RowID`或`RowID`”。
当`RowID`基于多个字段时,`RowID`值是由`||`连接的每个组成字段的值。操作员。例如,`Ross,Betsy || 123-45-6789`。 InterSystems IRIS尝试确定基于多个字段的`RowID`的最大长度。如果无法确定最大长度,则`RowID`长度默认为512。
## 隐藏的RowID?
- 使用`CREATE TABLE`创建表时,默认情况下隐藏`RowID`。 `SELECT *`不会显示隐藏字段,而是`PRIVATE`。创建表时,可以指定`%PUBLICROWID`关键字以使`RowID`不隐藏和公开。可以在`CREATE TABLE`逗号分隔的表元素列表中的任何位置指定此可选的`%PUBLICROWID`关键字。不能在`ALTER TABLE`中指定。
- 创建作为表投影的持久类时,默认情况下不会隐藏`RowID`。它由`SELECT *`显示,并且是`PUBLIC`。可以通过指定类关键字`SqlRowIdPrivate`来定义具有隐藏且为`PRIVATE`的`RowID`的持久类。
用作外键引用的`RowID`必须是公共的。
默认情况下,不能将具有公共`RowID`的表用作源表或目标表,以使用`INSERT INTO Sample.DupTable SELECT * FROM Sample.SrcTable`将数据复制到重复表中。
可以使用Management Portal SQL界面“目录详细信息字段”列出“隐藏”列来显示`RowID`是否被隐藏。
可以使用以下程序返回指定字段(在此示例中为`ID`)是否被隐藏:
```java
/// d ##class(PHA.TEST.SQL).RowID()
ClassMethod RowID()
{
SET myquery = "SELECT FIELD_NAME,HIDDEN FROM %Library.SQLCatalog_SQLFields(?) WHERE FIELD_NAME='ID'"
SET tStatement = ##class(%SQL.Statement).%New()
SET qStatus = tStatement.%Prepare(myquery)
IF qStatus'=1 {
WRITE "%Prepare failed:"
DO $System.Status.DisplayError(qStatus)
QUIT
}
SET rset = tStatement.%Execute()
DO rset.%Display()
WRITE !,"End of data"
}
```
最后一个占位符使用案例很棒!谢谢 总结的很好
公告
Claire Zheng · 十月 20, 2022
2022年9月5日-10月24日(北京时间),我们正在举办🏆InterSystems开发者社区中文版首届技术征文大赛🏆(←点击链接进入参赛页面,浏览所有参赛文章)!投票截止至10月23日,你的支持与喜爱,是优秀作品获得“开发者社区奖”的关键!我们先来看看目前作品排名情况吧!距离投票截止还有三天(截止至10月23日),我们暂时无法获得专家评审分数,以下根据作品“点赞”进行排名(排名截至10月21日10时)。
N
Author
标题
点赞⬇
1
Meng Cao
Caché数据库私有apache版本升级
42
2
Zhe Wang
IRIS如何进行CRUD操作
37
3
sun yao
前端操作自动生成BS、BP、BO
26
4
John Pan
论集成标准的选择对医院信息集成平台建设的影响
23
5
lizw lizw
关于%Dictionary.CompiledClass类在实际业务中的一些应用
23
6
聆严 周
使用Prometheus监控Cache集群
21
7
Chang Liu
在国产系统上安装Healthconnect2021
19
8
Zhe Wang
IRIS快速查询服务思路分享
18
9
Zhe Wang
使用Global进行数据可视化---商业智能(BI)
18
10
John Pan
如何调用Ensemble/IRIS内置的HL7 V2 webservice - Java,PB9,Delphi7样例
17
11
zhanglianzhu zhanglianzhu
Cache死循环检测和申明式事务
16
12
Zhe Wang
Rest实现Post、Get、Put、Delete几种操作方式
15
13
shaosheng shengshao
HEALTHSHARE2018版如何实现AES(CBC)的HEX输出,并可以实现加密和解密
15
14
姚 鑫
IRIS与Caché的23种设计模式
15
15
water huang
对 %XML.PropertyParameters类的探索
15
16
Zhe Wang
小工具:IRIS管理页打开显示查询功能
15
17
聆严 周
Cache / IRIS 操作数据的3种基本方式
14
18
he hf
10分钟快速开发一个连接到InterSystems IRIS数据库的C#应用
14
19
shaosheng shengshao
windows下处理IIS在未安装但Healthshare已安装的时候,部署IIS服务并代理Healthshare
11
20
water huang
Ens.Util.JSON类的启发
11
21
bai hongtao
第三方HA软件结合MIRROR使用方法探讨
11
22
li wang
HealthConnect访问HTTPS开头地址
10
23
Liu Tangh
在Cache系统中使用负载均衡服务的探讨
9
24
yaoguai wan
IRIS架构的浅显理解以及windows10、docker安装IRIS Health详解流程及部分问题浅析
7
25
li dong
实现Cache/IRIS中zip文件的下载、解压及读取
7
26
姚 鑫
CORS请求Request携带Cookie失败占用License解决方案
5
27
Zhe Wang
COS的基本语法
5
*奖励项目详见参赛规则:点击阅读
我们此次征文大赛计分规则如下:
🥇【专家提名奖】评选规则,由经验丰富的专家评审团进行评选打分,与其他加分项综合后进行排名。
🥇【开发者社区奖】评选规则,每个点赞计分为1分,与其他加分项综合后进行排名。
🥇【入围奖】评选规则,成功参赛的其余用户都将获得特别奖励。
每位作者只可以获得一个奖项(即:您只可以获得一次专家提名奖/开发者社区奖/入围奖);
当出现票数相当的平手情况时,将以专家评选投票数作为最终票数高低的判断标准。
那么,抓住最后五天的投票时间,为你喜欢的作品“点赞”投票吧!你的点赞是优秀作品获得【开发者社区奖】的关键!
10月24日晚19:30-20:30,我们将举办“InterSystems首届技术征文大赛线上分享会”,发布获奖名单,敬请留意后续参会信息!
欢迎关注InterSystems开发者社区中文版首届技术征文大赛
文章
Hao Ma · 十一月 26, 2022
## 建立私服(Porxy-Registry)
这张图解释了您的私服是怎么工作的, 整篇文章在这里: [Proxy-Registry](https://community.intersystems.com/post/new-zpm-registry-feature-%E2%80%93-proxy-registry)

### 搭建私服
您需要有一台自己的的服务器, 在上面安装IRIS, zpm, 然后用zpm去下载另一个软件包“zpm-registry"。象这样
```sh
zpm:DEMO>search -r zpm-registry
registry https://pm.community.intersystems.com:
zpm-registry 1.1.11Repository: https://github.com/intersystems-community/zpm-registry/
zpm:DEMO>install zpm-registry
[DEMO|zpm-registry] Reload START (/usr/irissys/mgr/.modules/DEMO/zpm-registry/1.1.11/)
[DEMO|zpm-registry] Reload SUCCESS
[zpm-registry] Module object refreshed.
[DEMO|zpm-registry] Validate START
[DEMO|zpm-registry] Validate SUCCESS
[DEMO|zpm-registry] Compile START
[DEMO|zpm-registry] Compile SUCCESS
[DEMO|zpm-registry] Activate START
[DEMO|zpm-registry] Configure START
[DEMO|zpm-registry] Configure SUCCESS
[DEMO|zpm-registry] Activate SUCCESS
zpm:DEMO>
```
到github页面, https://github.com/intersystems-community/zpm-registry/, 你可以得到更详细的软件信息。
配置私服连接公服, 需要在私服的IRIS的安装目录添加一个yaml文件, 定义uplink:
```yaml
uplinks:
pm:
url: https://pm.community.intersystems.com/
allow_packages: dsw,zpm*,?u*
```
几点说明:
- uplinks的项目可以有多个,pm是intersystems的默认公共registry
- allow_packages: - a comma-separated list of allowed packages, you can use the exact package name or mask: * - any sequence of characters, ? - any charac
- registry 提供的rest 接口描述: https://pm.community.intersystems.com/_spec
### 设置zpm client连接私服
通过repo命令将您的zpm client切换到刚刚配置的私服。`repo -n registry`里面的 - user, - pass是你搭建的私服的账号密码。您也可以在私服上修改/registryWeb应用不做用户验证。
```sh
zpm:DEMO>repo -list
registry
Source: https://pm.community.intersystems.com
Enabled? Yes
Available? Yes
Use for Snapshots? Yes
Use for Prereleases? Yes
Is Read-Only? No
Deployment Enabled? No
zpm:DEMO>repo -n registry -r -url http://localhost:52773/registry/ -user superuser -pass demo
registry
Source: http://localhost:52773/registry/
Enabled? Yes
Available? Yes
Use for Snapshots? Yes
Use for Prereleases? Yes
Is Read-Only? No
Deployment Enabled? No
Username: superuser
Password:
zpm:DEMO>
```
这时的私服时没有连接公服。
### 发布软件包到私服
**发布一个 GitHub 的包**
先把软件存在github, 然后用curl命令把包发布在私服的地址。
```sh
$ curl -i -X POST -H "Content-Type:application/json" -u superuser:1104 -d '{"repository":"https://github.com/psteiwer/ObjectScript-Math"}' 'http://localhost:52773/registry/package’
```
**使用zpm 客户端先在本地load,然后使用publish 命令**
大概像这个样子:
```sh
zpm:USER>help load
...
■ Examples
∙ load C:\module\root\path\
load C:\module\root\path\module-0.0.1.tgz
Loads the module described in C:\module\root\path\module.xml
∙ load -dev -verbose C:\module\root\path\
load -dev -verbose C:\module\root\path\module-0.0.1.tgz
Loads the module described in C:\module\root\path\module.xml in developer mode and with verbose output.
∙ load https://github.com/user/repository.git
load https://github.com/user/repository.git -b branch-name
Loads the module described in C:\module\root\path\module.xml in developer mode and with verbose output.
zpm:USER> load https://github.com/user/repository.git
zpm: USER> publish
```
## 其他的Feature
在使用中您还会有各种各样的需求, 但我相信看到现在您应该对怎么寻找答案非常清楚了。这里简单的说两个feautre
### 1. 发布为Delopyed模式
如果您要隐藏自己的代码,只发布编译后的软件, 可以简单的修改Module.xml, 设置““, zpm会自动完成。
### 2. 包的依赖
因为有朋友问,所以说一些包依赖的功能。是的, zpm是设计了包依赖的功能的,在module.xml里添加Dependencies节点, 可以定被依赖的包的列表。 具体的写法请参见这个例子:[module.xml example](https://github.com/intersystems/ipm/wiki/03.-Module.xml#modulexml-example)。
虽然但是,对ObjectScript程序来说,定义包依赖的机会并不多。我能想到的应用场景就是, 当您的软件中想用社区其他包,比如上面的bitmap-adoption的包的话,您可以包"bitmap-adoption"打包到module.xml里面。
我对当前发布的200多软件包随便挑了一些,还没有发现有哪个使用了包依赖, 象这样:
```sh
zpm:USER>list-dependents yaml-utils
zpm:USER>list-dependents terminal-multiline-editor
zpm:USER>list-dependents bitmap-adoption
zpm:USER>list-dependents global-dump-sql
...
```
文章
姚 鑫 · 五月 19, 2021
# IRIS 单元测试
# [第一章 单元测试概述☆☆☆☆](https://yaoxin.blog.csdn.net/article/details/116884316)
# [第二章 使用%UnitTest进行单元测试☆☆☆☆](https://yaoxin.blog.csdn.net/article/details/116906659)
# [第三章 执行测试☆☆☆](https://yaoxin.blog.csdn.net/article/details/116974672)
# [第四章 使用Setup和tear Down方法执行测试☆☆☆](https://yaoxin.blog.csdn.net/article/details/117014533)
# 前言
IRIS提供了用于对应用程序进行单元测试的类的%UnitTest包。该包为快速开发单元测试类、执行测试和创建报告提供了便利。可以直接使用该包,也可以扩展其类来自定义单元测试工具。%UnitTest在结构上与用于单元测试的xUnit框架非常相似。熟悉这些框架的开发人员使用%UnitTest会特别容易。
本教程提供对%UnitTest包的快速实践介绍。本教程的第一部分和第二部分是相互独立的,可以按任何顺序完成。
- 完成本教程的第一部分,了解单元测试和集成测试之间的区别、xUnit框架和%UnitTest之间的结构相似性,以及单元测试在敏捷应用程序开发方法中的作用。
- 完成本教程的第二部分,学习如何使用%UnitTest中的类为InterSystems IRIS应用程序创建和执行单元测试。
注意:本教程假定基本熟悉ObjectScript和InterSystems IRIS的面向对象开发。
# 预告
下一期系列将用一个月的时间连载,**《Caché 网络实用工具》**,敬请期待。
# 交流群
- QQ群号:410039091
- 笔者QQ:454115408
- 公众号:技术理科直男
- [intersys版主:姚鑫](https://cn.community.intersystems.com/user/236891/posts)
![\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f9VqwzNP-1608850948003)(3E1D939266954ED48BDAEA9B8086B11E)\]](https://img-blog.csdnimg.cn/20201225070433434.png)