第十四章 信号(四)- 多进程任务示例
可根据此思想进行多任务启动查询汇总数据。
原理
- 利用
job机制开启后台进程。 - 利用
loop循环减少进程的数量等于开启进程的数量,判断多进程任务是否完成。
创建表并插入
1000W条数据,统计Moeny字段总金额创建
demo代码如下。
可根据此思想进行多任务启动查询汇总数据。
job机制开启后台进程。loop循环减少进程的数量等于开启进程的数量,判断多进程任务是否完成。创建表并插入1000W条数据,统计Moeny字段总金额
创建demo代码如下。
Main、Producer 和 Consumer 这三个类中的每一个都有自己的 Run 方法,最好在各自的终端窗口中运行它们。每次运行时,它都会显示它为日志生成的消息。一旦用户通过提供它正在等待的输入来响应 Main 类,Main 的 Run 方法将终止删除信号量。然后,用户可以通过键入命令查看所有进程的合并日志文件的显示
Do ##class(Semaphore.Util).ShowLog()
注意:以下所有示例都假定所有类都已在“USER”命名空间中编译。
最简单的例子演示了信号量的创建和销毁。它使用 Semaphore.Main 类。请执行下列操作:
Do ##class(Semaphore.Main).Run()
Enter 键。该方法显示信号量的初始化值,将其删除,然后退出。Do ##class(Semaphore.Util).ShowLog()
按照上述步骤在终端窗口中显示的消息示例如下
下面是一系列使用信号量实现生产者/消费者场景的类。 “主”进程初始化信号量并等待用户指示活动已全部完成。生产者在循环中随机增加一个信号量值,更新之间的延迟可变。消费者尝试在随机时间从信号量中删除随机数量,也是在循环中。该示例由 5 个类组成:
Main – 初始化环境并等待信号量上的活动完成的类。Counter – 实现信号量本身的类。它记录它的创建以及由于信号量在等待列表中而发生的任何回调。Producer – 一个类,其主要方法增加信号量值。增量是一个随机选择的小整数。完成增量后,该方法会在下一个增量之前延迟一小段随机数秒。Consumer 消费者——这是对生产者的补充。此类的主要方法尝试将信号量减少一个随机选择的小整数。它将递减请求添加到其等待列表中,等待时间也是随机选择的秒数。注意:组成这些类的代码特意写得简单。尽可能地,每个语句只完成一个动作。这应该使用户更容易和更直接地修改示例。
此类建立演示环境。它调用实用程序类来初始化日志和名称索引工具。然后它用初始值 0 初始化公共信号量,并等待用户输入一个字符(通常是 ENTER 键),表明实验已经完成。
维基百科对信号量有这样的定义:“在计算机科学中,特别是在操作系统中,信号量是一种变量或抽象数据类型,用于控制多个进程在并行编程或多用户环境中对公共资源的访问。”信号量不同于互斥体(或锁)。互斥锁最常用于管理竞争进程对单个资源的访问。当一个资源有多个相同的副本并且这些副本中的每一个都可以由单独的进程同时使用时,就会使用信号量。
考虑一个办公用品商店。它可能有几台复印机供其客户使用,但每台复印机一次只能由一个客户使用。为了控制这一点,有一组键可以启用机器并记录使用情况。当客户想要复印文件时,他们向职员索取钥匙,使用机器,然后归还钥匙,并支付使用费。如果所有机器都在使用,客户必须等到钥匙归还。保存键的位置用作信号量。
该示例可以进一步推广到包括不同类型的复印机,也许可以通过它们可以制作的副本的大小来区分。在这种情况下,将有多个信号量,如果复制者在复制的大小上有任何重叠,那么希望复制共同大小的客户将有两个资源可供提取。
信号量是共享对象,用于在进程之间提供快速、高效的通信。每个信号量都是类 %SYSTEM.Semaphore 的一个实例。信号量可以建模为一个共享变量,它包含一个 64 位非负整数。信号量上的操作在共享它的所有进程中以同步的方式更改变量的值。按照惯例,值的变化会在共享信号量的进程之间传递信息。
注:IRIS有,Cache无。
^LOGDMN 例程允许管理结构化日志记录;还有一个基于类的 API,将在下一节中介绍。
要使用 ^LOGDMN 启用结构化日志记录:
set $namespace="%sys"
do ^LOGDMN
这将启动一个带有以下提示的例程:
1) Enable logging
2) Disable logging
3) Display configuration
4) Edit configuration
5) Set default configuration
6) Display logging status
7) Start logging
8) Stop logging
9) Restart logging
LOGDMN option?
4 以便可以指定配置详细信息。然后,该例程会提示输入以下项目:a. 最低日志级别,以下之一:
-2 — 详细的调试消息(例如十六进制转储)。-1 — 不太详细的调试消息。0 — 信息性消息,包括所有审计事件。1(默认值)— 警告,表示可能需要注意但未中断操作的问题。2 — 严重错误,表明问题已中断操作。3 — 致命错误,表示问题导致系统无法运行。b. 管道命令,它指定系统将结构化日志发送到哪里。输入以下形式的响应:
IRIS 支持结构化日志记录。
创建多个日志,每个日志用于不同的目的。从以前的产品迁移过来的客户可以像过去一样利用这些日志,但现在还可以将所有日志信息导入一个单一的、中央的、机器可读的日志文件——结构化日志。然后可以将此文件与第三方分析工具一起使用。
本文概述了结构化日志中的信息,展示了日志示例,并描述了如何启用结构化日志记录。
当启用结构化日志记录时,系统会将相同的数据写入结构化日志,它也会写入其他日志(无论哪个)。例如,系统将相同的行写入messages.log 和结构化日志。
启用结构化日志记录后,结构化日志包含以下所有信息:
messages.log 的信息。这包括需要注意的警报、有关系统启动和关闭的信息、有关日志文件和 WIJ 文件的高级信息、有关配置更改 (CPF) 的信息以及与许可相关的信息。本部分显示结构化日志记录实用程序的示例输出,用于名称/值对格式和 JSON 格式。
以下输出使用格式选项 NVP(名称/值对)。此示例经过编辑以用于显示目的;在实际输出中,每个条目只占一行,条目之间没有空行。
要创建一个存储为整数的新位串,请对每个位求和 2 的幂:
set bitint = (2**2) + (2**5) + (2**10)
write bitint
1060
要将现有位串中的位设置为 1,请使用 $zboolean 函数(逻辑 OR)的选项7(arg1 ! arg2):
set bitint = $zboolean(bitint, 2**4, 7)
write bitint
1076
要将现有位串中的位设置为 0,请使用 $zboolean 函数的选项 2(arg1 & ~arg2):
set bitint = $zboolean(bitint, 2**4, 2)
write bitint
1060
要在现有位串中切换位,请使用 $zboolean 函数(逻辑 XOR)的选项 6(arg1 ^ arg2):
set bitint = $zboolean(bitint, 2**4, 6)
write bitint
1076
set bitint = $zboolean(bitint, 2**4, 6)
write bitint
1060
要将位字符串显示为整数,可以使用如下方法,该方法循环位并使用 $zboolean 函数:
要创建新的位串,请使用 $bit 函数将所需位设置为 1:
kill bitstring
set $bit(bitstring, 3) = 1
set $bit(bitstring, 6) = 1
set $bit(bitstring, 11) = 1
使用 $bit 将现有位串中的位设置为 1:
set $bit(bitstring, 5) = 1
使用 $bit 将现有位串中的位设置为 0:
set $bit(bitstring, 5) = 0
由于位串中的第一位是位 1,因此尝试设置位 0 会返回错误:
set $bit(bitstring, 0) = 1
SET $BIT(bitstring, 0) = 1
^
<VALUE OUT OF RANGE>
要测试是否在现有位串中设置了位,还可以使用 $bit 函数:
write $bit(bitstring, 6)
1
write $bit(bitstring, 5)
0
如果测试未明确设置的位,则 $bit 返回 0:
write $bit(bitstring, 4)
0
write $bit(bitstring, 55)
0
要显示位串中的位,请使用 $bitcount 函数获取位串中位的计数,然后遍历位:
如果要将一系列布尔参数传递给方法,一种常见的方法是将它们作为编码为单个整数的位序列传递。
例如,Security.System.ExportAll() 方法用于从 IRIS 实例中导出安全设置。如果查看此方法的类引用,将看到它的定义如下:
classmethod ExportAll(FileName As %String = "SecurityExport.xml",
ByRef NumExported As %String, Flags As %Integer = -1) as %Status
第三个参数 Flags 是一个整数,其中每个位代表一种可以导出的安全记录。
有时可能希望在基于数据平台的应用程序中存储一系列相关的布尔值。可以创建许多布尔变量,也可以将它们存储在数组或列表中。或者可以使用称为“位串”的概念,它可以定义为位序列,首先呈现最低有效位。位串允许您以非常有效的方式存储此类数据,无论是在存储空间还是处理速度方面。
位串可以以两种方式之一存储,作为压缩字符串或整数。如果在没有上下文的情况下听到术语“位串”,则表示位序列存储为压缩字符串。本文向介绍了这两种类型的位串,然后介绍了一些可用于操作它们的技术。
存储位序列的最常见方式是在位串中,这是一种特殊的压缩字符串。除了节省存储空间外,还可以使用 ObjectScript 系统函数有效地操作位串。
这样的系统函数是 $factor,它将整数转换为位串。我们可以通过执行以下语句将整数 11744 转换为位串:
set bitstring = $factor(11744)
要查看位串内容的表示,可以使用 zwrite 命令:
zwrite bitstring
bitstring=$zwc(128,4)_$c(224,45,0,0)/*$bit(6..9,11,12,14)*/
增量锁定具有潜在危险,因为它可能导致称为死锁的情况。当两个进程各自对已被另一个进程锁定的变量断言增量锁定时,就会出现这种情况。因为尝试的锁是增量的,所以现有的锁不会被释放。结果,每个进程在等待另一个进程释放现有锁的同时挂起。
举个例子:
A 发出此命令:lock + ^MyGlobal(15)B 发出此命令:lock + ^MyOtherGlobal(15)A 发出此命令:lock + ^MyOtherGlobal(15)此 LOCK 命令不返回;进程被阻塞,直到进程 B 释放这个锁。
B 发出此命令:lock + ^MyGlobal(15)此 LOCK 命令不返回;进程被阻塞,直到进程 A 释放这个锁。但是,进程 A 被阻塞,无法释放锁。现在这些进程都在等待对方。
有几种方法可以防止死锁:
timeout 参数。LOCK 命令的顺序,请遵循严格的协议。只要所有进程都遵循相同的锁名称顺序,就不会发生死锁。一个简单的协议是按排序顺序添加锁。+ 运算符。如前所述,对于简单锁定,LOCK 命令首先释放进程持有的所有先前锁定。 (然而,在实践中,简单的锁定并不经常使用。)如果发生死锁,可以使用管理门户或 ^LOCKTAB
使用升级锁来管理大量锁。当锁定数组的节点时,它们是相关的,特别是当将多个节点锁定在同一下标级别时。
当给定进程在同一数组中的给定下标级别创建了超过特定数量(默认为 1000)的升级锁时, 将删除所有单独的锁名称并用新锁替换它们。新锁位于父级,这意味着数组的整个分支被隐式锁定。示例(如下所示)演示了这一点。
应用程序应在合适的情况下尽快释放特定子节点的锁(与非升级锁完全相同)。当释放锁时, 会减少相应的锁计数。当的应用程序移除足够多的锁时,会移除父节点上的锁。第二小节显示了一个示例。
假设有 1000 个^MyGlobal("sales","EU",salesdate) 形式的锁,其中 salesdate 表示日期。锁表可能如下所示:
注意 Owner 19776 的条目(这是拥有锁的进程)。 ModeCount 列指示这些是共享的、升级的锁。
当同一进程试图创建另一个相同形式的锁时, 会升级它们。它会移除这些锁并用名称为 ^MyGlobal("sales","EU") 的单个锁替换它们。现在锁表可能如下所示:
ModeCount 列表明这是一个共享的升级锁,它的计数是 1001。
请注意以下关键点:
如上所述,如果您将 timeout 指定为 0, 会添加锁。但是,如果使用零超时锁定父节点,并且已经在子节点上锁定,则忽略零超时并使用内部 1 秒超时。
要删除默认类型的锁,请使用 LOCK 命令,如下所示:
LOCK -lockname
如果执行此命令的进程拥有具有给定名称的锁(默认类型),则此命令将删除该锁。或者,如果进程拥有多个锁(默认类型),此命令将删除其中一个。
或者删除另一种类型的锁:
LOCK -lockname#locktype
其中 locktype 是一串锁类型代码。
LOCK 命令的其他基本变体为了完整起见,本节讨论 LOCK 命令的其他基本变体:使用它来创建简单的锁并使用它来删除所有锁。这些变化在实践中并不常见。
对于 LOCK 命令,如果省略 + 运算符,LOCK 命令首先会删除该进程持有的所有现有锁,然后尝试添加新锁。在这种情况下,锁称为简单锁而不是增量锁。一个进程可以拥有多个简单的锁,如果该进程使用如下语法同时创建它们:
LOCK (^MyVar1,^MyVar2,^MyVar3)
简单的锁在实践中并不常见,因为通常需要持有多个锁并在代码的不同步骤中获取它们。因此使用增量锁更实用。
任何多进程系统的一个重要特征是并发控制,即防止不同进程同时更改特定数据元素的能力,从而导致损坏。 提供了一个锁管理系统。本文提供了一个概述。
此外,%Persistent 类提供了一种控制对象并发访问的方法,即 %OpenId() 的并发参数和该类的其他方法。这些方法最终使用本文讨论的 ObjectScript LOCK 命令。所有持久对象都继承这些方法。同样,系统会自动对 INSERT、UPDATE 和 DELETE 操作执行锁定(除非指定 %NOLOCK 关键字)。
%Persistent 类还提供方法 %GetLock()、%ReleaseLock()、%LockId()、%UnlockId()、%LockExtent() 和 %UnlockExtent()。
基本的锁定机制是 LOCK 命令。此命令的目的是延迟一个进程中的活动,直到另一个进程发出可以继续进行的信号。
锁本身并不能阻止活动行为。锁定仅按约定起作用:它要求相互竞争的进程都使用相同的锁定名称实现锁定。例如,下面描述了一个常见的场景:
系统提供的变量。
$HOROLOG
$JOB
$NAMESPACE
$TLEVEL
$USERNAME
$ZHOROLOG
$ZJOB
$ZPI
$ZTIMESTAMP
$ZTIMEZONE
$ZVERSION
SQL直接支持许多对象脚本特殊变量。这些变量包含系统提供的值。只要可以在SQL中指定文字值,就可以使用它们。
SQL特殊变量名不区分大小写。大多数可以使用缩写来指定。
IRIS® 数据平台提供了用于登录数据库和开始使用的默认用户名和密码。默认用户名为“_SYSTEM”(大写),密码为“sys”。
执行大多数 SQL操作都会发出SQLCODE值。发出的SQLCODE值为0、100和负整数值。
SQLCODE=0表示SQL操作成功完成。对于SELECT语句,这通常意味着从表中成功检索数据。但是,如果SELECT执行聚合操作(例如:SELECT SUM(Myfield)),则聚合操作成功,即使myfield中没有数据,也会发出SQLCODE=0;在这种情况下,SUM返回NULL,%ROWCOUNT=1。SQLCODE=100表示SQL操作成功,但没有找到可操作的数据。发生这种情况的原因有很多。对于SELECT,这些包括:指定表不包含数据;表不包含满足查询条件的数据;或者行检索已到达表的最后一行。对于UPDATE或DELETE,它们包括:指定的表不包含数据;或者表不包含满足WHERE子句条件的数据行。在这些情况下,%ROWCOUNT=0。SQLCODE=-n表示错误。负整数值指定发生的错误类型。SQLCODE=-400是通用的致命错误代码。字段约束指定管理字段允许的数据值的规则。一个字段可能有以下约束:
管理门户提供管理全局变量的工具,系统类提供执行某些相同任务的方法。本章介绍如何使用这些工具。
与ObjectScript命令SET、MERGE、KILL和其他命令一样,这里描述的工具提供了直接访问操作全局变量的权限。如果通过全局访问删除或修改,则会绕过所有对象和SQL完整性检查,并且没有撤消选项。因此,在执行这些任务时要非常小心,这一点很重要。(查看和导出不会影响数据库,并且是安全活动。)
使用本章中介绍的工具时,请确保以下事项:
即使应用程序从不执行任何直接全局访问,应用程序也会使用全局变量。请记住,如果创建持久类,则它们的数据和任何索引都存储在全局变量中,全局变量的名称基于类名(默认情况下)。
管理门户包括全局页面,该页面允许管理全局。在此页上,可以执行以下操作:
此页还包括用于查看例程和类的选项;此处不讨论这些选项。
验证和转换 ODBC 日期、时间或时间戳。
{d 'yyyy-mm-dd'}
{d nnnnnn}
{t 'hh:mm:ss[.fff]'}
{t nnnnn.nnn}
{ts 'yyyy-mm-dd [hh:mm:ss.fff]'}
{ts 'mm/dd/yyyy [hh:mm:ss.fff]'}
{ts nnnnnn}
这些构造采用 ODBC 日期、时间或时间戳格式的整数或字符串,并将其转换为相应的 IRIS 日期、时间或时间戳格式。他们执行数据输入以及值和范围检查。
{d 'string'}{d 'string'}日期构造验证 ODBC 格式的日期。如果日期有效,它将以 IRIS $HOROLOG 日期格式存储(逻辑模式)作为 1840-12-31 的整数计数值。 IRIS 不附加默认时间值。要支持早于 1840-12-31 的日期,必须在表中定义数据类型为 %Library.Date(MINVAL=-nnn) 的日期字段,其中 MINVAL 是从 1840-12-31 倒数的负天数(第 0 天)最大为 -672045 (0001-01-01)。
在查询元数据和其他上下文中,为列定义的数据类型可以作为整数代码返回。 CType(客户端数据类型)整数代码列在 %SQL.StatementColumnclientType 属性中。
ODBC 和 JDBC 使用 xDBC 数据类型代码 (SQLType)。 ODBC 数据类型代码由 %SQL.Statement.%Metadata.columns.GetAt() 方法返回,如上例所示。 SQL Shell 元数据还返回 ODBC 数据类型代码。 JDBC 代码与 ODBC 代码相同,除了时间和日期数据类型的表示。下面列出了这些 ODBC 和 JDBC 值:
%Library.String 数据类型支持的最大字符串长度为 3,641,144 个字符。通常,极长的字符串应分配为 %Stream.GlobalCharacter 数据类型之一。
因为 IRIS 支持 xDBC 协议 50 和更高版本,所以没有强制执行 ODBC 或 JDBC 字符串长度限制。如果 IRIS 实例和 ODBC 驱动程序支持不同的协议,则使用两个协议中较低的一个。实际使用的协议记录在 ODBC 日志中。
请注意,默认情况下 IRIS 建立系统范围的 ODBC VARCHAR 最大长度为 4096;此 ODBC 最大长度是可配置的。
IRIS 支持列表结构数据类型 %List(数据类型类 %Library.List)。这是一种压缩的二进制格式,不会映射到 SQL 的相应本机数据类型。在其内部表示中,它对应于数据类型 VARBINARY,默认 MAXLEN 为 32749。 IRIS 支持列表结构数据类型 %ListOfBinary(数据类型类 %Library.ListOfBinary)对应于数据类型 VARBINARY,默认 MAXLEN 为 4096。
因此,动态 SQL 不能在 WHERE 子句比较中使用 %List 数据。也不能使用 INSERT 或 UPDATE 来设置 %List 类型的属性值。
可以定义日期、时间和时间戳数据类型,并通过标准 SQL 日期和时间函数相互转换日期和时间戳。例如,可以使用 CURRENT_DATE 或 CURRENT_TIMESTAMP 作为使用该数据类型定义的字段的输入,或者使用 DATEADD、DATEDIFF、DATENAME 或 DATEPART 来操作使用该数据类型存储的日期值。
数据类型类 %Library.Date、%Library.Time、%Library.PosixTime、%Library.TimeStamp 和 %MV.Date 对于 SqlCategory 的处理方式如下:
上表中为 DDL 和 IRIS 数据类型表达式显示的语法是为 SQL.SystemDataTypes 配置的默认映射。对于提供的系统数据类型和用户数据类型,有单独的映射表可用。
要查看和修改当前数据类型映射,请转到管理门户,选择系统管理、配置、SQL 和对象设置、系统 DDL 映射。
将数据类型从 DDL 映射到 IRIS 时,常规参数和函数参数遵循以下规则:
%# 格式标识。例如: VARCHAR(%1)
映射到:
%String(MAXLEN=%1)
因此,DDL 数据类型为:
VARCHAR(10)
映射到:
%String(MAXLEN=10)
MAXVAL、MINVAL 和 SCALE 参数。例如: DECIMAL(%1,%2)
映射到:
指定 SQL 实体(如列)可以包含的数据类型。
此处描述了以下主题:
支持的 DDL 数据类型及其类属性映射表
数据类型优先级用于从具有不同数据类型的数据值中选择最具包容性的数据类型
日期、时间、PosixTime 和时间戳数据类型
支持字符串数据类型、列表数据类型和流数据类型
支持 ROWVERSION 数据类型
IRIS® 数据平台 ODBC / JDBC 公开的数据类型
使用查询元数据方法和数据类型整数代码确定列的数据类型
创建用户定义的数据类型
处理未定义的数据类型
数据类型转换函数
数据类型指定列可以保存的值的种类。在使用 CREATE TABLE 或 ALTER TABLE 定义字段时指定数据类型。定义 SQL 字段时,可以指定下表(左列)中列出的 DDL 数据类型。当指定其中一种 DDL 数据类型时,它会映射到右侧列中列出的IRIS 数据类型类。在IRIS 中定义字段时,可以指定 DDL 数据类型或数据类型类。 DDL 数据类型名称不区分大小写。数据类型类名称区分大小写。 %Library 数据类型类可以通过全名(例如,%Library.String)或短名(%String)来指定。
绕过ODBC使用ObjectScript访问远程系统
这是一个在 IRIS 2020.1 和 Caché 2018.1.3 上工作的代码示例
不会与新版本保持同步
也不会获得 InterSystems 提供的支持服务!
我们经常会遇到这样的情况,由于各种原因ODBC是访问一个远程系统的唯一选择。如果你只需要检查或改变表,这就足够了。但你不能直接执行一些命令或改变一些Global。
特别感谢@Anna Golitsyna 启发我发表此文。
这个例子提供了3种 SQLprocedure 方法来实现访问远程系统这个目的,如果其他的访问方式被阻止,通常是被一些防火墙阻止。
返回日期表达式的年份的日期函数。
YEAR(date-expression)
{fn YEAR(date-expression)}
date-expression - 计算结果为 日期整数、ODBC 日期字符串或时间戳的表达式。此表达式可以是列名、另一个标量函数的结果或日期或时间戳字面量。YEAR 将日期整数($HOROLOG 日期)、ODBC 格式日期字符串或时间戳作为输入。 YEAR 以整数形式返回相应的年份。
日期表达式时间戳可以是数据类型 %Library.PosixTime(编码的 64 位有符号整数),也可以是数据类型 %Library.TimeStamp (yyyy-mm-dd hh:mm:ss.fff)。
年份 (yyyy) 部分应该是 0001 到 9999 范围内的四位整数。输入时前导零是可选的。前导零在输出上被抑制。两位数的年份不会扩展到四位数。
date-expression 的日期部分经过验证,并且必须包含 1 到 12 范围内的月份以及指定月份和年份的有效日期值。否则,将生成 SQLCODE -400 错误 <ILLEGAL VALUE>。
如果日期表达式的时间部分存在,则对其进行验证,但可以省略。
注意:为了与 内部日期表示兼容,强烈建议将所有年份值表示为 0001 到 9999 范围内的四位整数。
格式化多个 XML 标记以包含表达式值的函数。
XMLFOREST(expression [AS tag][,expression [AS tag]])
expression - 任何有效的表达式。通常是包含要标记的数据值的列的名称。当指定为逗号分隔列表时,列表中的每个表达式都将包含在其自己的 XML 标记标记中。AS tag - 可选 — XML 标记标记的名称。如果指定了标签,则 AS 关键字是必需的。保留标签中字母的大小写。
用双引号括起来的标签是可选的。如果省略双引号,标签必须遵循 XML 命名标准。用双引号括起来的标签消除了这些命名限制。XMLFOREST 对有效的标签名称实施 XML 命名标准。它不能包含任何字符!"#$%&'()*+,/;<=>?@[\]^``{|}~,也不能包含空格字符,并且不能以 "-", ".", 或数字。
如果指定不带 AS 标记子句的表达式,则标记值是表达式列的名称(大写字母):<HOME_CITY>Chicago</HOME_CITY>。
一种格式化 XML 标记标记以包含一个或多个表达式值的函数。
XMLELEMENT([NAME] tag,expression[,expression])
XMLELEMENT([NAME] tag,XMLATTRIBUTES(expression [AS alias]),expression[,expression])
NAME tag - XML标记的名称。NAME关键字是可选的。该参数有三种语法形式: NAME "tag", "tag"和NAME。前两者在功能上是相同的。如果指定,标记必须用双引号括起来。标签中的字母大小写保持不变。XMLELEMENT不执行标记值的验证。然而,XML标准要求有效的标记名不能包含任何字符 !"#$%&'()*+,/;<=>?@[\]^``{|}~,并且不能以"-", "."或数字开头。
如果指定没有标记值的 NAME 关键字, 将提供默认标记值:<Name> ... </Name>。 NAME 关键字不区分大小写;结果标签初始大写。
expression - 任何有效的表达式。通常是包含要标记的数据值的列的名称。可以指定以逗号分隔的列列表或其他表达式,所有这些都将包含在同一标记中。第一个以逗号分隔的元素可以是 XMLATTRIBUTES 函数。只能指定一个 XMLATTRIBUTES 元素。注:IRIS函数。
连接 XML 元素的函数。
XMLCONCAT(XmlElement1,XmlElement2[,...])
XmlElement - XMLELEMENT 函数。指定两个或多个要连接的 XmlElement。XMLCONCAT 函数将来自多个 XMLELEMENT 函数的值作为单个字符串返回。 XMLCONCAT 可用于引用表或视图的 SELECT 查询或子查询。 XMLCONCAT 可以与普通字段值一起出现在 SELECT 列表中。
以下查询连接来自两个 XMLELEMENT 函数的值:
SELECT Name,XMLCONCAT(XMLELEMENT("Para",Name),
XMLELEMENT("Para",Home_City)) AS ExportString
FROM Sample.Person
ExportString
<Para>Emerson,Molly N.</Para><Para>Boston</Para>
以下查询将 XMLCONCAT 嵌套在 XMLELEMENT 函数中:
一个日期函数,它将一年中的第几周作为日期表达式的整数返回。
{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。
返回当前用户的用户名的函数。
USER
{fn USER}
{fn USER()}
USER 不接受任何参数并返回当前用户的用户名(也称为授权 ID)。通用函数不允许括号; ODBC 标量函数可以指定或省略空括号。
用户名是使用 CREATE USER 命令定义的。
USER 的典型用途是在 SELECT 语句选择列表或查询的 WHERE 子句中。在设计报告时,USER 可用于打印正在为其生成报告的当前用户。
以下示例返回当前用户名:
SELECT USER AS CurrentUser
yx
以下示例选择姓氏 ($PIECE(Name,',',1) 或名字(没有中间首字母)与当前用户名匹配的那些记录:
SELECT Name FROM Sample.Person
WHERE %SQLUPPER(USER)=%SQLUPPER($PIECE(Name,',',1))
OR %SQLUPPER(USER)=%SQLUPPER($PIECE($PIECE(Name,',',2),' ',1))