搜索​​​​

清除过滤器
公告
Claire Zheng · 七月 4, 2024

积极参与社区互动,赢取中文社区最佳贡献奖!

👉即日起积极参与社区互动,就有机会获得赠书《AI医疗革命》(中文版)! Hi 开发者们, 为鼓励大家积极参与社区建设,即日起我们将持续、按月举办💡“中文社区最佳贡献奖”💡活动。 📅 活动简介 我们会在每个月的新增成员和现有成员中分别抽取一名当月积分最高的社区成员,奉上“中文社区最佳贡献奖”,奖品为《AI医疗革命》(中文繁体译版)一本。本书中文简体译版为《超越想象的GPT医疗》,原著The AI REVOLUTION IN MEDICINE(GPT-4 AND BEYOND) 出版于2023年,作者Peter Lee,Carey Goldberg,Isaac Kohane分享了以GPT-4 为代表的大语言模型在医学领域的诸多应用可能性,更重要的是向大家展现了一种可能出现的人- 机相结合的“关系”范式。本书(中文简体译版)也在CHIMA 2024期间作为优秀图书得到了推荐,值得一读。 🎉 哪些成员可以参与? InterSystems开发者社区中文社区现有成员,以及当月新加入中文社区的成员(非InterSystems员工),均在此次活动范围。 ✅如何参与? 我们欢迎您在社区进行以下互动: 发布文章/经验帖; 在Open Exchange发布应用; 在现有的帖子下,积极发布有效评论/回复; 将英文社区的文章翻译到中文社区; 邀请新成员加入开发者社区(如果您邀请了新成员,请通过站内信联系 @Xuying.Zheng 并告知)。 🎁 获奖须知 每位社区成员仅有一次获奖机会,我们会在抽奖时排除已获得过“中文社区最佳贡献奖”的成员。 我们会于次月公布上月的获奖者,通过开发者社区站内信与获奖者取得联系并进行奖品邮寄。敬请您留意。 🍀 如果您对此次活动有任何疑问,欢迎跟帖提问!🍀
文章
姚 鑫 · 四月 29, 2021

第九章 冻结计划

