清除过滤器
文章
姚 鑫 · 三月 10, 2021
# 第七章 SQL表之间的关系
要在表之间强制执行引用完整性,可以定义外键。修改包含外键约束的表时,将检查外键约束。
# 定义外键
有几种方法可以在InterSystems SQL中定义外键:
- 可以定义两个类之间的关系。定义关系会自动将外键约束投影到SQL。
- 可以在类定义中添加显式外键定义(对于关系未涵盖的情况)。
- 可以使用`CREATE TABLE`或`ALTER TABLE`命令添加外键。可以使用`ALTER TABLE`命令删除外键。
用作外键引用的`RowID`字段必须是公共的。引用隐藏的`RowID`?有关如何使用公用(或专用)`RowID`字段定义表的信息。
**一个表(类)的外键最大数目为400。**
## 外键引用完整性检查
外键约束可以指定更新或删除时的引用操作。
在`CREATE TABLE reference action`子句中描述了使用DDL定义这个引用操作。
在类定义引用的`OnDelete`和`OnUpdate`外键关键字中定义了一个持久化类来定义这个引用操作,该类投射到一个表。
在创建分片表时,这些引用操作必须设置为无操作。
默认情况下,InterSystemsIRIS®数据平台对`INSERT`,`UPDATE`和`DELETE`操作执行外键引用完整性检查。如果该操作将违反参照完整性,则不会执行;该操作将发出`SQLCODE -121,-122,-123或-124`错误。参照完整性检查失败会生成如下错误:
```java
错误#5540:SQLCODE:-124消息:表'HealthLanguage.FKey2'中至少存在1行,该行引用键NewIndex1-外键约束'NewForeignKey1'(字段'Pointer1')的NO ACTION引用操作失败[Execute + 5 ^ IRISSql16:USER]
```
可以使用`$SYSTEM.SQL.SetFilerRefIntegrity()`方法在系统范围内禁止此检查。若要确定当前设置,请调用`$SYSTEM.SQL.CurrentSettings()`。
默认情况下,当删除带有外键的行时,InterSystems IRIS将在相应的被引用表的行上获取长期(直到事务结束)共享锁。这样可以防止在引用行上的`DELETE`事务完成之前对引用行进行更新或删除。这样可以防止删除引用行,然后回退删除引用行的情况。如果发生这种情况,外键将引用不存在的行。如果使用`NoCheck`定义外键,或者使用`%NOCHECK`或`%NOLOCK`指定引用行的`DELETE`,则不会获取此锁定。
使用持久性类定义定义表时,可以使用`NoCheck`关键字定义外键,以禁止将来对该外键进行检查。` CREATE TABLE`不提供此关键字选项。
可以使用`%NOCHECK`关键字选项禁止检查特定操作。
默认情况下,InterSystems IRIS还对以下操作执行外键引用完整性检查。如果指定的操作违反了引用完整性,则不执行该命令:
- `ALTER TABLE DROP COLUMN`。
- `ALTER TABLE DROP CONSTRAINT`删除约束
问题`-317 SQLCODE`。
可以使用`SET`选项`COMPILEMODE=NOCHECK`来抑制外键完整性检查。
- 删除表。问题`-320 SQLCODE`。可以使用`SET`选项`COMPILEMODE = NOCHECK`来抑制外键插入检查。
- 触发器事件,包括事件之前。
例如,如果删除操作因违反外键引用完整性而不能执行,则不会执行`BEFORE DELETE`触发器。
在父/子关系中,没有定义子元素的顺序。
应用程序代码不能依赖于任何特定的顺序。
# 父表和子表
## 定义父表和子表
在定义投射到表的持久类时,可以使用`relationship`属性指定两个表之间的父/子关系。
下面的例子定义了父表:
```java
Class Sample.Invoice Extends %Persistent
{
Property Buyer As %String(MAXLEN=50) [Required];
Property InvoiceDate As %TimeStamp;
Relationship Pchildren AS Sample.LineItem [ Cardinality = children, Inverse = Cparent ];
}
```
下面的例子定义了一个子表:
```java
Class Sample.LineItem Extends %Persistent
{
Property ProductSKU As %String;
Property UnitPrice As %Numeric;
Relationship Cparent AS Sample.Invoice [ Cardinality = parent, Inverse = Pchildren ];
}
```
注意这两句话:
- `Relationship Pchildren AS Sample.LineItem [ Cardinality = children, Inverse = Cparent ];`
- `Relationship Cparent AS Sample.Invoice [ Cardinality = parent, Inverse = Pchildren ];`
在Management Portal SQL interface Catalog Details选项卡中,表信息提供了子表和/或父表的名称。
如果是子表,则提供对父表的引用,如:`parent->Sample.Invoice`。
子表本身可以是子表的父表。
(子表的子表被称为“孙”表。)
在本例中,表`Info`提供了父表和子表的名称。
## 向父表和子表插入数据
在将相应的记录插入子表之前,必须将每个记录插入父表。
例如:
```java
INSERT INTO Sample.Invoice (Buyer,InvoiceDate) VALUES ('yaoxin',CURRENT_TIMESTAMP)
```
```java
INSERT INTO Sample.LineItem (Cparent,ProductSKU,UnitPrice) VALUES (1,'45-A7',99.95)
INSERT INTO Sample.LineItem (Cparent,ProductSKU,UnitPrice) VALUES (1,'22-A1',0.75)
```

