文章 Kelly Huang · 五月 15 4m read

InterSystems ObjectScript 技巧与窍门

嘿,社区的朋友们大家好!

是的,我知道我们有很多技巧和窍门类的文章-——我们甚至为此专门设置了一个标签(Tips & Tricks),不是吗?但我不能分享我自己的收藏。在这个合集中,您可以找到适合初学者的代码片段,以及一些日常的 ObjectScript 结构。事实上,这也是一种学习我最喜欢的编程语言的新方法。所以,如果你们有什么要补充的,欢迎提出!

 

1) 使用格式文本返回错误:

Return $$$ERROR($$$GeneralError, $$$FormatText("Failed to open message with ID = %1", id))

2) 使用嵌入式 SQL 时的错误检查 (&sql()):

Return:SQLCODE<0 $$$ERROR($$$GeneralError, $$$FormatText("Operation failed. SQLCODE = %1: %2", SQLCODE, $SYSTEM.SQL.Functions.SQLCODE(SQLCODE)))

3) 空性检查,包括任何类似空值的值:

If $ASCII(object.field)>0 {
    // Not empty
}

这里需要解释一下,我相信。例如,通过 SOAP 协议的外部系统可以将空值返回为 $CHAR(0)。在 Cache null 中,它是一个空字符串,但检查空字符串将无法正常工作。该表达式是解决这一问题的单行方法。

4) 在表中自动填充记录更新时间戳:

Property UpdatedAt As %TimeStamp [ SqlComputeCode = { Set {*} = $ZDATETIME($NOW(), 3) }, SqlComputed, SqlComputeOnChange = (%%INSERT, %%UPDATE) ];

5)从 LookupTable 读取值(名为 Settings):

Set value = $GET(^Ens.LookupTable("Settings", "my_key"))

6) 将值写入 LookupTable (名为 Settings):

Set tSC = ##class(Ens.Util.LookupTable).%UpdateValue("Settings", "my_key", value)

7) 导入 Python 软件包:

XData %import [ MimeType = application/python ]
{
import iris
from confluent_kafka import Consumer, KafkaException, TopicPartition, KafkaError
}

8)从 Python 返回 IRIS 状态:

return iris.system.Status.OK()
return iris.system.Status.Error(5001, f'Request body is invalid: {e}')

9) Python 代码中的跟踪:

Method Trace(message As %String)
{
    $$$TRACE(message)
}

Method PyImpl() [ Language = python ]
{
    self.Trace(f'Received message: {input.value}')
}

10) 将 JSON 数组 (%DynamicArray) 转换为逗号分隔字符串并返回:

Set jsonArray = ["test1","test2","test3"]
Set str = $TRANSLATE(jsonArray.%ToJSON(), "[]")
Set jsonArray = [].%FromJSON("["_str_"]")

11)格式化 JSON:

Do ##class(%JSON.Formatter).%New().FormatToString({"test":"test"}, .formatted)

12)将 %Status 转换为异常并返回 Try/Catch:

try {
    $$$ThrowOnError(object.%Save())
} catch ex {
    Return ex.AsStatus()
}

13)将 $$ERROR 写入应用程序错误日志(当我们需要 "无声 "异常时):

Do ##class(%Exception.StatusException).CreateFromStatus(tSC).Log()

14)对输入字符串进行规范化处理:

Set value = $ZSTRIP(value, "<>WC")

15)迭代 %DynamicArray 的一种方法:

Set it = array.%GetIterator()
While it.%GetNext(.key, .value) {
    Write !, key, ":", value
}

16)执行 SQL 查询的一种方法:

Set rs = ##class(%SQL.Statement).%ExecDirect(, "SELECT ID, Name FROM MyTable WHERE Status = ?", status)
Return:rs.%SQLCODE<0 $$$ERROR($$$GeneralError, $$$FormatText("Execute failed. SQLCODE = %1: %2", rs.%SQLCODE, rs.%Message))
While rs.%Next() {
    Write !, rs.ID_", "_rs.Name
}

17)执行 SQL 查询的另一种方法(使用游标):

&sql(DECLARE C1 CURSOR FOR SELECT ID, Name INTO :id, :name FROM MyTable WHERE Status = :status)
&sql(OPEN C1)
Return:SQLCODE $SYSTEM.Error.FromSQLCode(SQLCODE, %msg).Status
&sql(FETCH C1)
While SQLCODE = 0 {
    Write !, $$$FormatText("id = %1, name = %2", id, name)       
    &sql(FETCH C1)
}
&sql(CLOSE C1)

18) 执行 SQL 查询的第三种方法(使用 SQL 函数):

Query Test(status As %String) As %SQLQuery [ SqlProc ]
{
    SELECT ID, Name FROM MyTable WHERE Status = :status
}

ClassMethod TestRun()
{
    Set rs = ..TestFunc("Active")
    While rs.Next() {
        Write !, rs.ID_", "_rs.Name
    }
}

以上是主要的三种方法,但还有其他执行 SQL 查询的方法。这里就不一一列举了,我们继续往下看。

19)在单个实例中运行代码,无论哪个进程先到(锁定):

Lock +^MyLock(id):0
Return:'$TEST $$$OK
Try {
    // Parallel execution is prohibited for this block
} Catch ex {
    Set tSC = ex.AsStatus()
}
Lock -^MyLock(id)

20) $CASE$SELECT 代替 If/Else 链:

Set label = $CASE(status, "A":"Active", "I":"Inactive", "P":"Pending", :"Unknown")
Set label = $SELECT(status="A": "Active", status="I": "Inactive", status="P":"Pending", 1:"Unknown")

21) 临时(进程私有)全局:

Set ^||Temp(1) = "Will be removed automatically when the process ends"

22) 添加前导零:

Return $REPLACE($JUSTIFY(docNumber,4)," ",0)

23) 在 JSON 对象中设置数值字段:

Set json = {"id":(+value)}

24) 在 JSON 对象中设置布尔字段:

Do json.%Set("active", isActive, "boolean")

25) 条件中 AND 的替代方法 (&&):

If '$ISOBJECT(obj),obj.prop'="" {
    Write !, obj.prop
}

26) 对数组进行迭代(Globals 也是如此):

Set node = ""
For {
    Set node = $ORDER(array(node))
    Quit:node=""
    Set subnode = ""
    For {
        Set subnode = $ORDER(array(node,subnode))
        Quit:subnode=""
        Write !, "array(", "node, ",", subnode, ") = ", array(node,subnode)
    } 
}

27)动态全局名称:

Set MyGlobal = "^Sample.Data"
Write !, $GET(@MyGlobal@(node))

28) 轮到你了! 🙂