# 第九章 冻结计划 大多数SQL语句都有一个关联的查询计划。查询计划是在准备SQL语句时创建的。默认情况下,添加索引和重新编译类等操作会清除此查询计划。下次调用查询时,将重新准备查询并创建新的查询计划。冻结计划使可以跨编译保留(冻结)现有查询计划。查询执行使用冻结的计划,而不是执行新的优化并生成新的查询计划。 对系统软件的更改也可能导致不同的查询计划。通常,这些升级会带来更好的查询性能,但软件升级可能会降低特定查询的性能。冻结计划使可以保留(冻结)查询计划,以便查询性能不会因系统软件升级而改变(降级或提高)。 # 如何使用冷冻计划 使用冻结计划有两种策略-乐观策略和悲观策略: - 乐观:如果假设更改系统软件或类定义会提高性能,请使用此策略。运行查询并冻结计划。导出(备份)冻结的计划。解冻该计划。更改软件。重新运行查询。这会产生一个新的计划。比较这两个查询的性能。如果新计划没有提高性能,可以从备份文件中导入先前冻结的计划。 - 悲观:如果假设系统软件或类定义的更改可能不会提高特定查询的性能,请使用此策略。运行查询并冻结计划。更改软件。使用`%NOFPLAN`关键字重新运行查询(这会导致冻结的计划被忽略)。比较这两个查询的性能。如果忽略冻结的计划没有提高性能,请保持冻结该计划并从查询中删除`%NOFPLAN`。 # 软件版本升级自动冻结计划 将InterSystems IRIS®Data Platform升级到新的主要版本时,现有的查询计划将自动冻结。这可确保重大软件升级永远不会降低现有查询的性能。升级软件版本后,对性能关键型查询执行以下步骤: 1. 执行计划状态为冻结/升级的查询,并监控性能。这是在软件升级之前创建的优化查询计划。 2. 将`%NOFPLAN`关键字添加到查询中,然后执行并监视性能。这将使用软件升级提供的SQL优化器优化查询计划。它不会解冻现有的查询计划。 3. 比较性能指标。 - 如果`%NOFPLAN`性能更好,则软件升级改进了查询计划。解冻查询计划。删除`%NOFPLAN`关键字。 - 如果`%NOFPLAN`性能较差,则软件升级会使查询计划降级。保持查询计划冻结状态,将查询计划从冻结/升级升级为冻结/显式。删除`%NOFPLAN`关键字。 4. 测试性能关键型查询后,可以解冻所有剩余的冻结/升级计划。 当在比最初创建计划时使用的InterSystems软件版本更新的InterSystems软件版本下准备/编译查询时,会发生这种自动冻结。例如,考虑一条在系统软件版本xxxx.1下准备/编译的SQL语句。随后升级到版本xxxx.2,再次准备/编译SQL语句。系统将检测到这是SQL语句在新版本上的第一次准备/编译,并自动将计划状态标记为冻结/升级,并将现有计划用于新的准备/编译。这确保使用的查询计划不会比以前版本的查询计划差。 只有主要版本的InterSystems系统软件升级才会自动冻结现有查询计划。维护发布版本升级不会冻结现有查询计划。例如,主要版本升级(如从2018.1升级到2019.1)将执行此操作。维护版本升级(如2018.1.0到2018.1.1)不执行此操作。 在管理门户SQL界面中,SQL语句计划状态列将这些自动冻结的计划指示为冻结/升级,计划版本指示原始计划的系统间软件版本。 可以使用`INFORMATION.SCHEMA.STATEMENTS` `Frozen=2`属性列出当前命名空间中的所有冻结/升级计划。 可以使用以下`$SYSTEM.SQL.Statement`方法冻结单个查询计划或多个查询计划:`FreezeStatement()`用于单个计划;`FreezeRelation()`用于关系的所有计划;`FreezeSchema()`用于架构的所有计划;`FreezeAll()`用于当前命名空间中的所有计划。有相应的解冻方法。 - 冻结方法可以提升(“冻结”)标记为冻结/升级到冻结/显式的查询计划。通常,可以使用此方法有选择地将适当的冻结/升级计划升级为冻结/显式,然后解冻所有剩余的冻结/升级计划。 - 解冻方法可以解冻指定范围内的冻结/升级查询计划:命名空间、架构、关系(表)或单个查询。 # 冻结计划界面 冻结计划界面有两种,用途不同: - Management Portal SQL语句界面,用于冻结(或解冻)单个查询的计划。 - `$SYSTEM.SQL.Statement`冻结和解冻方法,用于冻结或解冻命名空间、架构、表或单个查询的所有计划。 在Management Portal SQL界面中,选择`Execute Query`选项卡。编写查询,然后单击显示计划按钮以显示当前查询执行计划。如果计划被冻结,则查询计划部分的第一行是“冻结计划”。 在管理门户SQL界面中,选择SQL语句选项卡。这将显示SQL语句列表。此列表的计划状态列指定解冻、解冻/并行、冻结/显式或冻结/升级。(如果语句没有关联的查询计划,则计划状态列为空。) 可以使用`INFORMATION.SCHEMA.STATEMENTS` Frozen属性值列出当前命名空间中所有SQL语句的计划状态:`UNFRECTED(0)`、`Frozen/EXPLICIT(1)`、`Frozen/Upgrade(2)`或`UNFORMATED/PARALLEL(3)`。 要冻结或解冻计划,请在SQL语句文本列中选择SQL语句。这将显示“SQL语句详细信息”框。在此框的底部显示对帐单文本和查询计划。如果计划未冻结,则这些横断面的背景颜色为绿色,如果计划已冻结,则背景颜色为蓝色。在其正上方的对帐单操作下,可以根据需要选择冻结计划或解冻计划按钮。然后选择关闭。 - 冻结计划按钮:单击此按钮将冻结此语句的查询优化计划。冻结计划并编译该SQL语句时,SQL编译将使用冻结的计划信息并跳过查询优化阶段。 - 解冻计划按钮:点击该按钮将删除该语句冻结的计划,该语句的新编译将进入查询优化阶段,以确定要使用的最佳计划。 还可以使用`$SYSTEM.SQL.Statement`冻结和解冻方法冻结或解冻一个或多个计划。通过指定适当的方法,可以指定冻结或解冻操作的范围:单个计划的`FreezeStatement()`;关系的所有计划的`FreezeRelation()`;架构的所有计划的`FreezeSchema()`;当前命名空间中的所有计划的`FreezeAll()`。有相应的解冻方法。 ## 权限 用户只能查看他们具有`EXECUTE`权限的那些SQL语句。这既适用于Management Portal SQL语句列表,也适用于`INFORMATION.SCHEMA.STATEMENTS`类查询。 管理门户SQL语句访问要求对`%Development`资源具有`“USE”`权限。任何可以在管理门户中看到SQL语句的用户都可以冻结或解冻该语句。 对于SQL语句的目录访问,如果您具有执行该语句的权限或对`%Development`资源具有`“Use”`权限,则可以看到这些语句。 对于`$SYSTEM.SQL.Statement`冻结或解冻方法调用,必须对`%Developer`资源拥有`“U”`权限。 ## 冻结计划不同 如果计划被冻结,可以确定解冻该计划是否会导致不同的计划,而无需实际解冻该计划。此信息可以帮助您确定哪些SQL语句值得使用`%NOFPLAN`进行测试,以确定解冻计划是否会带来更好的性能。 可以使用`INFORMATION.SCHEMA.STATEMENTS` `FrozenDifferent`属性列出当前命名空间中此类型的所有冻结计划。 冻结的计划可能会因以下任一操作而与当前计划不同: - 重新编译该表或该表引用的表 - 使用`SetMapSelecability()`激活或停用索引 - 在表上运行`TuneTable` - 升级InterSystems软件版本 重新编译会自动清除现有的缓存查询。对于其他操作,必须手动清除现有缓存查询才能使新查询计划生效。 这些操作可能会也可能不会产生不同的查询计划。有两种方法可以确定它们是否这样做: - 手工检查个别冻结计划 - 每天自动扫描所有冻结计划 如果计划尚未由这两个操作中的任何一个检查,或者计划未冻结,则列出新计划的SQL语句列为空。解冻选中的冻结计划会将新建计划列重置为空。 ## 手动冻结计划检查 在冻结计划的SQL语句详细资料页的顶部有一个检查冻结按钮。按此按钮将显示解冻不同计划复选框。如果选中此框,则解冻计划将导致不同的查询计划。 对冻结计划执行此检查冻结测试后: - 如果选中解冻计划不同框,则列出新计划的SQL语句列包含“1”。这表明解冻计划将导致不同的计划。 - 如果未选中解冻计划不同框,则列出新计划的SQL语句列将包含“0”。这表明解冻计划不会产生不同的计划。 - 已冻结的缓存查询的New Plan为“0”;清除缓存查询,然后解冻该计划会导致SQL语句消失。 - 已冻结的`Natura`l查询在New Plan列中为空。 执行此测试后,检查冻结按钮消失。如果要重新测试冻结的计划,请选择刷新页面按钮。这将重新显示检查冻结按钮。 ## 日冻结计划自动检查 InterSystems SQL每晚`2:00`自动扫描SQL语句清单中的所有冻结语句。这次扫描最多持续一个小时。如果扫描未在一小时内完成,系统会记下它停止的位置,并从该点继续进行下一次每日扫描。可以使用管理门户监视此每日扫描或强制其立即扫描:选择系统操作、任务管理器、任务计划,然后选择扫描冻结计划任务。 此扫描检查所有冻结的计划: - 如果冻结的计划具有与当前版本相同的InterSystems软件版本,InterSystems IRIS®Data Platform将计算两个计划的引用表和时间戳的散列,以创建可能已更改的内部计划列表。对于这个子集,它然后执行两个计划的逐个字符串比较,以确定哪些计划实际上不同。如果两个计划之间有任何不同(无论有多小),它都会在列`出New Plan`列的SQL语句中用`“1”`标记SQL语句。这表明解冻计划将导致不同的查询计划。 - 如果冻结的计划具有与当前版本相同的InterSystems IRIS版本,并且两个计划的逐字符串比较完全匹配,则它会将列出新计划的SQL语句列中的SQL语句标记为`“0”`。这表明解冻计划不会导致不同的查询计划。 - 如果冻结的计划具有与当前版本(冻结/更新)不同的InterSystems软件版本,InterSystems IRIS将确定对SQL优化器逻辑的更改是否会导致不同的查询计划。如果是,它将用`“1”`标记“SQL Statements Listing New Plan”列中的SQL语句。否则,它会用`“0”`标记SQL语句`New Plan`列。 可以通过调用`INFORMATION.SCHEMA.STATEMENTS`来检查此扫描的结果。以下示例返回所有冻结计划的SQL语句,指示冻结的计划是否与未冻结的计划不同。请注意,解冻语句可以是`Frozen=0`或`Frozen=3`: ```sql SELECT Frozen,FrozenDifferent,Timestamp,Statement FROM INFORMATION_SCHEMA.STATEMENTS WHERE Frozen=1 OR Frozen=2 ``` ## 冻结计划出错 如果语句的计划被冻结,并且计划使用的定义发生了某些更改,从而导致计划无效,则会发生错误。例如,如果从语句`PLAN`使用的类中删除了索引: - 该声明的计划仍处于冻结状态。 - 在“SQL语句详细信息”页上,“编译设置”区域显示“计划错误”字段。例如,如果查询计划使用索引名`indxdob`,然后您修改了类定义以删除索引`indxdob`,则会显示如下消息: `Map 'indxdob' not defined in table 'Sample.Mytable', but it was specified in the frozen plan for the query`. - 在SQL语句详细资料页上,查询计划区域显示由于冻结计划中的错误而无法确定计划。 如果在冻结计划处于错误状态时重新执行查询,则InterSystems IRIS不使用冻结计划。相反,系统会创建一个新的查询计划,该计划将在给定当前定义的情况下工作,并执行查询。此查询计划被分配了与前一个查询计划相同的缓存查询类名。 在计划解冻或修改定义以使计划返回有效状态之前,出错的计划将一直处于错误状态。 如果修改定义以使计划返回有效状态,请转到SQL语句详细资料页,然后按清除错误按钮以确定是否已更正错误。如果更正,计划错误字段将消失;否则将重新显示计划错误消息。如果已更正定义,则不必显式清除计划错误,SQL即可开始使用冻结计划。如果已更正定义,则清除错误按钮会使SQL语句详细资料页的冻结查询计划区域再次显示执行计划。 计划错误可能是 `“soft error.”`。当计划使用索引,但查询优化器当前无法选择该索引时,可能会出现这种情况,因为`SetMapSelecability()`已将其可选择性设置为`0`。这样做可能是为了[重建]索引。当InterSystems IRIS遇到具有冻结计划的语句的软错误时,查询处理器会尝试自动清除错误并使用冻结计划。如果该计划仍然出错,则该计划将再次标记为出错,并且查询执行将尽可能使用最佳计划。 # %NOFPLAN关键字 可以使用`%NOFPLAN`关键字覆盖冻结的计划。包含`%NOFPLAN`关键字的SQL语句将生成新的查询计划。冻结的计划将保留,但不会使用。这允许测试生成的计划行为,而不会丢失冻结的计划。 ```sql DECLARE CURSOR FOR SELECT %NOFPLAN ... SELECT %NOFPLAN .... INSERT [OR UPDATE] %NOFPLAN ... DELETE %NOFPLAN ... UPDATE %NOFPLAN ``` 在`SELECT`语句中,`%NOFPLAN`关键字只能在查询中的第一个`SELECT`之后立即使用:它只能与`UNION`查询的第一个分支一起使用,不能在子查询中使用。`%NOFPLAN`关键字必须紧跟在`SELECT`关键字之后,位于`DISTINCT`或`TOP`等其他关键字之前。 # 导出和导入冻结计划 可以将SQL语句作为`XML`格式的文本文件导出或导入。这使可以将冻结的计划从一个位置移动到另一个位置。SQL语句导出和导入包括关联查询计划的编码版本和指示该计划是否冻结的标志。
文章
姚 鑫 · 三月 23, 2021

第十三章 使用动态SQL(一)