尝试插入没有对应父记录ID的子记录时,会使用`%msg`子表`'Sample生成SQLCODE -104错误。
LineItem'`引用父表中不存在的行。
在子表上的插入操作期间,在父表的相应行上获得共享锁。
在插入子表行时,该行被锁定。
然后,锁被释放(直到事务结束时才被持有)。
这确保了在插入操作期间引用的父行不会被更改。
## 标识父表和子表
在嵌入式SQL中,可以使用主机变量数组来标识父表和子表。
在子表中,主机变量数组的下标0被设置为父引用(`Cparent`),格式为parentref,下标1被设置为子记录ID,格式为`parentref|| childf`。
在父表中,没有定义下标0。
如下面的例子所示:
```java
/// d ##class(PHA.TEST.SQL).FatherChildTable()
ClassMethod FatherChildTable()
{
KILL tflds,SQLCODE,C1
&sql(DECLARE C1 CURSOR FOR
SELECT *,%TABLENAME INTO :tflds(),:tname
FROM Sample.Invoice)
&sql(OPEN C1)
IF SQLCODE
文章
姚 鑫 · 四月 9, 2021
# 第二十一章 导入和导出SQL数据
在InterSystems IRIS®Data Platform Management Portal中,有用于导入和导出数据的工具:
- 从文本文件导入数据
- 将数据导出到文本文件
这些工具使用动态SQL,这意味着查询是在运行时准备和执行的。可以导入或导出的行的最大大小为3,641,144个字符。
还可以使用%SQL.Import.Mgr类导入数据,使用%SQL.Export.Mgr类导出数据。
# 从文本文件导入数据
可以将数据从文本文件导入到合适的InterSystems IRIS类中。执行此操作时,系统将在表中为该类创建并保存新行。该类必须已经存在并且必须编译。要将数据导入到此类中,请执行以下操作:
1. 从管理门户中选择系统资源管理器,然后选择SQL。使用页面顶部的切换选项选择一个命名空间;这将显示可用命名空间的列表。
2. 在页面顶部,单击向导下拉列表,然后选择数据导入。
3. 在向导的第一页上,从指定外部文件的位置开始。对于导入文件所在的位置,请单击要使用的服务器的名称。
4. 然后输入文件的完整路径和文件名。
5. 对于选择架构名称,单击要向其中导入数据的InterSystems IRIS包。
6. 对于选择表名,单击将包含新创建的对象的类。
7. 然后单击下一步。
8. 在向导的第二页上,单击将包含导入数据的列。
9. 然后单击下一步。
10. 在向导的第三页上,描述外部文件的格式。
- 有关用什么分隔符分隔您的列?,请单击与此文件中的分隔符对应的选项。
- 单击第一行是否包含列标题?如果文件的第一行不包含数据,则选中此复选框。
- 对于字符串引号,单击指示此文件用于开始和结束字符串数据的引号分隔符字符的选项。
- 对于日期格式,请单击指示此文件中日期格式的选项。
- 对于时间格式,请单击指示此文件中的时间格式的选项。
- 对于时间戳格式,请单击指示此文件中的时间戳格式的选项。
- 单击禁用验证?如果不希望向导在导入时验证数据,请选中此复选框。
- 使用%SortBegin/%SortEnd?如果不希望向导在导入期间重新生成索引,请选中此复选框。如果选中延迟索引生成,向导将在将导入的数据插入到表中之前为该类调用%SortBegin方法。导入完成后,向导将调用%SortEnd方法。不执行任何验证(与使用%NOCHECK的INSERT相同)。这是因为当使用%SortBegin/%SortEnd时,在SQL INSERT期间不能检查索引的唯一性。如果选中延迟索引构建,则假定导入的数据有效,不会检查其有效性。
- 或者,单击“预览数据”以查看向导将如何分析此文件中的数据。
11. 单击“下一步”。
12. 检查条目,然后单击Finish。向导将显示“数据导入结果”对话框。
13. 单击关闭。或者单击给定的链接以查看后台任务页面。
在任何一种情况下,向导都会启动一个后台任务来完成工作。
# 将数据导出到文本文件
可以将给定类的数据导出到文本文件。为此:
1. 从管理门户中选择系统资源管理器,然后选择SQL。使用页面顶部的切换选项选择一个命名空间;这将显示可用命名空间的列表。
2. 在页面顶部,单击向导下拉列表,然后选择数据导出。
3. 在向导的第一页上:
- 输入要创建以保存导出数据的文件的完整路径和文件名。
- 从下拉列表中,选择要从中导出数据的命名空间、方案名和表名。
- 或者,从Charset下拉列表中选择一个字符集;默认值为Device Default。
- 然后单击下一步。
4. 在向导的第二页上,选择要导出的列。然后单击下一步。
5. 在向导的第三页上,描述外部文件的格式。
- 有关用什么分隔符分隔的列?,请单击与此文件中的分隔符对应的选项。
- 单击导出列标题?如果要将列标题导出为文件的第一行,请选中此复选框。
- 对于字符串引号,单击一个选项以指示如何开始和结束此文件中的字符串数据。
- 对于日期格式,单击一个选项以指示要在此文件中使用的日期格式。
- (可选)单击“预览数据”以查看结果的外观。然后单击下一步。
6. 检查条目,然后单击Finish。该向导将显示“数据输出结果”对话框。
7. 单击关闭。或单击给定的链接以查看后台任务页面。
在任何一种情况下,向导都启动后台任务来完成工作。
文章
Michael Lei · 七月 4, 2021
大家好, 在本文中,我比较了 Gartner 最新DBMS 魔力象限中的主要领先数据库产品的功能。 请见按现有功能数量排序的列表。 1. InterSystems IRIS 2020.3 - 60 个功能 (https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls) 2. Oracle Database 21c - 54 个功能 (https://docs.oracle.com/en/database/oracle/oracle-database/index.html) 3. Microsoft SQL Server - 45 个功能 (https://docs.microsoft.com/en-us/sql/sql-server/?view=sql-server-ver15) 4. AWS Aurora - PostgreSQL - 34 个功能 (https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/CHAP_AuroraOverview.html) 我只比较了功能,未进行任何性能比较(关于此内容,请参见性能测试:https://cn.community.intersystems.com/post/intersystems-iris%E6%95%B0%E6%8D%AE%E5%B9%B3%E5%8F%B0%EF%BC%9A%E6%95%B0%E6%8D%AE%E6%8E%A5%E6%94%B6%E9%80%9F%E5%BA%A6%E6%B5%8B%E8%AF%95)。 我使用了上面的产品官方文档链接。 请见比较表格: <colgroup><col style="width:245pt" width="327"><col style="width:88pt" width="118"><col style="width:122pt" width="162"><col style="width:150pt" width="200"><col style="width:146pt" width="195"></colgroup>
功能
InterSystemsIRIS 2020.3
OracleDatabase 21c
MicrosoftSQL Server 2020
AWS Aurora -PostgreSQL
故障转移集群
有
有
有
有
镜像/数据复制
有
有
有
有
分布式缓存/内存中支持
有
有
有
有
备份/恢复 - 增量和完整
有
有
有
有
纵向缩放
有
有
有
有
针对 Insert、Update 和 Delete 进行横向缩放
有
有
无
无
针对 Select 进行横向缩放
有
有
有
有
分片集群
有
有
无
有
云支持和云管理器
有
有
有
有
Kubernetes 支持和 Kubernetes 管理器
有
有
有
有
Docker 支持
有
有
有
无
AWS 托管
有
有
有
有
Azure 托管
有
有
有
无
Google Cloud 托管
有
有
有
无
托管云
有
有
有
有
内部部署支持
有
有
有
无
多模型 - OO
有
无
无
无
多模型 - 文档 - JSON
有
有
有
有
多模型 - XML
有
有
有
有
多模型 - 键/值
有
无
无
无
多模型 - SQL
有
有
有
有
多模型 - 空间
无
有
有
有
多模型 - 图表
无
有
有
无
多模型 - OLAP 多维数据集
有
有
有
无
GIS 平台
无
有
无
无
本机 OO 编程语言
有
有
无
无
Java、.Net、Python、C/C++ 和 PHP 支持
有
有
有
有
Node.js 支持
有
有
有
有
ODBC/JDBC 支持
有
有
有
有
后端应用程序开发
有
有
无
无
前端应用程序开发
有
有
无
无
低代码 Web 应用程序开发
无
有
有
无
数据库应用程序开发
有
有
有
有
OData 支持
无
有
有
无
REST 服务
有
有
有
有
SOAP 服务
有
无
无
无
终端工具
有
有
有
有
IDE 支持
有
有
有
有
Web 管理/IDE 支持
有
有
有
有
嵌入 NLP
有
无
无
无
嵌入 AutoML
有
无
无
无
R/机器学习支持
有
有
有
有
PMML
有
无
无
无
业务报表服务器/开发
有
有
有
无
自主 AI 操作
无
有
无
无
非结构化文本注释/类似 Apache UIMA
有
有
无
无
Spark 支持
有
有
有
有
BI 工具
有
无
有
无
MDX 支持
有
有
有
无
互操作性连接器
有
无
无
无
BPEL/集成编排/工作流
有
无
无
无
ETL - 提取、转换和加载数据
有
无
无
无
IoT/MQTT 支持
有
无
无
无
EDI 支持
有
无
无
无
ESB
有
无
无
无
CDC - 变更数据捕获
有
有
有
有
RBAC 模型
有
有
有
有
LDAP 支持
有
有
有
有
双因素授权/身份验证支持
有
有
有
有
加密
有
有
有
有
标记
有
有
有
无
审计和跟踪
有
有
有
有
SAM
有
有
有
有
多操作系统支持
有
有
有
有
SAML/Oauth/OpenID 支持
有
有
有
有
性能调整 IDE/包
无
有
无
无
特权用户访问管理
无
有
无
无
API 管理
有
无
无
无
功能总数
61
54
45
34
文章
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,并使用向导配置上述将在应用程序中使用的技术,请参见:
.png)
您可以选择技术并创建项目。 所有技术都将通过 maven 导入。 它就像一个可视化的 zpm。
所创建的项目有一个类用于为应用程序提供支持,其中包含所有所需内容(Web 和应用程序服务器,以及所有依赖项、微服务概念)。
此项目的完整源代码在以下 open exchange 项目中: https://openexchange.intersystems.com/package/springboot-iris-crud。
首先要配置 IRIS JDBC 驱动程序和 IRIS Hibernate 支持,为此,请将 jar 文件复制到 resources 文件夹,请参见:
.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 应用程序运行:
.png)
等待内部服务器启动,然后打开 localhost:8080。 Spring boot 将打开一个 API REST HAL 浏览器。 请参见以下图像记录:

更多详细信息,请参见我的应用程序示例。 我将所有内容一起打包成一个 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的命名规范吗。。。
文章
姚 鑫 · 三月 7, 2022
# 第七十四章 SQL函数 LEAST
从一系列表达式中返回最小值的函数。
# 大纲
```
LEAST(expression,expression[,...])
```
# 参数
- `expression` - 解析为数字或字符串的表达式。
将这些表达式的值相互比较,并返回最小值。
表达式可以是字段名、文字、算术表达式、主机变量或对象引用。
最多可以列出`140`个逗号分隔的表达式。
# 描述
`LEAST`从逗号分隔的表达式序列中返回最小值。
表达式按从左到右的顺序求值。
如果只提供一个表达式,则`LEAST`返回该值。
如果任何表达式为`NULL`, `LEAST`返回`NULL`。
如果所有表达式值都解析为规范数,则按数值顺序对它们进行比较。
如果引用的字符串包含规范格式的数字,则按数字顺序对其进行比较。
但是,如果引用的字符串包含非规范格式的数字(例如,`'00'`、`'0.4'`或`'+4'`),则将其作为字符串进行比较。
字符串比较按排序顺序逐字符执行。
任何字符串值都大于任何数字值。
空字符串大于任何数字值,但小于任何其他字符串值。
如果返回值是一个数字,`LEAST`将以规范格式返回它(删除前导和末尾的零,等等)。
如果返回值是一个字符串,`LEAST`将不改变返回值,包括任何开头或结尾的空格。
`LEAST`返回逗号分隔的一系列表达式中的最小值。
`GREATEST`返回逗号分隔的一系列表达式中的最大值。
`COALESCE`返回逗号分隔的一系列表达式中的第一个非`null`值。
# 返回值数据类型
如果表达式值的数据类型不同,则返回的数据类型是与所有可能的返回值最兼容的类型,具有最高数据类型优先级的数据类型。
例如,如果一个表达式是整数,而另一个表达式是小数,则`LEAST`返回数据类型`NUMERIC`的值。
这是因为`NUMERIC`是具有最高优先级的数据类型,并且与两者兼容。
但是,如果表达式是文字数字或字符串,则`LEAST`返回数据类型`VARCHAR`。
# 示例
在下面的例子中,每个`LEAST`比较三个正则数:
```sql
SELECT LEAST(22,2.2,-21) AS HighNum,
LEAST('2.2','22','-21') AS HighNumStr
-21 -21
```
在下面的例子中,每个`LEAST`比较三个数字字符串。
然而,每个`LEAST`包含一个非规范字符串;
这些非规范值将作为字符串进行比较。
字符串总是大于数字:
```sql
SELECT LEAST('22','+2.2','21'),
LEAST('0.2','22','21')
21 21
```
在下面的例子中,每个`LEAST`都会比较三个字符串,并返回排序序列最低的值:
```sql
SELECT LEAST('A','a',''),
LEAST('a','aa','abc'),
LEAST('#','0','7'),
LEAST('##','00','77')
a 0 77
```
下面的例子比较了两个被视为标准数字的日期:作为`$HOROLOG`整数的出生日期和转换为日期的`58074`整数。
它返回每个在`20`世纪出生的人的出生日期。
任何在`1999年12月31日`之后出生的人都会显示默认的出生日期为`2000年1月1日`:
```sql
SELECT Name,LEAST(DOB,TO_DATE(58074)) AS NewMillenium
FROM Sample.Person
```

文章
Frank Ma · 三月 2, 2022
如何检查密码是否足够强大,使其不会很快被破解? 又如何制作一个强大的密码?
我开发了一个工具,可能对这个问题有帮助。你可以在OpenExchange上找到它。用zpm安装。
zpm "install passwords-tool"
这个模块将只安装一个类 caretdev.Passwords中,其中包含一些有用的方法。
安全密码
要获得一个安全的密码,通常只需使用大写和小写的字母、数字和特殊符号,而且至少要有8个符号的长度。
Generate方法使用的参数:
Length - 只是一个生成密码的长度,默认值为12。
IncludeUpperLetter - 包括大写的ASCII字母,如果需要的话是2,默认是1。
IncludeLowerLetter - 包括小写ASCII字母,如果需要的话,默认为2。
IncludeNumber - 包括数字,如果需要的话,2个,默认为1个。
IncludeSymbol - 包括特殊符号,如果需要的话,2个,默认为1个。
USER>w ##class(caretdev.Passwords).Generate(12,1,0,0,0)
FMXRQEQPOVBC
USER>w ##class(caretdev.Passwords).Generate(12,1,1,0,0)
rgbPyWApcUjp
USER>w ##class(caretdev.Passwords).Generate(12,1,1,1,0)
cDuLf8FqEDx7
USER>w ##class(caretdev.Passwords).Generate(12,1,1,1,1)
0J/ lLbW|T$
USER>w ##class(caretdev.Passwords).Generate()
w3}{OQA|T{h^
这个方法使用$System.Encryption.GenCryptRand(),而不是普通的$random,后者对于密码来说可能不是那么安全。除了获得最佳密码外,它还在一个循环中生成一些密码,检查密码熵的值,并返回一个最高分。
密码熵 Entropy
密码熵预测了一个给定的密码通过猜测、暴力破解、字典攻击或其他常见方法破解的难度。熵本质上是衡量攻击者需要进行多少次猜测才能猜出你的密码。有几种方法来计算它。
USER>write ##class(caretdev.Passwords).Entropy("Pas$W0rD")
52.56
熵值公式L = 密码长度;密码中的符号数S = 独特的可能符号库的大小(字符集)。
比如:
数字(0-9): 10小写拉丁字母(a-z): 26小写和大写拉丁字母(a-z,A-Z):52ASCII可打印字符集(a-z、A-Z、符号、空格):95
可能的组合数=S**L密码熵值 = log2(可能的组合数)
香农熵 Shannon Entropy
USER>write ##class(caretdev.Passwords).ShannonScore("Pas$W0rD")
24
这种方式是基于使用字符的频率,以及密码的整个长度。详情见 Wiki.
NIST得分
USER>write ##class(caretdev.Passwords).NISTScore("Pas$W0rD")
24
计算
第一个字符的熵是4比特;
接下来的七个字符的熵是每个字符2比特;
第九个到第二十个字符的熵为每字符1.5比特;
第21个及以上的字符,每个字符有1比特的熵;
如果同时使用大写字母和非字母字符,将增加6位的 "奖励";
对于长度为1到19个字符的密码,在进行广泛的字典检查后,会增加6位的 "奖励",以确保密码不包含在一个大的字典中。20个字符以上的密码不会得到这个奖励,因为它被认为是由多个字典词组成的密码。
强度 Strength
write ##class(caretdev.Passwords).DetermineStrength("Pas$W0rD")
REASONABLE
生成的密码
USER>write ##class(caretdev.Passwords).DetermineStrength(##class(caretdev.Passwords).Generate())
STRONG
非常弱 VERY_WEAK - 熵值Entropy <= 32
弱WEAK - 熵值Entropy <= 48
正常 REASONABLE - 熵值Entropy <= 64
强 STRONG - 熵值Entropy <= 80
非常强 VERY_STRONG - 熵值Entropy > 80
如果你喜欢这篇文章,请投票 。
文章
姚 鑫 · 七月 28, 2021
# 第三十三章 类关键字 - SoapBodyUse
指定此类中定义的任何`web method`的编码。此关键字仅适用于`web服务`和`web客户端`类。
# 用法
要指定此类的`web method`的输入和输出所使用的编码,请使用以下语法:
```java
Class MyApp.MyClass [ SoapBodyUse = soapbodyuse ] { //class members }
```
其中`soapbodyuse`是下列之一:
- `literal` 文字(默认)—默认情况下,此类中的`web method`使用文字数据。也就是说,`SOAP`消息的``中的`XML`与`WSDL`中给出的模式完全匹配。
- `encoded` 编码—默认情况下,此类中的`web method`使用`SOAP`编码的数据。也就是说,`SOAP`消息的``中的`XML`使用了适合所使用的`SOAP`版本的`SOAP`编码,如以下规范所要求的:
- `SOAP 1.1` (https://www.w3.org/TR/2000/NOTE-SOAP-20000508/Opens in a new window)
- `SOAP 1.2` (https://www.w3.org/TR/soap12-part2/Opens in a new window)
重要提示:对于手动创建的`web服务`,该关键字的默认值通常是合适的。当使用`SOAP`向导从WSDL生成`web`客户端或服务时,InterSystems IRIS会将此关键字设置为适合该`WSDL`;如果修改该值,web客户端或服务可能不再工作。
# 详解
此关键字指定此类中定义的任何`web method`使用的默认编码。它还控制这个类的`ELEMENTQUALIFIED`和`XMLELEMENT`参数的默认值,这将在本主题的一个小节中讨论。
可以通过使用`SoapBodyUse`方法关键字或`SoapBodyUse`查询关键字,为单个方法重写此关键字。
# 对子类的影响
此关键字不是继承的。
# 默认
默认值为文字。(`SOAP`标准V1.1指定`web method`应该使用`SOAP`编码。但是,大多数`SOAP`客户端(包括`.NET`)都使用文字样式。)
# WSDL的关系
`SoapBodyUse`关键字指定了`WSDL`的``部分中``元素的`Use`属性的值。例如,如果`SoapBodyUse`是字面意思,则`WSDL`可能如下所示:
```xml
...