清除过滤器
公告
Claire Zheng · 五月 8, 2021
InterSystems中国正在招聘SE,具体职位需求以英文发布,详情如下,欢迎将简历砸过来 (claire.zheng@intersystems.com)or 私信联系 :)
Intersystems China 系联软件(北京)有限公司, established in 1978 is the trusted Healthcare IT solution provider for many World-Class hospitals and clinics in China, such as China’s largest foreign-invested hospital, United Family Healthcare 和睦家医疗, and one of China’s most prestige medical institution, Peking Union Medical College Hospital 北京协和医院。
The company has a small but collaborative team of talented and passionate individuals working the Greater China Region.
Due to China’s economic growth, aging population and the government’s determination in the Healthcare reform, China has become one of InterSystems’s most important strategic regions with unparalleled growth potentials in the years to come.
Overview
This Channel Sales Manager role will require someone who is passionate about technology within the Greater China Regions.
The role will focus on selling our core product portfolio and HealthShare into the Greater China Region IT channel.
The successful applicant will develop new relationships with Application Partners and System Integrators, whilst maintaining and enhancing relationships with current partners to ensure that Intersystems is there vendor of choice.
This role will suit someone who would like to work for a stable international company, have exposure to working with colleagues from other countries and who wants to be associated with leading edge technology.
Responsibilities
Develop relationships with new application partners and systems integrators.
Manage and motivate current application partners and systems integrators to ensure that Intersystems is their vendor of choice by showing value, enhancing customer experience and being the trusted advisor for them
Develop and execute against sales plan to meet revenue targets.
Work with Marketing to develop market awareness of the potential of InterSystems products, organise industry events and initiatives.
Create and maintain a healthy pipeline
Provide accurate forecasting to the management team.
Maintain awareness of industry sector and technological advances
Qualifications
Strong knowledge and experience in building and expanding solid partner ecosystem;
Capability and Experience of closing deals and transaction execution within limited time, driven by success and results.
In depth experience in and understanding of the IT sales channel within The Greater China Region.
Demonstrable experience developing Application Partner and System Integrators
Proven track record in exceeding quotas
Previous experience in developing and successfully executing against a sales plan
Ability to develop strong relationships with key decision makers and influencers with win-win strategy and be the trusted advisor to customers.
Ability to think and work creatively to develop unique value propositions for specific partners or customers
Experience negotiating and motivating a mutually agreeable and positive contracts
Fluent written and communication skills both in Mandarin and English.
Experience in Healthcare is not mandatory but a plus.
公告
Claire Zheng · 七月 7
InterSystems 发布了新的点式更新,该更新解决的缺陷问题影响以下受支持的产品线的最新先前版本 2025.1.0、2024.1.4、2023.1.6 和 2022.1.7:
InterSystems IRIS
InterSystems IRIS for Health
HealthShare Health Connect
此问题可能导致在使用以下功能时出现意外的 <PROTECT> 错误或访问异常:
隐式命名空间
对数据库的混合只读/读写访问
用于列出例程和全局变量的管理门户页面
症状包括:
命名空间创建故障
在列出例程时,间歇性出现“访问被拒”错误
对于具有只读权限的用户,全局显示页面不返回数据
虽然这些问题并不影响访问控制或用户权限,但它们会在多种场景下影响预期的系统行为。
问题得到解决的版本
以下点式版本中修复了该问题:
2025.1.0.230.2
2024.1.4.516.1
2023.1.6.810.1
2022.1.7.116.1
建议使用受影响版本的客户应用相关更新,以确保系统正常运行。
如果您有任何问题或需要支持,请联系 InterSystems 全球响应中心 (WRC)。
文章
Qiao Peng · 三月 29, 2021
一些熟悉SQL的用户希望用SQL表的方式获取InterSystems IRIS/Caché的变更数据。知道了Global和SQL表的对应关系,就可以知道是哪一张SQL表数据变化了,甚至通过SQL查询获取变更的数据。下面介绍如何实现这种方式,和注意事项。
获取Global和SQL表的对应关系
通常InterSystems IRIS/Caché的持久化的对象模型(类)和SQL表之间有一一对应的关系;而持久化的对象模型和Global之间也有一一对应关系。建立Global和SQL表的对应关系,通常可以使用以下的SQL查询特定SQL schema下所有表对应的Global:
SELECT CC.SqlQualifiedNameQ SQLTable, CS.parent Class, CS.DataLocation
FROM %Dictionary.CompiledStorage CS, %Dictionary.CompiledClass CC
WHERE CS.parent = CC.ID
AND CC.SqlSchemaName= <schemaname>
其中<schemaname>是SQL的Schema名称; 返回字段SQLTable是SQL表名、Class是对象类名、DataLocation是保存数据的Global名称。
多种建模方式Global和SQL表的对应关系的影响
InterSystems IRIS/Caché都是支持多种建模方式的数据平台,常见的建模方式有SQL、面向对象、多维数组。如果之前不了解InterSystems IRIS/Caché的多维数组,可以先简单理解为键值对。无论使用何种建模方式,都可以得到3套模型:SQL模型、对象模型和多维数组存储模型(Global模型)。上面提到通常InterSystems IRIS/Caché的持久化的对象模型(类)和SQL表之间有一一对应的关系。但由于SQL表达模型的局限性, InterSystems IRIS/Caché的对象模型和SQL表之间并不总是一一对应的关系。
下面就逐一分析各种建模方式下,如何分析和获取Global和SQL表的对应关系。
1. 基于SQL建模
如果InterSystems IRIS/Caché模型就是用SQL建模的,查找Global和SQL表的对应关系很简单:对象模型是基于SQL模型自动创建的,因此它们之间是一对一的关系。这是,在Caché里,编译出的Storage 类型为%Library.CacheStorage;在InterSystems IRIS里,编译出的Storage 类型为%Storage.Persistent。
可以执行SQL查询:
SELECT CC.SqlQualifiedNameQ as SQLTable, CS.parent as Class, CS.DataLocation
FROM %Dictionary.CompiledStorage CS, %Dictionary.CompiledClass CC
WHERE CS.parent = CC.ID
AND CC.SqlSchemaName= <schemaname> AND type='%Library.CacheStorage'
其中<schemaname>是SQL的Schema名称,如果Schema里有“_”,应将其去掉。Parent字段是SQL表对应的类名,DataLocation是保存数据的Global名称。而Global的第一个下标就是行号/Id字段。
例如使用DDL创建一个table:
Create table Demo.Mytable(name varchar(20), notes varchar(100))
通过上面的SQL查询,DataLocation为Demo.MytableD。那么Journal中所有对于Global为Demo.MytableD的操作就是对表Demo.Mytable的记录操作。例如^Demo.MytableD(123), 就是对行号/Id字段为123的Demo.Mytable记录到操作,从而可以通过SQL: SELECT name, notes from Demo.Mytable WHERE id = 123 获取这条变更的记录。
2. 基于对象建模
如果InterSystems IRIS/Caché模型是使用对象建模的,查找Global和SQL表的对应关系有时并不那么简单。例如以下描述患者及地址的简单对象模型:
Class Demo.Address Extends %SerialObject
{
Property Type As %String;
Property City As %String;
Property Street As %String;
Property RoomNo As %String;
}
Class Demo.Patient Extends %Persistent
{
Property Name As %String;
Property Gender As %String;
Property DOB As %Date;
Property Addresses As list Of Demo.Address(SQLPROJECTION = "table", STORAGEDEFAULT = "array");
}
因为患者可能有多个地址,因此Demo.Patient类用以列表类型(list)描述地址属性。其中地址Demo.Address对象模型是通过被引用的持久化对象来序列化的,此处引用它的持久化对象类就是Demo.Patient。Demo.Address类并没有独立的Global保存其数据,它的数据是保存在Demo.Patient的Global中的。
这个对象模型很容易理解,以对象方式在InterSystems IRIS/Caché里也很容易操作数据。但SQL的二维表无法表达这样稍微复杂一点的模型,因此需要将患者的地址投射为一张地址表,并用主外键将地址表和患者表的记录关联起来。
上面的患者对象模型中Addresses属性的SQLPROJECTION和STORAGEDEFAULT参数就是将属性Addresses投射为一张SQL表。
编译后,这个患者对象模型,在SQL上会投射出两张表:患者表:Demo.Patient地址表:Demo.Patient_Addresses注意:SQL表Demo.Patient_Addresses并不是由对象类Demo.Address投射而来,它是由对象类Patient的列表类型的属性Addresses投射而来。对象类Demo.Address是序列化类,它并不会投射SQL表。
执行SQL查询
SELECT CC.SqlQualifiedNameQ as SQLTable, CS.parent as Class, CS.DataLocation
FROM %Dictionary.CompiledStorage CS, %Dictionary.CompiledClass CC
WHERE CS.parent = CC.ID
AND CC.SqlSchemaName= 'Demo'
将返回类似如下结果:
SQLTable
Class
DataLocation
Demo.Patient
Demo.Patient
^Demo.PatientD
Demo.Patient_Addresses
Demo.Patient
注意:SQL表Demo.Patient_Addresses并没有对应的Global,因为它的数据是保存在Patient的Global里的。
这时可以使用以下SQL查询获取SQL表Demo.Patient_Addresses对应的Global和下标:
SELECT CC.ID||'_'||CSD.Attribute as SQLTable, CS.parent as Class, CS.DataLocation, CSD.Structure, CSD.Subscript
FROM %Dictionary.CompiledStorage CS, %Dictionary.CompiledClass CC, %Dictionary.CompiledStorageData CSD
WHERE CS.parent = CC.Name
AND CS.ID1 = CSD.parent
AND CC.SqlSchemaName= 'Demo'
AND CC.ID||CSD.Attribute in (select parent from %Dictionary.CompiledStorage where DataLocation is null)
它返回类似如下结果:
SQLTable
Class
DataLocation
Structure
Subscript
Demo.Patient_Addresses
Demo.Patient
^Demo.PatientD
subnode
“Addresses”
这说明SQL表Demo.Patient_Addresses的数据放在Global ^Demo.PatientD的下标为"Addresses"的子节点下。所以对Global节点 ^Demo.PatientD(“Addresses”)的数据变更就是对SQL表Demo.Patient_Addresses的数据变更。
类似的,当创建对象模型的父子关系时,父子关系子方的数据可以保存在父方的Global中。如以下模型:患者模型
Class Demo.Patient Extends %Persistent
{
Property Name As %String;
Property Gender As %String;
Property DOB As %Date;
Property Addresses As list Of Demo.Address(SQLPROJECTION = "table", STORAGEDEFAULT = "array");
Relationship Encounters As Demo.Encounter [ Cardinality = children, Inverse = Patient ];
}
就诊模型,它和患者模型是父子关系
Class Demo.Encounter Extends %Persistent
{
Property EncounterNo As %String;
Property VisitDate As %Date;
Relationship Patient As Demo.Patient [ Cardinality = parent, Inverse = Encounters ];
}
执行SQL查询
SELECT CC.SqlQualifiedNameQ as SQLTable, CS.parent as Class, CS.DataLocation
FROM %Dictionary.CompiledStorage CS, %Dictionary.CompiledClass CC
WHERE CS.parent = CC.ID
AND CC.SqlSchemaName= 'Demo'
将返回类似如下结果:
SQLTable
Class
DataLocation
Demo.Encounter
Demo.Encounter
{%%PARENT}(“Encounters”)
Demo.Patient
Demo.Patient
^Demo.PatientD
Demo.Patient_Addresses
Demo.PatientAddresses
这说明SQL表Demo.Encounter的数据放在Global ^Demo.PatientD的下标为" Encounters"的子节点下。所以对Global ^Demo.PatientD(“Encounters”)的数据变更就是对SQL表Demo.Encounter的数据变更。
3. 基于Global建模
直接基于Global建模并不常见。如果是直接基于Global建模的,可以在Global模型的基础上再建立对象模型,这样数据不仅可以使用多维数组方式操作,也可以通过对象和SQL方式操作。
这种情况下的对象模型,使用的Storage 类型在Caché里为%CacheSQLStorage,在InterSystems IRIS里为%Storage.SQL。
例如如下使用%CacheSQLStorage的Caché对象类Demo.Department:
Class Demo.Department Extends %Persistent [ StorageStrategy = SQLStorage ]
{
Property Id As %Integer;
Property Name As %String;
Property Parent As Demo.Department;
Index MyId On Id [ IdKey ];
Storage SQLStorage
{
<SQLMap name="DataMap">
<Data name="Id">
<Delimiter>"^"</Delimiter>
<Node>"id"</Node>
<Piece>1</Piece>
</Data>
<Data name="Name">
<Delimiter>"^"</Delimiter>
<Node>"Name"</Node>
<Piece>1</Piece>
</Data>
<Data name="Parent">
<Delimiter>"^"</Delimiter>
<Node>"Parent"</Node>
<Piece>1</Piece>
</Data>
<Global>^MyDepartment</Global>
<RowIdSpec name="1">
<Field>Id</Field>
</RowIdSpec>
<Subscript name="1">
<Expression>{Id}</Expression>
</Subscript>
<Subscript name="2">
<Expression>"Dep"</Expression>
</Subscript>
<Type>data</Type>
</SQLMap>
<StreamLocation>^Demo.DepartmentS</StreamLocation>
<Type>%CacheSQLStorage</Type>
}
}
对于这种使用%CacheSQLStorage或%Storage.SQL的对象类所投射出的SQL表,可以使用以下SQL查询获取SQL表对应的Global和下标:
SELECT CC.SqlQualifiedNameQ as sqltable,
CC.id as class, CSM._Global as DataLocation, CSM.Structure, CSMS.Name as subscript,CSMS.Expression
FROM %Dictionary.CompiledStorage CS,
%Dictionary.CompiledClass CC,
%Dictionary.CompiledStorageSQLMap CSM,
%Dictionary.CompiledStorageSQLMapSub CSMS
WHERE CS.parent = CC.ID
AND CS.ID1 = CSM.parent
AND CSM.ID = CSMS.parent
AND CSM.Type='data'
AND CC.SqlSchemaName= <schemaname>
其中<schemaname>是SQL的Schema名称。它返回类似如下结果:
SQLTable
Class
DataLocation
Structure
Subscript
Expression
Demo.Department
Demo.Department
^MyDepartment
1
{Id}
Demo.Department
Demo.Department
^MyDepartment
2
“Dep”
说明SQL表Demo.Department的数据保存在^MyDepartment 中,并且放在2个下标下,第一维下标为Id字段,第二维下标为字符串常量"Dep"。
这时,可以通过^MyDepartment的第一维下标(字段Id)值,执行SQL语句获取变更的整条记录:
SELECT * FROM Demo.Department WHERE id=?
使用%CacheSQLStorage/%Storage.SQL为Storage类型的InterSystems IRIS/Caché对象类,其Global模型可以任意灵活,而且不影响对象操作和SQL操作。但这也提高了将Global变更对应到SQL表的难度。
总结
通过上面的分析,如果要从InterSystems IRIS/Caché中通过SQL方式分析数据变更,需要先了解其建模方式,分析Global对应SQL表的关系。可以建立一张SQL表,存储分析得到的Global及下标和SQL表对应关系。当通过Dejournal filter发现global数据变更时,查询该SQL表,将数据变更表达为对应SQL表和对应记录(RowID),从而使用SQL获取完整的变化记录。
其它注意事项:流类型的属性/字段,通常保存在名为S的Global内,因此这些Global的数据更新也应该捕获并转换为对应SQL表的数据变更记录。
CDC系列
更多的CDC选项实现,请参考:
1. CDC系列之一 :使用Dejournal Filter在InterSystems IRIS/Caché上通过Mirroring实现CDC功能
2. CDC系列之二 :使用Dejournaling filter routine在Caché上通过Shadow实现CDC
3. CDC系列之三 :建立InterSystems IRIS/Caché的Global数据变更与SQL表记录的对应关系
4. CDC系列之四:使用DSTIME特性在InterSystems IRIS/Caché上实现CDC功能
文章
jieliang liu · 九月 22, 2021
技术概要:ObjectScript
技术概要:ObjectScript
本文档将向您介绍 ObjectScript 编程语言,并提供了几个示例,说明如何使用它来存储和检索来自 InterSystems IRIS®数据平台的数据。本技术概要(First Look)并不试图提供对该语言或其功能的全面概述。您可以使用本文件末尾列出的参考资料,继续您的探索。
要浏览所有的技术概要(First Look),包括可以在 InterSystems IRIS 免费的评估实例上执行的那些,请参见 InterSystems First Looks(《InterSystems 技术概要》)。
什么是 ObjectScript?
ObjectScript 是一种编程语言,用于在 InterSystems IRIS 数据平台上快速开发复杂的业务应用。ObjectScript 源代码被编译成 object 代码,该代码可针对业务应用程序中的典型操作(包括字符串操作和数据库访问)进行高度优化。
ObjectScript 的独特之处之一是它的底层存储结构,即所谓的 globals。Globals 可以被认为是持久的多维稀疏数组。ObjectScript 允许您直接从 globals 访问数据,但也允许您通过其本机 object 和 SQL 支持来访问这些数据。
<span id="2_Try_It:_Storing_and_Retrieving_Data_Us" class="anchor"></span>虽然您可以在 InterSystems IRIS 平台上使用 Java、.NET、node.js 或其他语言编写应用程序,但通过使用该平台的许多 API,您可以使用 ObjectScript 编写高效的、基于服务器的代码,让您对数据有更精细的控制。
试一试:使用 ObjectScript 存储和检索数据
在这篇技术概要(First Look)中,您将学习如何使用 ObjectScript 来:
在 globals 中存储和检索数据。
定义一个类,并实例化、使用和存储该类的 objects。
使用 SQL 查询访问为该类存储的数据,并对结果集进行处理。
正如您将看到的,ObjectScript 使您能够以多种方式存储和访问数据,既强大又灵活。
用前须知
要使用本技术概要(First Look),您需要一个正在运行的 InterSystems IRIS 实例。您的选择包括几种类型的已授权的和免费的评估实例;该实例不需要由您正在工作的系统托管(尽管您的系统必须能够通过网络访问该实例)。关于如何部署每种类型的实例的信息,如果您还没有一个实例可以使用,请参见(InterSystems IRIS Basics:Connecting an IDE《InterSystems IRIS 基础:连接一个 IDE》)中的Deploying InterSystems IRIS(部署 InterSystems IRIS)。
您也需要知道:
实例的基于 web 的管理门户(Management Portal)的 URL,这是 InterSystems IRIS 的系统管理用户界面。
试一试:使用 ObjectScript 存储和检索数据
如何访问终端(Terminal),InterSystems IRIS 命令行工具。
您的实例的用户名和密码(InterSystems Learning Labs 上的 web 实例不需要)。
您还需要从 InterSystems GitHub repo 下载 ObjectScript 示例代码:https://github.com/intersystems/FirstLook-ObjectScript。
关于如何访问管理门户(Management Portal )或终端(Terminal)的更多信息,请参见InterSystems IRIS Basics:Connecting an IDE(《InterSystems IRIS 基础:连接一个 IDE》) 中的 " InterSystems IRIS Connection Information《InterSystems IRIS 连接信息》)"。尽管您实际上不需要 IDE 来做这些练习,但您可以使用安装了 ObjectScript 扩展的 Studio 或 Visual Studio Code 查看和编辑示例代码 。
导入 ObjectScript 代码示例
首先,将 ObjectScript 代码示例导入 InterSystems IRIS:
从管理门户(Management Portal)的主页,选择 System Explorer(系统资源管理器) > Classes(类)。
在 Classes 页面上,查看左栏,确保您在 USER 命名空间。您可以把命名空间看作是工作空间或目录。
点击 Import(导入)。
在 Import Classes 的对话框中: a. 如果您的 InterSystems IRIS 实例在远程服务器上运行,请指定是将示例文件下载到远程服务器还是下载到您的本地计算机。 b. 在"File" 或 "Directory"的 Import(导入)区域,点击 File(文件)。 c. 浏览您从 GitHub 下载的 FirstLookObjectScript.xml 文件。 d. 选择 Compile Imported Items(编译导入项)。 e. 对于 Compile Flags(编译标志),指定 cuk。 f. 点击 Next(下一步)。 g. 点击 Import(导入)。 h. 当出现加载成功的消息时,点击 Done(完成)。
现在,在 Classes 页面上,您应该看到 FirstLook.ObjectScript.cls 和 FirstLook.Person.cls 在类的列表中。在 InterSystems IRIS 中,包含类的包名称(FirstLook)附加有类的名称(ObjectScript 或 Person)。扩展名 .cls 用来表示类文件。
注意: 如果您的命名空间包含大量的类,可以在页面左栏的 Class Name(类名) 框中输入 F*.cls 来过滤列表。
ObjectScript 和 Globals
如果您想使用一些 ObjectScript 命令,一个很好的方法是使用 InterSystems 终端(InterSystems Terminal)。(如果您以前没有使用过终端(Terminal),请参见InterSystems IRIS Basics:Connecting an IDE(《InterSystems IRIS 基础:连接一个 IDE》) 中的 "InterSystems IRIS Connection Information(《InterSystems IRIS 连接信息》)"。)
在您启动终端会话(Terminal session)后,提示会指示您处于哪个命名空间。如果您不在 USER 命名空间,执行以下命令:
set $namespace = "USER"
试一试:使用 ObjectScript 存储和检索数据
在 ObjectScript 中, 您可以使用 set 命令给变量赋值:
USER>set x = "Welcome to ObjectScript!"
要显示一个变量的内容,请使用 write 命令:
USER>write x
Welcome to ObjectScript!
您刚刚创建的变量只存在于这个终端会话(Terminal session)的工作内存中。如果您想在数据库中存储一个值,您可以使用 global,它看起来像一个带插入符号(^)的变量:
USER>set ^Settings("Color") = "Red"
Globals 提供持久性存储,这意味着在您关闭终端会话后,^Settings 将继续存在。
这个特殊的 global 也是一个数组,有一个下标。与许多其他语言中的数组不同,globals 可以有整数、小数或字符串等下标。Globals 也是稀疏的,这意味着下标可能是连续的,也可能不是连续的。
您可以利用 globals 的多维特性来定义一个更复杂的结构:
USER>set ^Settings("Auto1", "Properties", "Color") = "Red"
USER>set ^Settings("Auto1", "Properties", "Model") = "SUV" USER>set ^Settings("Auto2", "Owner") = "Mo"
USER>set ^Settings("Auto2", "Properties", "Color") = "Green"
要显示 global 中的所有节点,您可以使用 zwrite 命令:
USER>zwrite ^Settings
^Settings("Auto1","Properties","Color")="Red"
^Settings("Auto1","Properties","Model")="SUV"
^Settings("Auto2","Owner")="Mo"
^Settings("Auto2","Properties","Color")="Green"
^Settings("Color")="Red"
要检索存储在 global 特定节点上的值,您可以使用 $get() 函数。如果您试图从不存在的 global 节点检索值,这个函数将返回空字符串,以避免潜在的未定义错误。
在终端(Terminal)尝试以下操作:
USER>set ^testglobal(1) = 8888 USER>set ^testglobal(2) = 9999
USER>set globalValue = $get(^testglobal(1))
USER>write "The value of ^testglobal(1) is ", globalValue The value of ^testglobal(1) is 8888
要在 global 中迭代节点,您可以使用 $order() 函数,它返回 global 中的下一个下标。传入一个下标等于空字符串的 global 节点会导致 $order() 返回第一个下标。返回值等于空字符串表示 $order() 已经到达最后一个下标。
您可以像编写变量或 global 的值一样编写函数返回的值:
USER>write $order(^testglobal("")) 1
USER>write $order(^testglobal(1)) 2
USER>write $order(^testglobal(2))
USER>
在实践中,您通常会在 ObjectScript 类文件中的类方法中创建一个 $order() 循环。在 FirstLook.ObjectScript.cls 中为您提供了以下方法。
试一试: 使用 ObjectScript 存储和检索数据
/// Iterate over global ^testglobal ClassMethod Iterate() {
// Start by setting subscript to "" set subscript = ""
// "Argumentless" for loop for {
// Get the next subscript
set subscript = $order(^testglobal(subscript))
// When we get to the end, quit the for loop quit:(subscript = "")
// Otherwise, write the subscript and the value
// stored at ^testglobal(subscript)
write !, "subscript=", subscript, ", value=", ^testglobal(subscript)
}
}
请注意,"无参数(argumentless) "的 for 循环没有指定终止条件,如果我们不显式退出该循环,它将永远循环下去。Write 语句中的感叹号告诉 ObjectScript 在编写 global 中每个节点的下标和值之前移动到下一行。
要在终端(Terminal)运行该方法,请输入:
USER>do ##class(FirstLook.ObjectScript).Iterate()
这产生了输出:
subscript=1, value=8888 subscript=2, value=9999
ObjectScript 和 Objects
您可以使用 ObjectScript 来创建具有方法和属性的类。然后您可以将该类的 objects 实例化。示例类 FirstLook.Person.cls 定义了一个类 Person,然后让您创建该类的实例,如 person John Smith 或 person Jane Doe。
基本的类定义如下所示:
Class FirstLook.Person Extends %Persistent
{
Property FirstName As %String [ Required ]; Property LastName As %String [ Required ];
}
Person 类扩展了内置的 InterSystems IRIS 类 %Persistent,它允许您访问父类中一些有用的方法,如 %New() 和 %Save()。 然后列出该类的属性。在这种情况下,您只是了存储一个 person 的名字和姓氏。
继续使用 终端(Terminal)创建一个新 person。如果您不在 USER 命名空间,执行以下命令:
set $namespace = "USER"
要创建一个新的 Person object,请使用 %New() 方法,该方法返回一个新 person 的 "句柄",更正式的说法是一个 object 引用,或 OREF。然后设置新 person 的属性,并调用 %Save() 方法将新 person 存储在数据库中。
USER>set person = ##class(FirstLook.Person).%New() USER>set person.FirstName = "Sarah"
USER>set person.LastName = "Aarons" USER>set status = person.%Save()
USER>write status 1
试一试: 使用 ObjectScript 存储和检索数据
%Save() 方法返回一个状态,如果成功的话,其值为 1。
当您保存一个 object 时,InterSystems IRIS 会自动为您把它储存在一个 global 中。默认的 global 名称是末尾带有 Dappended 的类名,在本例中是 ^FirstLook.PersonD。
如果显示 global 的内容,您可以看到根节点(没有下标的节点)持有一个 ID,这个 ID 对存储的每个新对象来说是递增的。Global 的其余部分由 ID 下标。每个 Person 节点包含一个属性值列表,其中列表用 $lb 表示,用于 "列表构建"。
USER>zwrite ^FirstLook.PersonD
^FirstLook.PersonD=1
^FirstLook.PersonD(1)=$lb("","Sarah","Aarons")
您还可以定义实例方法,它对特定的实例进行操作,而类方法则是类的泛型方法。例如, FirstLook.Person.cls 包含一个 WriteName() 方法, 该方法编写 person 的名字。
/// Given an instance of a person, write person's name Method WriteName() {
write "The name of this person is:" write !, ..FirstName
write !, ..LastName
}
属性或方法名称前面的额外点表示当前对象或类。
由于变量 person 目前指的是 Sarah Aarons,您可以这样写她的名字:
USER>do person.WriteName() The name of this person is:
Sarah Aarons
作为练习,创建、存储和编写 Person 类的一些新对象,例如,Andrew Shaw、Peter Shaw 和 Kate Aarons。
ObjectScript 和 SQL
您刚刚已经看到了如何将创建的每个 person 存储为 global 中的节点。正如您将在本节中所看到的,每个 person 也是表中的一行,可以使用 SQL 进行访问。
InterSystems 提供了几种在 ObjectScript 中使用 SQL 的方法。例如,您可以使用类查询,这基本上是类文件中的 SQL 查询。
在 FirstLook.Person.cls 中,下面的类查询,对类中的所有对象执行 SELECT 命令:
/// Query for all stored names
Query Select() As %SQLQuery [SqlProc]
{
SELECT %ID, FirstName, LastName FROM Person
ORDER By LastName, FirstName
}
要测试该查询,您可以从终端(Terminal)运行它:
USER>do ##class(%ResultSet).RunQuery("FirstLook.Person", "Select")
输出将显示一个列表,其中包含您在前面的练习中创建并存储的每个 person,按姓氏,然后是名字排序:
ID:FirstName:LastName:
4:Kate:Aarons:
1:Sarah:Aarons:
2:Andrew:Shaw:
3:Peter:Shaw:
了解有关 ObjectScript 的更多信息
在实际生活中,您可能会编写一个类方法,比如 FirstLook.Person.cls 中为您提供的方法,将查询的结果放在结果集中,然后遍历这个结果集中的每一行:
/// Run select query and write all names in result set ClassMethod WriteAllNames()
{
// Create a new %SQL.Statement object
set stmt = ##class(%SQL.Statement).%New()
// Prepare the class query to execute by passing in
// the ClassName and QueryName.
set status = stmt.%PrepareClassQuery("FirstLook.Person", "Select")
// Handle any errors if $$$ISERR(status) {
do $system.OBJ.DisplayError(status) quit
}
// Execute the query
set resultSet = stmt.%Execute()
// Iterate over results while (resultSet.%Next()) {
// Write person's first and last name
write !, resultSet.%Get("FirstName"), " ", resultSet.%Get("LastName")
}
}
在调用 %PrepareClassQuery() 后,这个类方法使用 $$$ISERRmacro 来检查错误状态。然后, 在执行查询后,代码使用 resultSet.%Next() 循环遍历结果集,如果存在另一行,则返回 true。
要在终端(Terminal)运行该方法,请输入:
USER>do ##class(FirstLook.Person).WriteAllNames() Kate Aarons
Sarah Aarons Andrew Shaw Peter Shaw
正如您所看到的,ObjectScript 为您提供了几个处理数据的选项。使用 globals 可以最大限度地控制数据的存储方式,使用 objects 可以轻松地处理类的单个实例,而 SQL 可以跨表的行进行操作。如何看待数据完全取决于您自己。
了解有关 ObjectScript 的更多信息
使用下面列出的参考资料,了解更多关于 ObjectScript 编程的知识。
ObjectScript 教程 --- 提供 ObjectScript 语言的交互式介绍。
Using ObjectScript(使用 ObjectScript)--- 提供 ObjectScript 编程语言的概述和详细信息。
ObjectScript Reference(ObjectScript 参考资料) --- 提供 ObjectScript 的参考资料。
Orientation Guide for Server-Side Programming(服务器端编程定向指南) --- 为使用 InterSystems 产品编写服务器端代码的程序员提供基本信息。
InterSystems ObjectScript Basics(InterSystems ObjectScript 基础) --- 涵盖 ObjectScript 基础的交互式课程。
公告
Claire Zheng · 八月 22, 2022
亲爱的开发者们!
到了展示互操作性技术的时候了!来参加我们最新的竞赛吧!
🏆 InterSystems开发者大赛:以互操作性技术为可持续发展构建解决方案 🏆
时间: 8月29日-9月19日(北京时间)
奖金更高: $13,500 – 请留意,奖金分配跟以往有所不同!
主题
💡 基于InterSystems IRIS和InterSystems IRIS医疗版的互操作性解决方案 💡
基于InterSystems IRIS数据平台或InterSystems IRIS医疗版开发互操作性解决方案,或为开发/维护互操作性解决方案提供帮助的解决方案。
此外,我们邀请开发者尝试解决一个全球性问题,这次我们提出的是“可持续发展问题”。
我们鼓励您参与此次竞赛,构建旨在解决可持续发展问题的解决方案:
1) 如果您的应用对解决可持续发展问题、ESC、可替代能源、最佳利用等问题有帮助,您将获得特别奖励。2) 如果您准备并提交了一个与可持续发展、ESG、可替代能源、最佳利用等问题相关的数据集,您将获得更多额外奖励。
基本要求
有效应用程序:100%全新的Open Exchange Apps或已有的应用程序(但有显著提升)。所有参赛者/团队提交的应用程序只有经过我们团队的审核之后才会被批准参赛。
该应用可以在 IRIS Community Edition or IRIS for Health Community Edition or IRIS Advanced Analytics Community Edition上运行。
该应用需开源并在GitHub上发布。
该应用的README文件应为英文,包含安装步骤,并包含视频demo或/和应用程序如何运行的描述。
🆕 奖品:
如您所愿!我们这次提高了奖金,优化了奖金分配机制!
1. 专家提名奖(Experts Nomination)- 获奖者由我们特别挑选的专家团选出:
🥇 第1名 - $5,000
🥈 第2名 - $3,000
🥉 第3名 - $1,500
🏅 第4名 - $750
🏅 第5名 - $500
🌟 第6-10名 - $100
2. 社区提名奖(Community Nomination)- 获得总投票数最多的应用:
🥇 第1名 - $1,000
🥈 第2名 - $750
🥉 第3名 - $500
✨ 所有获奖者都将获得Global Masters徽章!
注意:如果同时多位参赛者获得同样的票数,均被视为优胜者,将平分奖金
关键参赛节
🛠 应用开发、提交阶段
2022年8月29日 (12:00PM 北京时间):竞赛启动。
2022年9月12日 (11:59AM 北京时间):提交截止。
✅ 投票阶段
2022年9月12日 (12:00PM 北京时间): 投票开始。
2022年9月19日 (11:59AM 北京时间): 投票结束。
注意:在整个参赛期间(开发与投票期间),开发者可持续提升其应用
谁可以参加?
任何开发者社区的成员均可参加,InterSystems内部员工除外(InterSystems contractor员工可以参加)。还没有账号?现在来建一个!
👥 开发者可以组团 创建一个协作应用程序,组团限定人数为2-5人。
请注意,要在您的README文件中标注您的团队成员——社区用户profile
资源助力:
✓ 示例应用:
interoperability-embedded-python
IRIS-Interoperability-template
ETL-Interoperability-Adapter
HL7 and SMS Interoperability Demo
UnitTest DTL HL7
Twitter Sentiment Analysis with IRIS
Healthcare HL7 XML
RabbitMQ adapter
PEX demo
✓ 在线课程:
Interoperability for Business
Interoperability QuickStart
Interoperability Resource Guide - 2019
✓ 视频:
Intelligent Interoperability
Interoperability for Health Overview
✓ IRIS初学者:
Build a Server-Side Application with InterSystems IRIS
Learning Path for beginners
✓ ObjectScript Package Manager (ZPM) 初学者:
How to Build, Test and Publish ZPM Package with REST Application for InterSystems IRIS
Package First Development Approach with InterSystems IRIS and ZPM
✓ 如何将您的APP提交给大赛:
如何在InterSystems Open Exchange上发布应用程序
如何把参赛APP提交给大赛
需要帮助?
加入InterSystems的 Discord server频道,或跟帖评论提出您的问题!
期待您的精彩提交!祝好运 👍
参与此次竞赛,您同意 遵守相关条款,请认真阅读。
公告
Johnny Wang · 九月 2, 2021
2021 年 8 月的学习资料现在可以在learning.intersystems.com上独家获取!您可以:
先睹为快:2021 年虚拟峰会体验实验室
使用自适应分析(Adaptive Analytics)解决方案来组建你的第一个数据模型
免费试用 InterSystems IRIS 社区版
查看 InterSystems 文档中的分析
申请即将举行的线上技术课程
立刻报名!
注意:老是错过最新消息?别担心,我们会在9月恢复正常的邮件发送。
文章
Jingwei Wang · 六月 8, 2023
在InterSystems IRIS中重新加载更新后的Python模块的方式和直接使用Python 重新加载模块的方式是一样的。
在Python3.4 之后到版本中,直接使用Python 重新加载模块的方式如下:
import importlib
importlib.reload(module)
同样,在在InterSystems IRIS中重新加载Python模块的方式与其没有区别,示例如下:
ClassMethod Hello() As %Status
{
Set sc = $$$OK
Set sm = ##class(%SYS.Python).Import("sample")
Set importlib = ##class(%SYS.Python).Import("importlib")
do importlib.reload(sm)
write sm.hello()
Return sc
}
文章
Claire Zheng · 五月 9, 2023
2023年4月,InterSystems亚太区总经理老卢(Luciano Brustia)回到了阔别三年多的北京,针对一些热门问题分享了自己的观点:北京在疫情前后有什么不同?InterSystems是如何进行本土化创新服务中国市场的?与其他亚太国家相比,中国医疗信息化发展有什么特色?医疗信息化未来的发展方向和趋势是什么?
公告
Michael Lei · 二月 8, 2023
InterSystems 宣布其首个开发人员预览版,作为2023.1 版开发人员预览计划的一部分。 2023.1 中添加了许多更新和增强功能,还有全新的功能,例如对列存储Columnar Storage 的生产就绪支持、使用Bulk FHIR 的能力以及对MacOS 13 Ventura的支持。当前的开发人员预览版可能不提供其中一些功能或改进。
未来的预览版本预计每两周更新一次,我们将在功能准备就绪时添加它们。请通过开发者社区分享您的反馈,以便我们共同打造更好的产品。
可以在下面的这些链接中找到初始文档。它们将在接下来的几周内更新,直到正式宣布发布(一般可用性 - GA):
InterSystems IRIS
InterSystems IRIS医疗版
HealthShare HealthConnect
此外,查看此链接以获取与此版本相关的升级信息。
与往常一样,扩展维护 (EM) 版本附带适用于所有受支持平台的经典安装包,以及 Docker 容器格式的容器映像。有关完整列表,请参阅支持的平台文档。
安装包和预览密钥可从 WRC 的预览下载站点或通过评估服务网站获得(使用标记“显示预览软件”以访问 2023.1)。
InterSystems IRIS 和 IRIS for Health 的企业版和社区版的容器镜像以及所有相应的组件都可以从新的InterSystems Container Registry Web 界面获得。有关 docker 命令的更多信息,请参阅这篇文章: 宣布 InterSystems Container Registry Web 用户界面。
此开发人员预览版的内部版本号为2023.1.0.185.0 。
有关可用图像的完整列表,请参阅ICR 文档。或者,所有容器镜像的 tarball 版本都可以通过 WRC 的预览下载站点获得。
文章
姚 鑫 · 三月 26, 2021
# 第十三章 使用动态SQL(四)
# 返回完整结果集
使用`%Execute()`或`%ExecDirect()`执行语句将返回一个实现`%SQL.StatementResult`接口的对象。该对象可以是单一值,结果集或从`CALL`语句返回的上下文对象。
## %Display()方法
可以通过调用`%SQL.StatementResult`类的`%Display()`实例方法来显示整个结果集(结果对象的内容),如以下示例所示:
```
DO rset.%Display()
```
请注意,`%Display()`方法不会返回%Status值。
显示查询结果集时,`%Display()`通过显示行数来结束:“受影响的5行”。 (这是`%Display()`遍历结果集之后的`%ROWCOUNT`值。)请注意,`%Display()`不会在此行计数语句之后发出行返回。
`%Display()`有两个可选参数:
- 分隔符:在数据列和数据标题之间插入的字符串。它出现在结果集列之间,紧靠标题或数据值之前。默认为无定界符。如果省略,请在“列对齐”标志之前指定一个占位符逗号。
- 列对齐:整数标志,指定如何计算数据列和数据标题之间的空格。可用的选项有:
- 0:结果集标题/数据列将根据标准定界符(选项卡)对齐。这是默认值。
- 1:结果集标题/数据列将根据列标题和标准定界符(标签)的长度对齐。
- 2:结果集标题/数据列将根据列数据属性的精度/长度和标准定界符(选项卡)进行对齐。
## `%DisplayFormatted()`方法
可以通过调用`%SQL.StatementResult`类的`%DisplayFormatted()`实例方法,而不是调用`%Display()`,将结果集内容重新格式化并重定向到生成的文件。
可以通过指定字符串选项`%DisplayFormatted(“HTML”)`或相应的整数代码`%DisplayFormatted(1)`来指定结果集格式。可以使用以下格式:XML(整数代码0),HTML(整数代码1),PDF(整数代码2),TXT(整数代码99)或CSV(整数代码100)。 (请注意,CSV格式未实现为真正的逗号分隔值输出;相反,它使用制表符来分隔列。)TXT格式(整数代码99)以行数结尾(例如,“受影响的5行”) ”);其他格式不包括行数。 InterSystems IRIS生成指定类型的文件,并附加适当的文件扩展名。
可以指定或省略结果集文件名:
- 如果指定一个目标文件(例如,`%DisplayFormatted(99,"myresults")`),则在当前命名空间的子目录的mgr目录中生成具有该名称和相应后缀(文件扩展名)的文件。
例如,`C:\InterSystems\IRIS\mgr\user\myresults.txt`.
如果具有该后缀的指定文件已经存在,则InterSystems IRIS将用新数据覆盖它。
- 如果没有指定目标文件(例如,`%DisplayFormatted(99)`,则在Temp子目录的mgr目录中生成一个具有随机生成的名称和适当后缀(文件扩展名)的文件。
例如,`C:\InterSystems\IRIS\mgr\Temp\w4FR2gM7tX2Fjs.txt.`
每次运行一个查询时,都会生成一个新的目标文件。
这些例子显示了Windows文件名;
InterSystems IRIS支持其他操作系统上的等效位置。
如果无法打开指定的文件,则此操作将在30秒后超时并显示一条错误消息;否则,该操作将超时。当用户没有对指定目录(文件夹)的`WRITE`权限时,通常会发生这种情况。
**如果无法以指定的格式呈现数据,则将创建目标文件,但不会将结果集数据写入其中。而是将适当的消息写入目标文件。例如,流字段`OID`包含与XML和HTML特殊格式字符冲突的字符。可以通过在流字段上使用`XMLELEMENT`函数来解决此XML和HTML流字段问题。例如`SELECT Name,XMLELEMENT(“ Para”,Notes)`。**
可以选择提供`%DisplayFormatted()`在执行指定格式转换时将使用的转换表的名称。
如果一个结果集序列中有多个结果集,则每个结果集的内容都将写入其自己的文件中。
可选的第三个`%DisplayFormatted()`参数指定消息存储在单独的结果集中。成功完成后,将返回类似以下的消息:
```
Message
21 row(s) affected.
```
下面的Windows示例在`C:\InterSystems\IRIS\mgr\user\`中创建了两个PDF(整数代码2)结果集文件。
它为消息创建一个mess结果集,然后使用`%Display()`将消息显示到终端:
```java
/// d ##class(PHA.TEST.SQL).CreatePDF()
ClassMethod CreatePDF()
{
SET myquery=2
SET myquery(1)="SELECT Name,Age FROM Sample.Person"
SET myquery(2)="WHERE Age > ? AND Age < ? ORDER BY Age"
SET rset = ##class(%SQL.Statement).%ExecDirect(,.myquery,12,20)
IF rset.%SQLCODE'=0 {
WRITE !,"1st ExecDirect SQLCODE=",rset.%SQLCODE,!,rset.%Message QUIT
}
DO rset.%DisplayFormatted(2,"Teenagers",.mess)
DO mess.%Display()
WRITE !,"End of teen data",!!
SET rset2 = ##class(%SQL.Statement).%ExecDirect(,.myquery,19,30)
IF rset2.%SQLCODE'=0 {
WRITE !,"2nd ExecDirect SQLCODE=",rset2.%SQLCODE,!,rset2.%Message QUIT
}
DO rset2.%DisplayFormatted(2,"Twenties",.mess)
DO mess.%Display()
WRITE !,"End of twenties data"
}
```
```java
DHC-APP>d ##class(PHA.TEST.SQL).CreatePDF()
Message
9 row(s) affected.
End of teen data
Message
20 row(s) affected.
End of twenties data
```
```java
/// d ##class(PHA.TEST.SQL).CreatePDF1()
ClassMethod CreatePDF1()
{
ZNSPACE "SAMPLES"
SET myquery=2
SET myquery(1)="SELECT Name,Age FROM Sample.Person"
SET myquery(2)="WHERE Age > ? AND Age < ? ORDER BY Age"
SET rset = ##class(%SQL.Statement).%ExecDirect(,.myquery,12,20)
DO rset.%DisplayFormatted(2,"Teenagers")
WRITE !,"End of teen data",!!
SET rset2 = ##class(%SQL.Statement).%ExecDirect(,.myquery,19,30)
DO rset2.%DisplayFormatted(2,"Twenties")
WRITE !,"End of twenties data"
}
```
```java
DHC-APP>d ##class(PHA.TEST.SQL).CreatePDF1()
End of teen data
End of twenties data
```
## 对结果集进行分页
可以使用一个视图ID (`%VID`)来分页结果集。下面的例子从结果集中返回页面,每个页面包含5行:
```java
/// d ##class(PHA.TEST.SQL).Paginating()
ClassMethod Paginating()
{
SET q1="SELECT %VID AS RSRow,* FROM "
SET q2="(SELECT Name,Home_State FROM Sample.Person WHERE Home_State %STARTSWITH 'M') "
SET q3="WHERE %VID BETWEEN ? AND ?"
SET myquery = q1_q2_q3
SET tStatement = ##class(%SQL.Statement).%New()
SET qStatus=tStatement.%Prepare(myquery)
IF qStatus'=1 {
WRITE "%Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT
}
FOR i=1:5:25 {
WRITE !!,"Next Page",!
SET rset=tStatement.%Execute(i,i+4)
DO rset.%Display()
}
}
```
```java
DHC-APP>d ##class(PHA.TEST.SQL).Paginating()
Next Page
RSRow Name Home_State
1 O'Rielly,Chris H. MS
2 Orwell,John V. MT
3 Zevon,Heloisa O. MI
4 Kratzmann,Emily Z. MO
5 King,Dmitry G. MO
5 Rows(s) Affected
Next Page
RSRow Name Home_State
6 Hanson,George C. MD
7 Martinez,Emilio G. MO
8 Cheng,Charlotte Y. MI
9 Emerson,Edgar T. MO
10 Nelson,Neil E. MT
5 Rows(s) Affected
Next Page
RSRow Name Home_State
11 Larson,Nataliya Z. MD
12 Lennon,Chelsea T. MD
13 Ingleman,Kristen U. MT
14 Zucherro,Olga H. MN
15 Ng,Lola H. MD
5 Rows(s) Affected
Next Page
RSRow Name Home_State
16 Frost,Xavier D. MO
17 Adams,Diane F. MD
18 Isaacs,Chad N. MN
19 Van De Griek,Phil S. MS
20 Schaefer,Usha G. MO
5 Rows(s) Affected
Next Page
RSRow Name Home_State
21 Wells,Sophia U. MS
22 Vivaldi,Michelle N. MD
23 Anderson,Valery N. MD
24 Frost,Heloisa K. MI
25 Gallant,Thelma Q. MA
5 Rows(s) Affected
```
文章
姚 鑫 · 五月 30, 2022
# 第157章 SQL函数 WEEK
一个日期函数,它将一年中的第几周作为日期表达式的整数返回。
# 大纲
```
{fn WEEK(date-expression)}
```
# 参数
- `date-expression` - 一个表达式,它是列的名称、另一个标量函数的结果,或者是日期或时间戳文字。
# 描述
`WEEK` 接受一个日期表达式,并返回该日期从年初开始的周数。
默认情况下,使用 `$HOROLOG` 日期(从 1840 年 12 月 31 日开始的正整数或负整数天数)计算周数。因此,周数是逐年计算的,因此第 1 周是完成从上一年最后一周开始的 7 天期间的天数。一周总是从星期日开始;因此,日历年的第一个星期日标志着从第 1 周到第 2 周的变化。如果一年中的第一个星期日是 1 月 1 日,则该星期日是第 1 周;如果一年中的第一个星期日晚于 1 月 1 日,则该星期日是第 2 周的第一天。因此,第 1 周的长度通常少于 7 天。可以使用 `DAYOFWEEK` 函数确定星期几。一年中的总周数通常为 `53`,闰年可能为 `54`。
IRIS 还支持确定一年中星期的 ISO 8601 标准。该标准主要用于欧洲国家。当配置为 ISO 8601 时,`WEEK` 从星期一开始计算星期,并将星期分配给包含该星期星期四的年份。例如,2004 年的第 1 周从 2003 年 12 月 29 日星期一到 2004 年 1 月 4 日星期日,因为本周的星期四是 2004 年 1 月 1 日,这是 2004 年的第一个星期四。2005 年的第 1 周是从 2005 年 1 月 3 日星期一到 1 月 9 日星期日2005,因为它的星期四是 2005 年 1 月 6 日,也就是 2005 年的第一个星期四。一年中的总周数通常是 52,但偶尔也可能是 53。要激活 ISO 8601 计数, `SET ^%SYS("sql","sys","week ISO8601")=1`.
日期表达式可以是 日期整数、`$HOROLOG` 或 `$ZTIMESTAMP` 值、ODBC 格式日期字符串或时间戳。
日期表达式时间戳可以是数据类型 `%Library.PosixTime`(编码的 64 位有符号整数),也可以是数据类型 `%Library.TimeStamp` (`yyyy-mm-dd hh:mm:ss.fff`)。
时间戳的时间部分不被评估,可以省略。
使用 `DATEPART` 或 `DATENAME` 函数可以返回相同的星期信息。
也可以使用 `WEEK() `方法调用从 ObjectScript 调用此函数:
```
$SYSTEM.SQL.Functions.WEEK(date-expression)
```
## 日期验证
`WEEK` 对输入值执行以下检查。如果某个值未通过检查,则返回空字符串。
- 日期字符串必须完整且格式正确,其中包含适当数量的元素和每个元素的数字,以及适当的分隔符。年份必须指定为四位数。
- 日期值必须在有效范围内。年:0001 到 9999。月:1 到 12。日:1 到 31。
- 一个月的天数必须与月份和年份相匹配。例如,日期`“02–29”`仅在指定年份是闰年时有效。
- 小于 10 的日期值可以包括或省略前导零。不允许使用其他非规范整数值。因此,`Day` 值`“07”`或`“7”`有效,但`“007”`、`“7.0”`或`“7a”`无效。
# 示例
以下嵌入式 SQL 示例返回 2005 年 1 月 2 日(星期日)和 2006 年 1 月 1 日(星期日)的星期几和一年中的星期几。
```java
/// d ##class(PHA.TEST.SQLFunction).Week()
ClassMethod Week()
{
SET x = "2005-1-2"
SET y = "2006-1-1"
&sql(
SELECT
{fn DAYOFWEEK(:x)},{fn WEEK(:x)},
{fn DAYOFWEEK(:y)},{fn WEEK(:y)}
INTO
:a,:b,:c,:d
)
if SQLCODE '= 0 {
w !,"Error code ",SQLCODE
} else {
w !,"2005 Day of Week is: ",a," (Sunday=1)"
w " Week of Year is: ",b
w !,"2006 Day of Week is: ",c," (Sunday=1)"
w " Week of Year is: ",d
}
}
```
```java
DHC-APP>d ##class(PHA.TEST.SQLFunction).Week()
2005 Day of Week is: 1 (Sunday=1) Week of Year is: 2
2006 Day of Week is: 1 (Sunday=1) Week of Year is: 1
```
以下示例返回数字 `9`,因为日期是 `2004` 年的第九周:
```sql
SELECT {fn WEEK('2004-02-25')} AS Wk_Date,
{fn WEEK('2004-02-25 08:35:22')} AS Wk_Tstamp,
{fn WEEK(59590)} AS Wk_DInt
9 9 9
```
以下示例返回数字 `54`,因为此特定日期是闰年,从第 2 周开始,从第二天开始,如紧随其后的示例所示:
```sql
SELECT {fn WEEK('2000-12-31')} AS Week
54
```
```sql
SELECT {fn WEEK('2000-01-01')}||{fn DAYNAME('2000-01-01')} AS WeekofDay1,
{fn WEEK('2000-01-02')}||{fn DAYNAME('2000-01-02')} AS WeekofDay2
1Saturday 2Sunday
```
以下示例均返回当前周:
```sql
SELECT {fn WEEK({fn NOW()})} AS Wk_Now,
{fn WEEK(CURRENT_DATE)} AS Wk_CurrD,
{fn WEEK(CURRENT_TIMESTAMP)} AS Wk_CurrTS,
{fn WEEK($HOROLOG)} AS Wk_Horolog,
{fn WEEK($ZTIMESTAMP)} AS Wk_ZTS
20 20 20 20 20
```
以下嵌入式 SQL 示例显示了 默认的一年中的一周以及应用 ISO 8601 标准的一年中的一周:
```sql
/// d ##class(PHA.TEST.SQLFunction).Week1()
ClassMethod Week1()
{
TestISO
s def = $d(^%SYS("sql","sys","week ISO8601"))
if def = 0 {
s ^%SYS("sql","sys","week ISO8601")=0
} else {
s isoval = ^%SYS("sql","sys","week ISO8601")
}
if isoval = 1 {
g UnsetISO
} else {
s isoval=0
g WeekOfYear
}
UnsetISO
s ^%SYS("sql","sys","week ISO8601") = 0
WeekOfYear
&sql(
SELECT
{fn WEEK($HOROLOG)}
INTO
:a
)
w "For Today:",!
w "default week of year is ",a,!
s ^%SYS("sql","sys","week ISO8601") = 1
&sql(
SELECT
{fn WEEK($HOROLOG)}
INTO
:b
)
w "ISO8601 week of year is ",b,!
ResetISO
s ^%SYS("sql","sys","week ISO8601") = isoval
}
```
文章
Qiao Peng · 三月 29, 2021
InterSystems IRIS/Caché的CDC
InterSystems IRIS/Caché未提供开箱即用的变更数据捕获(CDC)工具,而且由于其多模型建模能力和底层的多维存储模型,相对于关系型数据库的单一模型,针对于SQL的CDC在InterSystems IRIS/Caché上会更复杂一些。例如通过Journal日志记录的是底层持久化多维数组的数据变更,而不是SQL table的变更。
通常,在应用层面实现变更数据捕获是更灵活和简单的方式,例如通过设置触发器、类的DSTIME参数。但如果无法在应用层做CDC,可以考虑使用InterSystems IRIS/Caché的Journal和强大的开发能力获取数据变更。
这里介绍使用InterSystems IRIS/Caché的Reporting类型的异步镜像成员获取数据变更。
Dejournal 过滤器
InterSystems IRIS/Caché的 Dejournal 过滤器用于在Reporting类型的异步镜像成员上过滤Journal记录。当配置了Dejournal 过滤器后,异步镜像成员在redo journal前会自动调用Dejournal过滤器类的方法RunFilter,并传入以下参数: 1. MirrorDBName:镜像数据库名称; 2. GlobalReference:Global节点(包括下标); 3. RecordType:操作类型,为S(Set)和K(Kill); 4. Address:Journal记录在Journal文件中的偏移量。
我们可以利用自定义的Dejournal过滤器,捕获持久化多维数组(Global)的数据变化,并输出给外部系统。
注意:1. 如果仅为实现CDC,并不需要配置镜像备机。2. Dejournal过滤器只能配置在Reporting类型的异步镜像成员上。3. 镜像配置不在本文内容里,请参考文档:[IRIS] https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls?KEY=GHA_mirror[Caché] https://cedocs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GHA_mirror
编写Dejournal过滤器
InterSystems IRIS/Caché提供镜像Dejournal系统类 - SYS.MirrorDejournal。对于用户自定义过滤逻辑,通过继承于SYS.MirrorDejournal的子类来实现。
在Reporting异步镜像成员的%SYS命名空间(IRISLIB数据库)下创建SYS.MirrorDejournal的子类,命名应以Z或z开头,以避免升级时被覆盖,例如命名为ZCustom.MirrorDejournal。注意: IRISLIB数据库默认是只读的,需要先将其修改为可读写。
Override该类的RunFilter方法,将数据变更捕获的逻辑放在该方法里,并根据需要返回1或0。1代表这个global变更需要dejournal,0代表不需要。即便仅仅是为实现CDC,建议在Reporting异步镜像成员恢复所有数据,即让该方法返回1,从而不需要影响生产系统,直接从Reporting异步镜像成员上获取所有的变更数据。
例如,将global的数据变更记录在^CDCLog中:
Class ZCustom.MirrorDejournal Extends SYS.MirrorDejournal
{
Method RunFilter(
MirrorDBName As %String,
GlobalReference As %String,
RecordType As %String,
Address As %Integer) As %Integer
{
Set ^CDCLog( $$I ($^CDCLog))=$lb(MirrorDBName,GlobalReference,RecordType,Address)
Quit 1
}
}
配置Dejournal过滤器
在Reporting异步镜像成员上,配置其镜像Dejournal过滤器为上面创建的过滤器类的名称。
后记
今天有人问到,如何获取变更的值和变更前的值。可以使用`$$$JRNNEWVAL(Address) 、$$$JRNOLDVAL(Address)`在上面的RunFilter方法中获取变更后和变更前的数据。注意,`$$$JRNNEWVAL(Address) 、$$$JRNOLDVAL(Address)`这2个宏定义在%syJrnRecord.inc文件里,因此需要将这个include文件加入ZCustom.MirrorDejournal类定义:Include %syJrnRecord
又,在InterSystems IRIS上修改并编译dejournal过滤器类后,需要重启异步镜像成员的Mirror,以使更改生效。
CDC系列
更多的CDC选项实现,请参考:
1. CDC系列之一 :使用Dejournal Filter在InterSystems IRIS/Caché上通过Mirroring实现CDC功能
2. CDC系列之二 :使用Dejournaling filter routine在Caché上通过Shadow实现CDC
3. CDC系列之三 :建立InterSystems IRIS/Caché的Global数据变更与SQL表记录的对应关系
4. CDC系列之四:使用DSTIME特性在InterSystems IRIS/Caché上实现CDC功能
很好的文章 学习一下
文章
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
文章
姚 鑫 · 三月 8, 2021
# 第五章 SQL定义表(三)
# 使用DDL定义表
可以使用标准DDL命令在InterSystems SQL中定义表:
InterSystems SQL中可用的DDL命令
- `ALTER`命令 `ALTER TABLE`,`ALTER VIEW`
- `CREATE` 命令 `CREATE TABLE`,`CREATE VIEW`,`CREATE INDEX`,`CREATE TRIGGER`
- `DROP` 命令 `DROP TABLE`,`DROP VIEW`,`DROP INDEX`,`DROP TRIGGER`
可以通过多种方式执行DDL命令,包括:
- 使用动态SQL。
- 使用嵌入式SQL。
- 使用DDL脚本文件。
- 使用ODBC调用。
- 使用JDBC调用。
## 在嵌入式SQL中使用DDL
在ObjectScript方法或例程中,可以使用嵌入式SQL来调用DDL命令。
例如,以下方法创建一个`Sample.Employee`表:
```java
/// d ##class(PHA.TEST.SQL).CreateTable()
ClassMethod CreateTable() As %String
{
&sql(CREATE TABLE Sample.Employee (
EMPNUM INT NOT NULL,
NAMELAST CHAR (30) NOT NULL,
NAMEFIRST CHAR (30) NOT NULL,
STARTDATE TIMESTAMP,
SALARY MONEY,
ACCRUEDVACATION INT,
ACCRUEDSICKLEAVE INT,
CONSTRAINT EMPLOYEEPK PRIMARY KEY (EMPNUM)))
IF SQLCODE=0 {WRITE "Table created" RETURN "Success"}
ELSEIF SQLCODE=-201 {WRITE "Table already exists" RETURN SQLCODE}
ELSE {WRITE "Serious SQL Error, returning SQLCODE" RETURN SQLCODE_" "_%msg}
}
```
```java
DHC-APP>d ##class(PHA.TEST.SQL).CreateTable()
Table already exists
```
调用此方法时,它将尝试创建`Sample.Employee`表(以及相应的`Sample.Employee`类)。如果成功,则将`SQLCODE`变量设置为0。如果失败,则`SQLCODE`包含指示错误原因的SQL错误代码。
这样的DDL命令失败的最常见原因是:
- `SQLCODE -99`(违反权限):此错误表明没有执行所需DDL命令的权限。通常,这是因为应用程序尚未确定当前用户是谁。可以使用`$SYSTEM.Security.Login()`方法以编程方式执行此操作:
```java
DHC-APP>w $SYSTEM.Security.Login("yx","123456")
0
```
`SQLCODE -201`(表或视图名称不是唯一的):此错误表明正在尝试使用已经存在的表的名称创建新表。
## 使用类方法执行DDL
在ObjectScript中,可以使用`Dynamic SQL%SQL.Statement`对象使用`Dynamic SQL`准备和执行DDL命令。
下面的示例定义了一个使用动态SQL创建表的类方法:
```java
ClassMethod DefTable(user As %String,pwd As %String) As %Status [Language=objectscript]
{
DO ##class(%SYSTEM.Security).Login(user,pwd)
SET myddl=2
SET myddl(1)="CREATE TABLE Sample.MyTest "
SET myddl(2)="(NAME VARCHAR(30) NOT NULL,SSN VARCHAR(15) NOT NULL)"
SET tStatement=##class(%SQL.Statement).%New()
SET tStatus=tStatement.%Prepare(.myddl)
IF qStatus'=1 {WRITE "%Prepare failed:" DO $System.Status.DisplayError(qStatus) QUIT}
SET rset=tStatement.%Execute()
IF rset.%SQLCODE=0 {WRITE "Created a table"}
ELSEIF rset.%SQLCODE=-201 {WRITE "table already exists"}
ELSE {WRITE "Unexpected error SQLCODE=",rset.%SQLCODE}
}
```
与嵌入式SQL示例一样,如果当前没有用户登录,则此方法将失败。
## 通过导入和执行DDL脚本定义表
可以使用`IRIS()`方法从终端会话中交互式地导入InterSystems SQL DDL脚本文件,也可以使用`DDLImport(“ IRIS”)`方法作为后台作业来导入InterSystems SQL DDL脚本文件。此方法可以导入和执行多个SQL命令,使可以使用txt脚本文件来定义表和视图,并用数据填充它们。
如果要将表从另一供应商的关系数据库迁移到InterSystems IRIS,则文本文件中可能包含一个或多个DDL脚本。 InterSystems IRIS提供了几种`%SYSTEM.SQL`方法来帮助将此类表加载到InterSystems IRIS中。可以使用通用的`DDLImport()`方法或特定供应商的`%SYSTEM.SQL`方法。供应商特定的SQL转换为InterSystems SQL并执行。错误和不支持的功能记录在日志文件中。
例如,从ObjectScript命令行加载一个Oracle DDL文件:
1. 使用InterSystems IRIS启动器菜单中的“终端”命令启动终端会话。
2. 切换到希望在其中加载表定义的名称空间:
```java
SET $namespace = "MYNAMESPACE"
```
3. 调用所需的DDL导入方法:
```java
DO $SYSTEM.SQL.Oracle()
```
并按照终端上显示的说明进行操作。

# 定义分片表
创建分片表有三个要求。
1. 许可证密钥必须支持分片。使用管理门户,系统管理,许可,许可证密钥显示当前许可证或激活新许可证。
2. 必须在IRIS实例上启用分片。必须具有`%Admin_Secure`特权才能启用分片。使用“管理门户”,“系统管理”,“配置”,“系统配置”,“分片配置”来选择“启用分片”按钮。这使当前的InterSystems IRIS实例可以在分片群集中使用。选择“为任何角色启用此实例”或“仅对碎片主机角色启用此实例”。按确定。重新启动您的InterSystems IRIS实例。
3. 必须在IRIS实例上部署分片群集。此分片群集包含一个分片主名称空间。如果未为分片配置当前名称空间,则尝试定义分片表失败,并显示错误#9319:当前名称空间%1没有配置分片。
然后,可以在Shard Master命名空间中定义一个分片表,该表已定义为分片集群的一部分。可以使用`CREATE TABLE`通过指定分片键来定义分片表。或者,可以创建一个持久化类,该持久化类投影到分片表。
# 通过查询现有表定义表
可以使用`$SYSTEM.SQL.QueryToTable()`方法基于一个或多个现有表来定义和填充新表。指定一个查询和一个新的表名称。现有表名和/或新表名可以是合格的或不合格的。该查询可以包含`JOIN`语法。该查询可以提供列名别名,这些别名将成为新表中的列名。
1. `QueryToTable()`复制现有表的DDL定义,并为其指定指定的新表名。它复制查询中指定的字段的定义,包括数据类型,`maxlength`和`minval / maxval`。它不复制字段数据约束,例如默认值,必需值或唯一值。它不会将引用从字段复制到另一个表。
如果查询指定`SELECT *`或`SELECT%ID`,则将原始表的`RowID`字段复制为数据类型为整数的非必需,非唯一数据字段。 `QueryToTable()`为新表生成唯一的`RowID`字段。如果复制的`RowID`名为`ID`,则生成的`RowID`名为`ID1`。
`QueryToTable()`为此新表创建一个对应的持久化类。持久类定义为DdlAllowed。新表的所有者是当前用户。
不管源表中的这些设置如何,新表都将使用`Default Storage = YES`定义,并且`Supports Bitmap Indices = YES`。
为新表创建的唯一索引是`IDKEY`索引。没有位图范围索引生成。复制字段的索引定义不会复制到新表中。
2. `QueryToTable()`然后使用查询选择的字段中的数据填充新表。它将表格的“范围大小”设置为100,000。它估计`IDKEY`块计数。运行“音调表”以设置实际的“范围大小”和“块计数”,以及每个字段的“选择性”和“平均字段大小”值。
`QueryToTable()`既创建表定义,又用数据填充新表。如果只希望创建表定义,请在查询`WHERE`子句中指定一个不选择任何数据行的条件。例如,`WHERE Age < 20 AND Age > 20`.
下面的示例从S`ample.Person`复制`“名称”`和`“年龄”`字段,并创建一个AVG(Age)字段。这些字段定义用于创建名为`Sample.Youth`的新表。然后,该方法`where Age < 21`. 的那些记录的`Sample.Person`数据填充`Sample.Youth`。`AvgInit`字段包含创建表时所选记录的合计值。
```java
DO $SYSTEM.SQL.QueryToTable("SELECT Name,Age,AVG(Age) AS AvgInit FROM Sample.Person WHERE Age < 21","Sample.Youth",1,.errors)
```
```java
DHC-APP> DO $SYSTEM.SQL.QueryToTable("SELECT Name,Age,AVG(Age) AS AvgInit FROM Sample.Person WHERE Age < 21","Sample.Youth",1,.errors)
Preparing query...
Creating class...
Compiling class...
Copying data...
```

# 外部表
在InterSystems SQL中,还可以具有“外部表”,这些表在SQL词典中定义但存储在外部关系数据库中。外部表的行为就像它们是本机InterSystems IRIS表一样:可以对它们发出查询并执行`INSERT`,`UPDATE`和`DELETE`操作。 InterSystems SQL网关提供对外部数据库的访问,该网关使用ODBC或JDBC提供透明的连接。
# List表
`INFORMATION.SCHEMA.TABLES`持久类显示有关当前名称空间中所有表(和视图)的信息。它提供了许多属性,包括模式和表名称,表的所有者以及是否可以插入新记录。 `TABLETYPE`属性指示它是基表还是视图。
以下示例返回当前名称空间中所有表和视图的表类型,架构名称,表名称和所有者:
```java
SELECT Table_Type,Table_Schema,Table_Name,Owner FROM INFORMATION_SCHEMA.TABLES
```

`INFORMATION.SCHEMA.CONSTRAINTTABLEUSAGE`持久类为为当前名称空间中的每个表定义的每个主键(显式或隐式),外键或唯一性约束显示一行。 `INFORMATION.SCHEMA.KEYCOLUMNUSAGE`为定义为当前名称空间中每个表的这些约束之一的一部分的每个字段显示一行。
# 列出列名和数字
可以通过以下四种方式列出指定表的所有列名(字段名):
- `GetColumns()`方法。这列出了所有列名和列号,包括隐藏的列。 `ID(RowID)`字段可以隐藏也可以不隐藏。 `x__classname`列始终是隐藏的;除非使用`Final class`关键字定义了持久类,否则它将自动定义。
- 管理门户网站SQL界面(系统资源管理器,SQL)架构内容的“目录详细信息”选项卡。它列出了所有列名和列号(包括隐藏的列)以及其他信息,包括数据类型和指示列是否被隐藏的标志。
- `SELECT TOP 0 * FROM`表名。这将按列号顺序列出所有非隐藏的列名。请注意,由于隐藏的列可以按列号顺序出现在任何位置,因此您无法通过计算这些非隐藏的列名来确定列号。
- `INFORMATION.SCHEMA.COLUMNS`持久类为当前名称空间中每个表或视图中的每个非隐藏列列出一行。 `INFORMATION.SCHEMA.COLUMNS`提供了大量属性,用于列出表和视图列的特征。请注意,`ORDINALPOSITION`与列号不同,因为不计算隐藏字段。 `GetColumns()`方法同时计算隐藏字段和非隐藏字段。
下面的示例使用`INFORMATION.SCHEMA.COLUMNS`列出一些列属性:
```java
SELECT TABLE_NAME,COLUMN_NAME,ORDINAL_POSITION,DATA_TYPE,CHARACTER_MAXIMUM_LENGTH,
COLUMN_DEFAULT,IS_NULLABLE,UNIQUE_COLUMN,PRIMARY_KEY
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='Sample'
```

## GetColumns()方法
要以列号顺序列出表中的列名,可以使用`GetColumns()`方法,如下所示:
```java
/// d ##class(PHA.TEST.SQL).GetColumn()
ClassMethod GetColumn()
{
SET stat=##class(%SYSTEM.SQL).GetColumns("Sample.Person",.byname,.bynum)
IF stat=1 {
SET i=1
WHILE $DATA(bynum(i)) {
WRITE "name is ",bynum(i)," col num is ",i,!
SET i=i+1
}
}
ELSE { WRITE "GetColumns()无法找到指定的表" }
}
```
`GetColumns()`列出所有已定义的列,包括隐藏的列。如果表引用了嵌入式`%SerialObject`类,则`GetColumns()`首先列出持久性类中的所有列,包括引用`%SerialObject`的属性,然后列出所有`%SerialObject`属性。在下面的`GetColumns()`结果中显示了这一点:
```java
DHC-APP>d ##class(PHA.TEST.SQL).GetColumn()
name is ID col num is 1
name is Age col num is 2
name is DOB col num is 3
name is FavoriteColors col num is 4
name is Home col num is 5
name is Name col num is 6
name is Office col num is 7
name is SSN col num is 8
name is Spouse col num is 9
name is x__classname col num is 10
name is Home_City col num is 11
name is Home_State col num is 12
name is Home_Street col num is 13
name is Home_Zip col num is 14
name is Office_City col num is 15
name is Office_State col num is 16
name is Office_Street col num is 17
name is Office_Zip col num is 18
```
还可以使用此方法确定指定列名的列号,如下所示:
```java
/// d ##class(PHA.TEST.SQL).GetColumn1()
ClassMethod GetColumn1()
{
SET stat=##class(%SYSTEM.SQL).GetColumns("Sample.Person",.byname)
IF stat=1 {
WRITE "Home_State is column number ",byname("Home_State"),!
} ELSE {
WRITE "GetColumns()无法找到指定的表"
}
}
```
```java
DHC-APP>d ##class(PHA.TEST.SQL).GetColumn1()
Home_State is column number 12
```
公告
Claire Zheng · 九月 23, 2022
亲爱的社区同学们!
2022年9月5日-10月24日,我们正在举办InterSystems开发者社区中文版首届技术征文大赛!
🏆InterSystems开发者社区中文版首届技术征文大赛🏆(←点击链接进入参赛页面,浏览所有参赛文章)!
2022年9月27日(下周二)11:00-11:30,我们将进行一次针对此次征文大赛的线上宣讲,欢迎您通过腾讯会议参加,了解关于此次征文大赛的信息,针对感兴趣的问题提问。
#腾讯会议信息
会议主题:InterSystems 社区技术征文大赛宣讲&解读会议时间:2022/09/27 11:00-11:30 (GMT+08:00) 中国标准时间 - 北京
点击链接入会,或添加至会议列表:https://meeting.tencent.com/dm/4UEzyh467wae
#腾讯会议:493-643-076