# 第十三章 使用动态SQL(一) # 动态SQL简介 动态SQL是指在运行时准备并执行的SQL语句。在动态SQL中,准备和执行SQL命令是单独的操作。通过动态SQL,可以以类似于ODBC或JDBC应用程序的方式在InterSystems IRIS中进行编程(除了要在与数据库引擎相同的进程上下文中执行SQL语句)。动态SQL是从ObjectScript程序调用的。 动态SQL查询是在程序执行时准备的,而不是在编译时准备的。这意味着编译器无法在编译时检查错误,并且不能在Dynamic SQL中使用预处理器宏。这也意味着执行程序可以响应用户或其他输入而创建专门的Dynamic SQL查询。 动态SQL可用于执行SQL查询。它也可以用于发出其他SQL语句。本章中的示例执行SELECT查询。 动态SQL用于执行InterSystems IRIS SQL Shell,InterSystems IRIS管理门户网站“执行查询”界面,SQL代码导入方法以及“数据导入和导出实用程序”。 在Dynamic SQL(和使用它的应用程序)中,行的最大大小为`3,641,144`个字符。 ## 动态SQL与嵌入式SQL 动态SQL与嵌入式SQL在以下方面有所不同: - **动态SQL查询的初始执行效率比嵌入式SQL稍低,因为它不会生成查询的内联代码。但是,动态SQL和嵌入式SQL的重新执行比第一次执行查询要快得多,因为它们都支持缓存的查询。** - 动态SQL可以通过两种方式接受输入到查询的文字值:使用`“?”`指定的输入参数。字符和输入主机变量(例如`:var`)。嵌入式SQL使用输入和输出主机变量(例如`:var`)。 - 使用结果集对象(即`Data`属性)的API检索动态SQL输出值。嵌入式SQL将主机变量(例如`:var`)与`SELECT`语句的`INTO`子句一起使用以输出值。 - **动态SQL设置`%SQLCODE`,`%Message`,`%ROWCOUNT`和`%ROWID`对象属性。嵌入式SQL设置相应的`SQLCODE`,`%msg`,`%ROWCOUNT`和`%ROWID`局部变量。动态SQL不会为`SELECT`查询设置`%ROWID`;嵌入式SQL为基于游标的`SELECT`查询设置`%ROWID`。** - 动态SQL提供了一种简单的方法来查找查询元数据(例如列的数量和名称)。 - 动态SQL执行SQL特权检查;必须具有适当的权限才能访问或修改表,字段等。Embedded SQL不执行SQL特权检查。 - 动态SQL无法访问私有类方法。要访问现有的类方法,必须将该方法公开。这是一般的SQL限制。但是,嵌入式SQL克服了此限制,因为嵌入式SQL操作本身是同一类的方法。 动态SQL和嵌入式SQL使用相同的数据表示形式(默认情况下为逻辑模式,但是可以更改)和NULL处理。 # `%SQL.Statement`类 动态SQL的首选接口是`%SQL.Statement`类。要准备和执行动态SQL语句,请使用`%SQL.Statement`的实例。执行动态SQL语句的结果是一个SQL语句结果对象,该对象是`%SQL.StatementResult`类的实例。 SQL语句结果对象可以是单一值,结果集或上下文对象。在所有情况下,结果对象都支持标准接口。每个结果对象都会初始化`%SQLCODE`,`%Message`和其他结果对象属性;这些属性设置的值取决于发出的SQL语句。对于成功执行的`SELECT`语句,对象是结果集(特别是`%SQL.StatementResult`的实例),并且支持预期的结果集功能。 以下ObjectScript代码准备并执行动态SQL查询: ```java /// d ##class(PHA.TEST.SQL).DynamicSQL() ClassMethod DynamicSQL() { /* 简单的%SQL.Statement示例 */ SET myquery = "SELECT TOP 5 Name,DOB FROM Sample.Person" SET tStatement = ##class(%SQL.Statement).%New() SET qStatus = tStatement.%Prepare(myquery) IF qStatus'=1 { WRITE "%Prepare 失败" DO $System.Status.DisplayError(qStatus) QUIT } SET rset = tStatement.%Execute() DO rset.%Display() WRITE !,"End of data" } ``` ```java DHC-APP>d ##class(PHA.TEST.SQL).DynamicSQL() Name DOB yaoxin 54536 xiaoli 姚鑫 63189 姚鑫 63189 姚鑫 50066 5 Rows(s) Affected End of data ``` 本章中的示例使用与`%SQL.Statement`和`%SQL.StatementResult`类关联的方法。 # 创建一个对象实例 可以使用`%New()`类方法创建`%SQL.Statement`类的实例: ` SET tStatement = ##class(%SQL.Statement).%New()` 此时,结果集对象已准备好准备SQL语句。创建`%SQL.Statement`类的实例后,可以使用该实例发出多个动态SQL查询和/或`INSERT`,`UPDATE`或`DELETE`操作。 `%New()`按以下顺序接受三个可选的逗号分隔参数: 1. `%SelectMode`,它指定用于数据输入和数据显示的模式。 2. `%SchemaPath`,它指定用于为无限定的表名提供架构名称的搜索路径。 3. `%Dialect`,它指定Transact-SQL(TSQL)Sybase或MSSQL方言。默认值为IRIS(InterSystems SQL)。 还有一个`%ObjectSelectMode`属性,不能将其设置为`%New()`参数。 `%ObjectSelectMode`指定字段到其相关对象属性的数据类型绑定。 在下面的ObjectScript示例中,`%SelectMode`为2(显示模式),`%SchemaPath`将`“Sample”`指定为默认架构: ```java SET tStatement = ##class(%SQL.Statement).%New(2,"Sample") ``` 在下面的ObjectScript示例中,未指定`%SelectMode`(请注意占位符逗号),并且`%SchemaPath`指定包含三个架构名称的架构搜索路径: ```java SET tStatement = ##class(%SQL.Statement).%New(,"MyTests,Sample,Cinema") ``` ## %SelectMode属性 `%SelectMode`属性指定以下模式之一:`0 =Logical逻辑(默认)`,`1 = ODBC`,`2 =Display.显示`。这些模式指定如何输入和显示数据值。模式最常用于日期和时间值以及显示`%List`数据(包含编码列表的字符串)。数据以逻辑模式存储。 `SELECT`查询使用`%SelectMode`值确定用于显示数据的格式。 `INSERT`或`UPDATE`操作使用`%SelectMode`值来确定允许的数据输入格式。 `%SelectMode`用于数据显示。 SQL语句在内部以逻辑模式运行。例如,无论`%SelectMode`设置如何,`ORDER BY`子句均根据记录的逻辑值对记录进行排序。 SQL函数使用逻辑值,而不管`%SelectMode`设置如何。映射为SQLPROC的方法也可以在逻辑模式下运行。在SQL语句中称为函数的SQL例程需要以逻辑格式返回函数值。 - 对于`SELECT`查询,`%SelectMode`指定用于显示数据的格式。将`%SelectMode`设置为ODBC或Display也会影响用于指定比较谓词值的数据格式。某些谓词值必须以`%SelectMode`格式指定,而其他谓词值必须以逻辑格式指定,而与`%SelectMode`无关。 - `%SelectMode = 1(ODBC)`中的时间数据类型数据可以显示小数秒,这与实际的ODBC时间不同。 InterSystems IRIS Time数据类型支持小数秒。相应的ODBC TIME数据类型(TIME_STRUCT标准标头定义)不支持小数秒。 ODBC TIME数据类型将提供的时间值截断为整秒。 ADO DotNet和JDBC没有此限制。 - `%SelectMode = 0(逻辑)`中的`%List`数据类型数据不会显示内部存储值,因为`%List`数据是使用非打印字符编码的。而是,Dynamic SQL将`%List`数据值显示为`$LISTBUILD`语句,例如:`$lb("White","Green")`。 `%SelectMode = 1(ODBC)`中的`%List`数据类型数据显示用逗号分隔的列表元素;此元素分隔符指定为`CollectionOdbcDelimiter`参数。 `%SelectMode = 2`中的`%List`数据类型数据(显示)显示由`$ CHAR(10,13)`分隔的列表元素(换行,回车);此元素分隔符指定为CollectionDisplayDelimiter参数。 - 对于`INSERT`或`UPDATE`操作,`%SelectMode`指定将转换为逻辑存储格式的输入数据的格式。为了进行此数据转换,必须使用RUNTIME(默认)的选择模式编译SQL代码,以便在执行`INSERT`或`UPDATE`时使用`Display`或`ODBC %SelectMode`。有关日期和时间的允许输入值,请参考日期和时间数据类型。 可以将`%SelectMode`指定为`%New()`类方法的第一个参数,或直接对其进行设置,如以下两个示例所示: ```java SET tStatement = ##class(%SQL.Statement).%New(2) ``` ```java SET tStatement = ##class(%SQL.Statement).%New() SET tStatement.%SelectMode=2 ``` 下面的示例返回`%SelectMode`的当前值: ```java /// d ##class(PHA.TEST.SQL).DynamicSQL1() ClassMethod DynamicSQL1() { SET tStatement = ##class(%SQL.Statement).%New() WRITE !,"默认选择模式=",tStatement.%SelectMode SET tStatement.%SelectMode=2 WRITE !,"设置选择模式=",tStatement.%SelectMode } ``` ```java DHC-APP>d ##class(PHA.TEST.SQL).DynamicSQL1() 默认选择模式=0 设置选择模式=2 ``` 可以使用`$SYSTEM.SQL.Util.GetOption("SelectMode")` 方法为当前进程确定`SelectMode`默认设置。当`n`可以为`0 =逻辑`,`1 = ODBC`或`2 = Display`时,可以使用`$SYSTEM.SQL.Util.SetOption("SelectMode",n)` 方法来更改当前进程的`SelectMode`默认设置。设置`%SelectMode`会覆盖当前对象实例的默认设置。它不会更改`SelectMode`进程的默认值。 ## %SchemaPath属性 `%SchemaPath`属性指定用于为非限定的表名,视图名或存储过程名提供架构名的搜索路径。模式搜索路径用于数据管理操作,例如`SELECT`,`CALL`,`INSERT`和`TRUNCATE TABLE`;数据定义操作(例如`DROP TABLE`)将忽略它。 搜索路径被指定为带引号的字符串,其中包含模式名称或逗号分隔的一系列模式名称。 InterSystems IRIS以从左到右的顺序搜索列出的模式。 InterSystems IRIS会搜索每个指定的架构,直到找到第一个匹配的表,视图或存储过程名称。因为模式是按指定顺序搜索的,所以不会检测到歧义的表名。仅搜索当前名称空间中的架构名称。 模式搜索路径可以包含文字模式名称以及`CURRENT_PATH`,`CURRENT_SCHEMA`和`DEFAULT_SCHEMA`关键字。 - `CURRENT_PATH`指定当前模式搜索路径,如先前的`%SchemaPath`属性中所定义。这通常用于将架构添加到现有架构搜索路径的开头或结尾。 - 如果`%SQL.Statement`调用是从类方法中进行的,则`CURRENT_SCHEMA`指定当前模式容器的类名称。如果在类方法中定义了`#SQLCompile Path`宏指令,则`CURRENT_SCHEMA`是映射到当前类包的架构。否则,`CURRENT_SCHEMA`与`DEFAULT_SCHEMA`相同。 - `DEFAULT_SCHEMA`指定系统范围的默认架构。使用此关键字,可以在搜索其他列出的架构之前,在架构搜索路径中将系统范围的默认架构作为一个项目进行搜索。如果已经搜索了路径中指定的所有模式而没有匹配项,则在搜索模式搜索路径后始终会搜索系统范围内的默认模式。 `%SchemaPath`是InterSystems IRIS在架构中搜索匹配表名的第一位。如果未指定`%SchemaPath`,或者未列出包含匹配表名的架构,则InterSystems IRIS将使用系统范围的默认架构。 可以通过指定`%SchemaPath`属性或指定`%New()`类方法的第二个参数来指定模式搜索路径,如以下两个示例所示: ```java SET path="MyTests,Sample,Cinema" SET tStatement = ##class(%SQL.Statement).%New(,path) ``` ```java SET tStatement = ##class(%SQL.Statement).%New() SET tStatement.%SchemaPath="MyTests,Sample,Cinema" ``` 可以在使用它的`%Prepare()`方法之前的任何位置设置`%SchemaPath`。 下面的示例返回`%SchemaPath`的当前值: ```java /// d ##class(PHA.TEST.SQL).DynamicSQL2() ClassMethod DynamicSQL2() { SET tStatement = ##class(%SQL.Statement).%New() WRITE !,"默认 path=",tStatement.%SchemaPath SET tStatement.%SchemaPath="MyTests,Sample,Cinema" WRITE !,"设置 path=",tStatement.%SchemaPath } ``` ```java DHC-APP>d ##class(PHA.TEST.SQL).DynamicSQL2() 默认 path= 设置 path=MyTests,Sample,Cinema ``` 可以使用`%ClassPath()`方法将`%SchemaPath`设置为为指定的类名定义的搜索路径: ```java /// d ##class(PHA.TEST.SQL).DynamicSQL3() ClassMethod DynamicSQL3() { SET tStatement = ##class(%SQL.Statement).%New() SET tStatement.%SchemaPath=tStatement.%ClassPath("Sample.Person") WRITE tStatement.%SchemaPath } ``` ```java DHC-APP>d ##class(PHA.TEST.SQL).DynamicSQL3() Sample ``` ## %Dialect属性 `%Dialect`属性指定SQL语句方言。可以指定Sybase,MSSQL或IRIS(InterSystems SQL)。 Sybase或MSSQL设置导致使用指定的Transact-SQL方言处理SQL语句。 Sybase和MSSQL方言在这些方言中支持SQL语句的有限子集。它们支持`SELECT`,`INSERT`,`UPDATE`,`DELETE`和`EXECUTE`语句。他们支持`CREATE TABLE`语句用于永久表,但不支持临时表。支持创建视图。支持`CREATE TRIGGER`和`DROP TRIGGER`。但是,如果`CREATE TRIGGER`语句部分成功,但是在类编译时失败,则此实现不支持事务回滚。支持`CREATE PROCEDURE`和`CREATE FUNCTION`。 Sybase和MSSQL方言支持IF控制流语句。 IRIS(InterSystems SQL)方言不支持此命令。 默认值为InterSystems SQL,由空字符串(`“”`)表示,或指定为“ IRIS” 可以将`%Dialect`指定为`%New()`类方法的第三个参数,或者将其直接设置为属性,或者使用方法进行设置,如以下三个示例所示: 在`%New()`类方法中设置`%Dialect`: ```java /// d ##class(PHA.TEST.SQL).DynamicSQL4() ClassMethod DynamicSQL4() { SET tStatement = ##class(%SQL.Statement).%New(,,"Sybase") WRITE "语言模式设置为=",tStatement.%Dialect } ``` ```java DHC-APP>d ##class(PHA.TEST.SQL).DynamicSQL4() 语言模式设置为=Sybase ``` 直接设置`%Dialect`属性: ```java /// d ##class(PHA.TEST.SQL).DynamicSQL5() ClassMethod DynamicSQL5() { SET tStatement = ##class(%SQL.Statement).%New() SET defaultdialect=tStatement.%Dialect WRITE "默认语言模式=",defaultdialect,! SET tStatement.%Dialect="Sybase" WRITE "语言模式设置为=",tStatement.%Dialect,! SET tStatement.%Dialect="IRIS" WRITE "语言模式重置为默认=",tStatement.%Dialect,! } ``` ```java DHC-APP>d ##class(PHA.TEST.SQL).DynamicSQL5() 默认语言模式= 语言模式设置为=Sybase 语言模式重置为默认=iris ``` 使用`%DialectSet()`实例方法设置`%Dialect`属性,该方法将返回错误状态: ```java /// d ##class(PHA.TEST.SQL).DynamicSQL6() ClassMethod DynamicSQL6() { SET tStatement = ##class(%SQL.Statement).%New() SET tStatus = tStatement.%DialectSet("Sybase") IF tStatus'=1 { WRITE "%DialectSet 失败:" DO $System.Status.DisplayError(tStatus) QUIT } WRITE "语言模式设置为=",tStatement.%Dialect } ``` ```java DHC-APP>d ##class(PHA.TEST.SQL).DynamicSQL6() 语言模式设置为=Sybase ``` `%DialectSet()`方法返回`%Status`值:成功返回状态1。失败返回以0开头的对象表达式,后跟编码错误信息。因此,无法执行`tStatus = 0`测试是否失败;您可以执行`$$ISOK(tStatus)= 0`宏测试以检查失败 ## %ObjectSelectMode属性 `%ObjectSelectMode`属性是一个布尔值。如果`%ObjectSelectMode = 0(默认)`,则`SELECT`列表中的所有列都将绑定到结果集中具有文字类型的属性。如果`%ObjectSelectMode = 1`,则`SELECT`列表中的列将绑定到具有关联属性定义中定义的类型的属性。 `%ObjectSelectMode`允许指定如何在从`SELECT`语句生成的结果集类中定义类型类为swizzleable类的列。如果`%ObjectSelectMode = 0`,则将在结果集中将与swizzleable列相对应的属性定义为与SQL表的RowID类型相对应的简单文字类型。如果`%ObjectSelectMode = 1`,则将使用列的声明类型定义属性。这意味着访问结果集属性将触发 swizzling。 无法将`%ObjectSelectMode`设置为`%New()`的参数。 下面的示例返回`%ObjectSelectMode`默认值,设置`%ObjectSelectMode`,然后返回新的`%ObjectSelectMode`值: ```java /// d ##class(PHA.TEST.SQL).DynamicSQL7() ClassMethod DynamicSQL7() { SET myquery = "SELECT TOP 5 %ID AS MyID,Name,Age FROM Sample.Person" SET tStatement = ##class(%SQL.Statement).%New() WRITE !,"默认 ObjectSelectMode=",tStatement.%ObjectSelectMode SET tStatement.%ObjectSelectMode=1 WRITE !,"语言 ObjectSelectMode=",tStatement.%ObjectSelectMode } ``` ```java DHC-APP>d ##class(PHA.TEST.SQL).DynamicSQL7() 默认 ObjectSelectMode=0 语言 ObjectSelectMode=1 ``` 当使用字段名称属性从结果集中返回值时,主要使用`%ObjectSelectMode = 1`。本章“从结果集中返回特定值”部分的字段名属性中的示例对此进行了进一步说明。 当`SELECT`列表中的字段链接到集合属性时,可以使用`%ObjectSelectMode = 1`。 `%ObjectSelectMode`将使集合swizzle。如果`%SelectMode = 1或2`,则系统在转换前将收集序列值转换为逻辑模式形式。生成的oref支持完整的收集接口。
文章
Claire Zheng · 二月 1, 2021

如何发帖以及其他常见问题解答

Hi, 大家好! 我们正在努力改进本网站,让大家可以在 InterSystems 开发者社区舒适地阅读、贡献、分享和获取答案! 虽然有一些 UI 问题还没有得到修复,但本帖提供了一些关于如何使用开发者社区的简单回答。 如何添加帖子? 打开社区页面, 选择所需产品,例如 Caché 然后点击 "创建新帖"。 如何订阅帖子的更新? 要订阅帖子的更新并通过电子邮件获取它们,请点击帖子摘要下方的“收藏”,例如: 如何管理帖子的标题? 假设您已经创建文章,并且想要在其注释中添加几句话。 为此,将编辑器切换到“筛选的 HTML”模式,然后在注释末尾输入<!--break--> 标签。 否则注释会被修剪为一两句话。 就像这样: 未完待续。 敬请期待!
问题
Johnny Wang · 二月 24, 2022

问题转发

请教各位老师: Cache数据日志怎么读取? 如果是想写代码去读取,应该怎么操作?如果是不知道数据日志在哪,应该在哪可以获取? 不知道你问题里的日志是不是指的journal文件。 没有直接读取journal的方法,只有类似MirrorDejournal的方法对写入异步镜像成员的journal进行操作, 比如将内容写入到你自己的一个数据global中。 在写journal的同时将journal中记录的内容存放在另一个地方。 具体做法可以参考社区里的另一篇文章:CDC系列之一 :使用Dejournal Filter在InterSystems IRIS/Caché上通过Mirroring实现CDC功能 对于较早版本还没有镜像Mirror的配置,则可以使用Shadow服务器的Dejournaling filter routine。 可以参考:CDC系列之二 :使用Dejournaling filter routine在Caché上通过Shadow实现CDC
文章
Michael Lei · 十一月 9, 2021

翻译文章--通过ODBC用Appeon PowerBuilder连接IRIS

https://www.appeon.com/products/powerbuilder Appeon PowerBuilder 是一个企业级开发工具,可以用来建立数据驱动的商业应用程序和组件。它是Appeon产品套件之一,同时提供了开发C/S、Web、移动和分布式应用程序的工具。 在这篇文章中,我将展示通过使用ODBC用Appeon PowerBuilder连接Caché的步骤。 步骤1 :确保在安装IRIS时选择ODBC驱动程序选项。 步骤2:通过使用ODBC数据源管理器配置ODBC IRIS数据源 步骤 3: 配置InterSystems ODBC 数据源 步骤 4: 测试连接 (确保 IRIS 实例在运行) 步骤 5: 从 PowerBuilder 打开数据库Profiles, 在列表选中ODB ODBC并单击“新建 New”... 按钮 步骤 6: 选择我们已经用ODBC管理器创建的 "IRISHealth User"数据源 步骤 7: 点击“测试连接Test Connection” 按钮,在Preview页面下测试连接 恭喜! 我们已经成功建立了IRIS链接。现在我们可以用PowerBuilder database painter来看表和数据了 谢谢
文章
Michael Lei · 六月 1, 2022

部分IRIS 2022 年度编程大奖赛作品展示——FHIR 病人查看器

![Alt Text](https://media.giphy.com/media/UXO1VWyK7ZeD72NwVg/giphy.gif) 大家好! 在这里跟大家分享一下我在大奖赛上的项目 :) FHIR病人查看器是一个建立在Vue.js上的单页、反应式渲染工具,它以对人友好的方式显示从对InterSystems FHIR服务器的/Patient/{id}/$everything调用返回的数据。在自述文件中,包括3个主要内容: 1. 一个视频演示,将FHIR患者浏览器连接到一个沙盒IRIS FHIR服务器上(这是测试它的最快方法); 2.第二个视频显示我如何在生产环境中使用FHIR患者浏览器(使用一个定制的后端来处理API调用,在我的例子中用PHP/Laravel编写,但可以转移到其他语言/框架); 3.修改组件的说明,创建你自己版本的工具,并建立你自己的dist文件。 谢谢大家! 本次大赛的参赛作品质量很好! Dan
问题
Luo Haimianbaobao · 四月 13, 2023

Production中的java网关服务EnsLib.JavaGateway.Service会经常连接超时,导致适配器EnsLib.SQL.InboundAdapter使用jdbc连接数据库的BS报错

问题如标题。尝试过改变java网关端口,还是会经常出现报错,错误如下图: 这个java Gateway 报错的引起的原因可能很多,如果是生产环境,建议开一个WRC工单,如果是开发测试环境可以InterSystems 的se 可以将Java Gateway Service的日志打开,设置方法是在Production管理页面选中该组件上,在设置中设置日志文件(包括路径和文件名称)。如果问题再次出现,我们可以对日志文件进行分析,开启之后请注意该文件的大小增长。 另外,linux的Dynamic TCP port范围是32768~60999,可通过下面的命令进行查询,例如(在RedHat7.9下), sysctl net.ipv4.ip_local_port_range net.ipv4.ip_local_port_range = 32768 60999 在这个范围内的tcp端口号可能会被系统动态分配给其他进程使用,所以建议咱们更改一个不在此范围内的端口号。
文章
Meng Cao · 十一月 23, 2023

使用支持SSL的ODBC连接IRIS数据库

前言 随着网络安全日益被重视,特别是等级保护制度的大环境下,SSL加密传输越来越被重视,本文介绍如何使用支持SSL的ODBC连接IRIS数据库。 数据库版本:IRISHealth-2023.1 1. 服务器端配置 1)新建SSL服务器配置。 2)开启超级端口的SSL支持,这里我们选择启用即可,如所有超级端口的连接都支持SSL可选要求。 2.Windows客户端配置 1)创建 SSLDefs.ini 配置文件,并编辑内容: [TLS to an InterSystems IRIS instance] Address=127.0.0.1 Port=51773 SSLConfig=DHCC [DHCC] TLSMinVersion=8 TLSMaxVersion=16 CipherList=ALL:!aNULL:!eNULL:!EXP:!SSLv2 KeyType=2 VerifyPeer=1 Password= CertFile=E:\ADSSL\ADSSL.crt KeyFile=E:\ADSSL\ADSSL.key CAfile=E:\ADSSL\ADSSL.crt 2)设置系统环境变量 ISC_SSLconfigurations ,指向 SSLDefs.ini 配置文件。 3.创建ODBC源进行测试。 很棒哦,加油加油加油! 学到了,大佬棒棒 学到了 学到了 学到了,赞👍 👍👍👍
文章
Louis Lu · 十一月 22, 2024

设置Windows IIS 用于显示 HTTP 返回的错误详细信息

当我们将 InterSystems IRIS 安装在Windows 系列操作系统中时,往往同时使用IIS 作为其Web 服务器。 但这时候我们却发现,由RESTful返回的错误信息却不能正常显示出来了,特别是在调试程序的时候,非常不方便。 比如在测试 FHIR Post/Put 请求时,我们的请求消息体中包含不正确的内容,这时我可以看到返回的是HTTP 400 Bad Request的返回内容. 我无法具体知道请求消息体哪句出错了,这对我调试程序造成很大困扰。 解决方法: 1. 打开IIS的管理页面,双击 错误页 2. 选择右侧 编辑功能设置 3. 选择错误响应下的 详细错误 选项。 我们再次请求,此时可以看到页面上显示了详细的错误信息 相关详细信息可以查看文档:Configuring IIS to Return SOAP Fault Details 以及 HTTP Errors
文章
Claire Zheng · 五月 21, 2023

【视频文字版】对话:“数据二十条”与FHIR标准

视频文字版。点击查看视频。 CHIMA主任委员:王才有 老卢,你好。疫情三年我们没见,中国发生了很大的变化,你回来会感觉到。特别是在信息化和数字化方面,确实中国的这三年可以说是政策和制度设计上都有了很大的一些调整和进步,特别是去年政府发布了关于数据基本制度的设计方案,我们管它叫“数据二十条”。 这个制度呢,实际上是避开了数据的所有权的问题,如果说我们在数据的所有权和使用权上长期去争论的话,它的价值就很难发挥。所以说中国这次首次提出了一个“三权”,数据“三权分立”的新的战略设计,不再强调数据是谁的,我们强调数据的控制权——就是数据现在在谁手里;数据的开发权——他这些数据可以用来干什么;数据的受益权——他把这数据再分享给别人,再创造二次价值,或者再创造三次价值,这样数据的资源就得到充分的利用。 所以说一方面要对这种数据基本制度的建立,为今后数据资源市场化是开了一道新的大门。中国是一个数据资源的大国,那这些资源怎么利用好,怎么用在生产,怎么用在服务,怎么用在改善我们医院的管理,给我们患者服务,给这个居民服务,这项我想是一个很大的一个制度上的创新。 当然这个制度的创新也给我们提出了很多新的要求:数据安全的要求,个人信息保护的要求,数据标准的要求…… 我国基础制度的形成,将促进数据合规高效流通使用。今后,医疗健康数据将在更大空间交换和共享,这就需要新一代标准体系了,例如FHIR。 我想这方面你也许知道了,在这方面有什么体会呢?咱们可以做做交流。 InterSystems 亚太区总经理卢侠亮(Luciano Brustia): 好的,谢谢。 您所说的这些让我感到很兴奋,谢谢您的发言。因为我同意,当我们在谈论标准、谈论专业术语的时候,每个人都会立即想到FHIR标准。在这方面,InterSystems在全球绝对是领先的。 你可能知道,在过去的这些年里,我们做了许多工作,我们的IRIS数据平台,在全球范围内得到了大范围部署,同时,我们在中国持续地进行本地化创新,构建了中国版的互联互通平台(内嵌FHIR资源仓库),我们称之为“互联互通套件”,用来实现基于FHIR标准的互联互通 。 当谈到专业术语(统一语义)是我们的目标时,FHIR绝对可以作为一个最佳标准选择,我们已经帮助150多家医院通过了国内互联互通标准化成熟度等级评测,其中有近30家医院通过了最高级别的认证(五级乙等),值此(“数据二十条”颁布的)重要时机,我们肯定还会继续加大投入,在这些方面(打通互联互通和FHIR两大生态)开展更多活动。我们现在已经发布了互联互通套件的第三版,目前正在计划进行更多升级。 CHIMA主任委员王才有: 卢总,您刚才讲的系联在中国的一些做法,我很认可。因为系联公司(InterSystems)在中国已经多年,特别是在推进互联互通,推进信息标准的应用方面发挥了很重要的作用。 对这个FHIR来讲,它是针对的移动互联网出现之后,这信息在更大的范围里面交换共享和随时的调用的时候,随机调用的时候,它只有利用这个标准,它才可能实现信息的动态的、语义互操作的这种交换。 而HL7 2.X它面对的是语法层面的交换,语义层面的这个能力呢,它是比较弱的。所以说如果要做得更好,信息在互联网和移动互联网时代,特别是数字,我们说的数字时代,你在更大的空间里面交换和共享信息的时候,同时保持信息理解上的一致性,那我们只有选用FHIR才可能实现得会更好一些。这一方面是技术上的进步,一方面是应用上的需求。 那当然这种技术上的提供和应用上的需求是必须要依赖于工具,依赖于产品。那系联公司这方面的平台支撑和工具支撑上,我想对于促进FHIR在中国的应用还是发挥了很好的作用的。 系联过去确实做得不错,但是我们看到了FHIR的应用还不是特别地普及,原因是多方面的,可能也有一些新的制约和一些新的挑战。我想系联公司在这方面也会进一步地做出努力,推进FHIR在中国的应用。 这方面,卢总下一步你有什么打算呢? InterSystems 亚太区总经理卢侠亮(Luciano Brustia): 是的,当然有。我们已经将FHIR作为我们所有开发部署的核心,包括我们所有医疗平台。首先,我很高兴在今年CHIMA大会上(HL7中国)将发布《FHIR白皮书》 ,明确界定HL7、CDA和FHIR之间的区别。因为医院采用CDA标准,他们拥有一个庞大的临床数据中心,但我们还需要一个额外的步骤来实现FHIR。 为了让大家更容易理解,我经常举这样一个例子:我总是把FHIR的重要性比作普通话的重要性,因为普通话可以作为人们互相交流的一种共同语言。我也总是喜欢这样说,我看到了一张图片,上面是一匹带着黑色条纹的白马,大家都明白它是什么。你也可以说,你看到了一张图片,上面是一匹带着白色条纹的黑马,大家也都明白它是什么。FHIR不会告诉你这是一匹白马还是一匹黑马,而是会说这是一匹“斑马”——只用一个词,就确切指出了图片内容的唯一标识,以及我们在谈论的是什么。这是深层次的主要区别。 我很高兴《FHIR白皮书》即将在CHIMA上发布,这将有助于理解这一点。InterSystems作为FHIR标准在全球范围的推广者,已经在美国和亚太地区拥有众多成功案例,并且帮助越来越多的国家部署并遵循这种标准,为当地居民提供更多价值,我们很高兴能在中国做同样的事情。 CHIMA主任委员王才有: 刚才没想到您作为一个总裁,对技术细节了解得这么清楚。确实我们要把技术细节搞清楚,把关键的概念搞清楚,这样才能使我们的行动走到正确的轨道上来。对FHIR,它到底是适用于什么场景,什么场景下应该用哪些标准解决什么问题,这我觉得是一个非常重要的一个考虑。任何一个企业、任何一个用户都应该考虑你选用标准的适宜性,我们不能说哪个标准好,哪个标准不好。所以说我们CHIMA,刚才老卢也提到了,我们要在下一次CHIMA大会上发一个白皮书,而这个白皮书实际上就是我们对这些标准的基本概念,它的用途,在什么场景下应用,我们要做一个比较清晰的这种引导,让大家在选择标准和使用标准上,使标准能真正解决自己互联互通上的问题。 那我们CHIMA跟系联一样,也是在推进标准的应用和标准的采纳,实现我们互联互通的目标。前年,我们也组织了专家,在中国的医院编了一个中国医院里边的关于FHIR的应用的一些案例的分享,我们是请的北京友谊医院的专家来共同承担这个课题,也非常感谢系联的专家对这个项目给予了很好的支持。 卢总,我们系联今后在这个信息互联互通和促进,我们叫数字时代的健康场景下,我们公司还有什么好的想法和建议? InterSystems 亚太区总经理卢侠亮(Luciano Brustia):谢谢。我认为此时来到中国,这是一个非常令人兴奋的时机,因为我们能够带来许多在世界各地获得的经验。我们在日本群马大学建立了日本首个FHIR数据库;我们正在与印度尼西亚的一家超大型医疗集团合作,该医疗集团拥有40多家医院,(借助InterSystems技术)采用FHIR标准,将他们的数据汇聚起来,并在此基础上进行分析。毫无疑问,InterSystems一直都在采用、推广FHIR标准,在FHIR成为互操作性标准之前就是如此,而且我们将带来更多的创新,以确保中国始终与国际最前沿的标准接轨,因为最终真正重要的是,我们这样做是为了确保所有中国居民的利益,而且我认为这对像你我这样从事IT行业,特别是从事医疗IT领域的从业者来说,才是最重要的。我们不仅仅是在做生意,更多的是在提供价值。在人口不断增长的情况下助力全民健康水平提升,中国居民的寿命越来越长,这是一件非常好的事情。但也带来了很多问题,特别是人口老龄化的问题,建设高质量的数据库,采用先进的标准,可以有效地预防更多的慢性疾病发生,我认为这是非常有价值的,也让我们所做的事情更有意义,以上是我的看法,非常感谢。CHIMA主任委员王才有:非常高兴看您为中国医疗信息化做出的贡献。系联公司把国际上的一些标准引用到中国,我们也看到中国自身医疗信息化发展也是非常地快,特别是中国具有一个独特的优势——就是数据资源丰富、应用场景非常之多,所以中国的经验呢,我想也在逐渐地积累和形成。所以说我认为系联公司将来的更重要的任务,把中国的经验引向世界,为全球的人民的健康共同做出贡献。InterSystems 亚太区总经理卢侠亮(Luciano Brustia):是的,当然。我的意思是,就像我一直在说的,我很荣幸来到中国,这已经是我在中国的第15个年头了,而系联来到中国已经不止25年了,我们打算再呆上另一个20年、25年……如果我还能再活二十年,(我会)继续留在这里,继续为各位和所有聪明睿智的中国居民服务。毫无疑问,InterSystems一直致力于把我们的先进技术带到中国,助力中国本土企业做大做强,当然,我们也会将在中国获得的经验,作为一种资源共享给世界其他地方。所以我真的很高兴再次回到中国,我认为这是最好的时候,非常感谢大家!
文章
姚 鑫 · 五月 4, 2021

第二章 全局变量结构(二)

# 第二章 全局变量结构(二) # 全局变量物理结构 全局变量使用高度优化的结构存储在物理文件中。管理此数据结构的代码也针对运行InterSystems IRIS的每个平台进行了高度优化。这些优化确保全局操作具有高吞吐量(每单位时间的操作数)、高并发性(并发用户总数)、缓存的高效使用,并且不需要与性能相关的持续维护(例如频繁的重建、重新索引或压缩)。 用于存储全局变量的物理结构是完全封装的;应用程序不会以任何方式担心物理数据结构。 全局变量存储在磁盘上的一系列数据块中;每个块的大小(通常为`8KB`)是在创建物理数据库时确定的。为了提供对数据的高效访问,InterSystems IRIS维护了一种复杂的**B树状结构**,该结构使用一组指针块将相关数据块链接在一起。InterSystems IRIS维护一个缓冲池-经常引用的块的内存缓存-以降低从磁盘获取块的成本。 虽然许多数据库技术使用类似`B树`的结构来存储数据,但InterSystems IRIS在许多方面都是独一无二的: - 存储机构通过安全、易于使用的接口显露出来。 - 压缩下标和数据以节省磁盘空间和宝贵的内存缓存空间。 - 存储引擎针对事务处理操作进行了优化:插入、更新和删除都很快。与关系系统不同,InterSystems IRIS从不需要重建索引或数据来恢复性能。 - 存储引擎针对最大并发访问进行了优化。 - 数据会自动群集,以实现高效检索。 # 引用全局变量 全局变量驻留在特定的InterSystems IRIS数据库中。如果使用适当的映射,全局变量的部分可以驻留在不同的数据库中。数据库可以在物理上位于当前系统上,也可以位于通过ECP网络访问的远程系统上。术语数据集是指包含InterSystems IRIS数据库的系统和目录。 命名空间是共同构成一组相关信息的数据集和全局映射的逻辑定义。 简单的全局变量引用适用于当前选定的命名空间。名称空间定义可能导致它物理访问本地系统或远程系统上的数据库。不同的全局变量可以映射到不同的位置或数据集(其中数据集是指包含InterSystems IRIS数据库的系统和目录)。 例如,要在当前已映射到的命名空间中创建对全局顺序的简单引用,请使用以下语法: ```java ^ORDER ``` ## 设置全局变量映射 可以将全局变量和例程从一个数据库映射到相同或不同系统上的另一个数据库。这允许简单地引用可以存在于任何地方的数据,这是命名空间的主要特征。可以映射整个全局或部分全局;映射全局(或下标)的一部分称为下标级别映射(`SLM`)。因为可以映射全局下标,所以数据可以轻松地跨磁盘。 全局映射是分层应用的。例如,如果NSX命名空间有一个关联的`DBX`数据库,但将`^x`全局变量映射到`DBY`数据库,将`^x(1)`映射到`DBZ`数据库,则`^x`全局变量的任何下标形式(属于`^x(1)`层次结构的那些除外)都映射到`DBY`;属于`^x(1)`层次结构的那些全局变量映射到DBZ。下图说明了此层次结构: ![image](/sites/default/files/inline/images/1_43.png) 在此图中,全局变量及其层次结构显示为灰色,它们映射到的数据库显示为黑色。 还可以将映射的、下标的全局的一部分映射到另一个数据库,甚至映射回初始全局映射到的数据库。假设前面的示例有`^x(1,2)`全局变量返回到`DBY`数据库的附加映射。这将如下所示: ![image](/sites/default/files/inline/images/2_25.png) 同样,全局变量及其层次结构显示为灰色,它们映射到的数据库显示为黑色。 一旦将全局从一个命名空间映射到另一个命名空间,就可以引用映射的全局变量,就像它在当前命名空间中一样-只需一个简单的引用,如`^Order`或`^X(1)`。 重要提示:建立下标级别映射范围时,字符串下标的行为与整数下标的行为不同。对于字符串,第一个字符确定范围,而对于整数,范围使用数值。例如,下标范围`("A"):("C")` 不仅包含`AA`,还包含`AC`和`ABCDEF`;相比之下,下标范围`(1):(2)` 不包含`11`。 ### 使用全局和下标的不同范围 命名空间的每个映射必须引用不同范围的全局变量或下标。映射验证可防止建立任何类型的重叠。例如,如果使用管理门户创建与现有映射重叠的新映射,则门户会阻止这种情况发生,并显示一条错误消息。 ### 记录更改 通过门户对映射的成功更改也会记录在`messages.log`中;不成功的更改不会记录。通过手动编辑配置参数(CPF)文件来建立映射的任何失败尝试都会记录在`messages.log`中. ## 扩展的全局变量引用 可以引用位于当前命名空间以外的命名空间中的全局变量。这称为扩展全局变量引用或简称为扩展引用。 有两种形式的扩展引用: - 显式命名空间引用-将全局所在命名空间的名称指定为全局变量引用语法的一部分。 - 隐含名称空间引用-指定目录和系统名称(可选)作为全局变量引用语法的一部分。在这种情况下,不适用全局变量映射,因为物理数据集(目录和系统)是作为全局变量引用的一部分提供的。 最好使用显式名称空间,因为这允许在需求更改时在外部重新定义逻辑映射,而无需更改应用程序代码。 InterSystems IRIS支持两种形式的扩展引用: - 方括号语法,它用方括号(`[]`)将扩展引用括起来。 - 环境语法,用竖线(`||`)括起扩展引用。 注意:扩展全局引用的示例使用`Windows`目录结构。实际上,此类引用的形式取决于操作系统。 ### 方括号语法 可以使用方括号语法来指定具有显式命名空间或隐含命名空间的扩展全局引用: 显式命名空间: ```java ^[nspace]glob ``` 隐含命名空间: ```java ^[dir,sys]glob ``` 在显式名称空间引用中,`nspace`是全局全局当前尚未映射或复制到的已定义名称空间。在隐含的名称空间引用中,`dir`是目录(其名称包括尾随反斜杠:`“\”`),`sys`是`SYSTEM`,`glob`是该目录中的全局目录。如果将`nspace`或`dir`指定为(`“^”`),则引用的是进程私有全局变量。 除非将目录和系统名称或命名空间名称指定为变量,否则必须在目录和系统名称或命名空间名称两边加上引号。目录和系统一起构成一个隐含的命名空间。隐含的命名空间可以引用以下任一项: - 指定系统上的指定目录。 - 本地系统上的指定目录(如果未在引用中指定系统名称)。如果在隐含的命名空间引用中省略了系统名称,则必须在目录引用内提供双脱字符(`^^`)以指示省略的系统名称。 要在远程系统上指定隐式命名空间,请执行以下操作: ```java ["dir","sys"] ``` 在本地系统上指定一个隐含的命名空间: ```java ["^^dir"] ``` 例如,要访问名为SALES的计算机上的`C:\BUSINESS\`目录中的全局变量`ORDER`: ```java SET x = ^["C:\BUSINESS\","SALES"]ORDER ``` 要访问本地计算机上的`C:\BUSINESS\`目录中的全局`ORDER`: ```java SET x = ^["^^C:\BUSINESS\"]ORDER ``` 要访问定义的命名空间`MARKETING`中的全局`ORDER`: ```java SET x = ^["MARKETING"]ORDER ``` 要访问进程私有的全局`ORDER`: ```java SET x = ^["^"]ORDER ``` 注意:在创建涉及镜像数据库的隐含命名空间扩展引用时,可以使用镜像数据库路径,格式为`:mirror:mirror_name:mirror_DB_name`。 例如,当在镜像`CORPMIR`中引用镜像数据库名称为mirdb1的数据库时,可以形成如下的隐含引用: ```java ["^^:mirror:CORPMIR:mirdb1"] ``` 镜像数据库路径既可以用于本地数据库,也可以用于远程数据库。 ### 环境语法 环境语法被定义为: ```java ^|"env"|global ``` `"env"`可以有以下五种格式之一: - 空字符串(`""`)-本地系统上的当前命名空间。 - `"namespace"` -定义的命名空间,当前没有全局映射到。 命名空间名称不区分大小写。 如果`namespace`具有特殊值`"^"`,则它是进程私有的全局变量。 - `"^^dir"` -一个隐含的命名空间,它的默认目录是本地系统上的指定目录,其中dir包含一个末尾的反斜杠(`" \ ")`。 - `"^system^dir"`——一个隐含的命名空间,默认目录是指定的远程系统上的指定目录,其中`dir`包含一个结尾的反斜杠(`" \ "`)。 - 省略-如果根本没有`"env"`,它是进程私有的全局变量。 要访问当前系统上当前命名空间中的全局`ORDER`,如果没有为`ORDER`定义映射,请使用以下语法: ```java SET x = ^|""|ORDER ``` 这与简单的全局变量引用相同: ```java SET x = ^ORDER ``` 要访问映射到定义的命名空间`MARKETING`的全局`ORDER`: ```java SET x = ^|"MARKETING"|ORDER ``` 可以使用一个隐含的命名空间来访问本地系统上`C:\BUSINESS\`目录下的全局`ORDER`: ```java SET x = ^|"^^C:\BUSINESS\"|ORDER ``` 可以使用一个隐含的命名空间来访问一个名为`SALES`的远程系统上的目录`C:\BUSINESS`中的全局`ORDER`: ```java SET x = ^|"^SALES^C:\BUSINESS\"|ORDER ``` 要访问进程私有的全局`ORDER`: ```java SET x = ^||ORDER SET x=^|"^"|ORDER ```
文章
姚 鑫 · 八月 27, 2021

Storage关键字SqlRowIdProperty,SqlTableNumber,State,StreamLocation,Type

# 第153章 Storage关键字 - SqlRowIdProperty 指定`SQL RowId`属性。 # 大纲 ```java prop ``` # 值 该元素的值是一个`SQL`标识符。 # 描述 此元素仅由从早期InterSystems产品迁移的类使用。 # 默认值 ``元素的默认值为空字符串。 # 第154章 Storage关键字 - SqlTableNumber 指定内部`SQL`表号。 # 大纲 ```java 123 ``` # 值 该元素的值是一个表号。 # 描述 此元素仅由从早期InterSystems产品迁移的类使用。 # 默认值 ``元素的默认值为空字符串。 # 第155章 Storage关键字 - State 指定用于串行对象的数据定义。 # 大纲 ```java state ``` # 值 此元素的值是此存储定义中的数据定义的名称。 # 描述 对于串行(嵌入式)类,此关键字指示使用哪个数据定义来定义对象的序列化状态(序列化时对象属性的排列方式)。这也是默认数据定义,默认结构生成器将向其添加未存储的属性。 # 默认值 ``元素的默认值为空字符串。 # 第156章 Storage关键字 - StreamLocation 指定流属性的默认存储位置。 # 大纲 ```java ^Sample.PersonS ``` # 值 此元素的值是带有可选前导下标的全局名称。 # 描述 此元素允许指定用于在持久化类中存储任何流属性的默认全局设置。存储在此全局的根位置的值是一个计数器,每当存储此类的流值时,该计数器就会递增。 请注意,还可以单独指定每个流属性的存储。 # 默认值 如果未指定,则类编译器将生成``元素的值。通常,该值是`^MyApp.MyClassS`(其中`MyApp.MyClass`是类名),但是,它可能会根据许多因素而有所不同。 # 第157章 Storage关键字 - Type 用于提供持久性的存储类。 # 大纲 ```java %Storage.Persistent ``` # 值 该元素的值是一个类名。 # 描述 此元素指定为此类提供持久性的存储类。 `%Storage.Persistent`类是默认存储类,并提供默认存储结构。 `%Storage.SQL`类用于将类映射到旧数据结构。 对于串行(嵌入式)类,必须将其设置为`%Storage.Serial`(由新建类向导自动设置)。 # 默认值 ``元素的默认值为`%Storage.Persistent`。
文章
姚 鑫 · 八月 2, 2021

索引关键字PrimaryKey,ShardKey,SqlName,Type

# 第五十三章 索引关键字 - PrimaryKey 指定此索引是否定义表的主键。 # 用法 要指定该表的主键由该索引所基于的属性构成,请使用以下语法: ```java Index name On property_expression_list [ PrimaryKey ]; ``` 否则,省略此关键字或将单词`Not`放在关键字的前面。 # 详解 此关键字指定应通过SQL将此索引报告为此类(表)的主键。 `PrimaryKey`索引的行为也类似于唯一索引。 也就是说,对于在此索引中使用的属性(或属性组合),InterSystems IRIS强制唯一性。 在这个索引定义中,允许将`Unique`关键字指定为`true`,但这是多余的。 # 示例 ```java Index EmpIDX On EmployeeID [ PrimaryKey] ; ``` # 默认 如果忽略此关键字,则该表的主键不是由索引所基于的属性构成的。 # 第五十四章 索引关键字 - ShardKey 指定这个类的分片键。 # 用法 在分片类完全实现之前,InterSystems建议从`SQL`创建分片表,而不是从对象端。 但是,如果你查看一个通过创建一个分片表生成的类,你可能会看到如下代码: ```java /// ShardKey分片表索引,由DDL CREATE table语句自动生成 Index ShardKey On DeptNum [ Abstract, CoshardWith = User.Department, ShardKey, SqlName = %ShardKey ]; ``` 在本例中,`DeptNum`属性是当前类的分片键。 # 第五十五章 索引关键字 - SqlName 指定索引的SQL别名。 # 用法 当通过`SQL`引用该索引时,要覆盖该索引的默认名称,使用以下语法: ```java Index name On property_expression_list [ SqlName = sqlindexname]; ``` 其中`sqlindexname`是一个`SQL`标识符。 # 详解 当通过`SQL`引用该关键字时,可以为该索引定义一个替代名称。 # 默认 如果忽略此关键字,则索引的SQL名称为索引定义中给定的`indexname`。 # 第五十六章 索引关键字 - Type 指定索引的类型。 # 用法 要指定索引的类型,请使用以下语法: ```java Index name On property_expression_list [ Type = indextype ]; ``` 其中`indextype`是下列类型之一: - `bitmap` — 位图索引 - `bitslice` — 位片索引 - `index` —标准索引(默认) - `key` — 废弃 # 详解 此关键字指定索引的类型,具体是将索引实现为位图索引还是标准(常规、非位图)索引。 位图索引不能标记为唯一`unique`。 # 默认 如果省略此关键字,则索引为标准索引。
文章
姚 鑫 · 二月 16

第二十五章 S 开头的术语

# 第二十五章 S 开头的术语 # 以 S 开头的术语 ### 模式演变 (schema evolution) **对象(Objects)** 模式演变允许你在不丢失使用旧类定义存储的数据访问能力的情况下,为类添加新的类成员。 ### 搜索用户 (search user) **系统** `IRIS` 连接到 `LDAP` 服务器的用户,其权限允许搜索 `LDAP` 数据库。其值在 `LDAP` 配置页面(系统管理 > 安全 > 系统安全 > `LDAP` 配置)的 `LDAP` 搜索用户 `DN` 或用于搜索的 `LDAP` 用户名字段中指定。(请注意,如果启用了 `Kerberos`,页面名称和菜单选项中会包含 `Kerberos`。) ### 次要卷 (secondary volume) **系统** 卷集中的任何卷,除了主卷之外。在一个 `IRIS` 数据库中,可以有零到七个次要卷,总共八个卷。 ### 安全顾问 (Security Advisor) **系统** 管理门户内的诊断工具,提供有关 `IRIS` 实例设置与典型安全标准建议之间差异的反馈。 ### 安全域 (security domain) **系统** 一组逻辑上的机器分组,大致对应于 `Kerberos` 领域或 `Windows` 域。 ### 选择性 (selectivity) **InterSystems SQL** 属性的选择性指定整个值分布中特定值的大致频率。 ### 顺序文件 (sequential file) **通用** 数据按照输入顺序存储的文件。 ### 服务器锁 (server lock) **系统** 请参见 传入锁(Incoming Lock)。 ### 服务器主进程 (server master) **系统** 服务器软件的一个组件,监听通过 `TCP` 连接的客户端的连接尝试,并生成服务器进程以服务这些连接。每个服务器主进程都是一个 `IRIS` 进程。 ### 服务器进程 (server process) **系统** 服务器上的一个后台进程,用于服务单个客户端连接。服务器主进程为此目的创建服务器进程。 ### 服务 (service) **系统** `InterSystems` 安全系统中的实体,通过现有路径(例如 `Telnet` 或 `JDBC`)调节对 `IRIS` 的访问。当连接到 `IRIS` 时,应用程序位于服务之上。 ### 浅层保存 (shallow save) **对象(Objects)** 浅层保存仅保存一个对象,而不保存其引用的对象。有关更多详细信息,请参见类参考内容中的 `%Persistent.%Save` 方法。