第八十三章 SQL命令 UPDATE(二)

2021-11-22  本文已影响0人  Cache技术分享

第八十三章 SQL命令 UPDATE(二)

显示到逻辑数据转换

数据以逻辑模式格式存储。
例如,日期存储为整数天数,时间存储为从午夜开始的秒数,%List存储为编码字符串。
大多数其他数据,如字符串和数字,不需要转换;
无论当前模式如何,它们都以相同的格式输入、更新和存储。

对于已转换的数据,可以在LOGICAL模式(默认)中更新数据值,或者通过指定选择模式,使用更易于阅读的格式(DISPLAY模式或ODBC模式)更新数据值。
例如,通过指定选择模式,可以以DISPLAY格式(例如2/22/2018)、ODBC格式(例如2018-02-22)或逻辑格式(例如64701)更新日期。
对于某些数据类型,还可以在ODBC或DISPLAY选择模式下以LOGICAL格式指定数据。

列表结构

IRIS支持列表结构数据类型%list(数据类型类%Library.List)。
这是一种压缩的二进制格式,并不映射到 SQL的相应本机数据类型。
它对应的数据类型为VARBINARY,默认MAXLEN32749
因此,动态SQL不能使用UPDATEINSERT来设置类型为%List的属性值。

流值

可以按照如下方法更新流字段中的数据值:

    SET literal="update stream string value"
       //do the update; use a string
    &sql(UPDATE MyStreamTable SET MyStreamField = :literal WHERE %ID=21)
    SET oref=##class(%Stream.GlobalCharacter).%New()
    DO oref.Write("Update stream string value non-shard 1")
       //do the update; use an actual OREF
    &sql(UPDATE MyStreamTable SET MyStreamField = :oref WHERE %ID=22)

或流的OREF的字符串版本,例如:

    SET oref=##class(%Stream.GlobalCharacter).%New()
    DO oref.Write("Update stream string value non-shard 2")
       //next line converts OREF to a string OREF
    set string=oref_""
       //do the update
    &sql(UPDATE MyStreamTable SET MyStreamField = :string WHERE %ID=23)
    SET clob=##class(%Stream.GlobalCharacter).%New("Shard")
    DO clob.Write("Update sharded table stream string value")
    SET sc=clob.%Save() // Handle $$$ISERR(sc)
      set ClobOid=clob.%Oid()
    //do the update
    &sql(UPDATE MyStreamTable SET MyStreamField = :ClobOid WHERE %ID=24)

不能使用流字段的内容更新非流字段。
这将导致一个SQLCODE -303错误:“不支持在UPDATE赋值中隐式地将流值转换为非流字段”。
要用Stream数据更新字符串字段,必须首先使用SUBSTRING函数将Stream数据的前n个字符转换为字符串,如下面的示例所示:

UPDATE MyTable
     SET MyStringField=SUBSTRING(MyStreamField,1,2000)

计算字段

COMPUTECODE定义的字段可以作为UPDATE操作的一部分重新计算它的值,如下所示:

当没有实际更新发生时,COMPUTEONCHANGE计算字段不会重新计算:当update操作的新字段值与之前的字段值相同时。

在大多数情况下,将计算字段定义为只读。
这防止更新操作直接更改一个值,该值是涉及其他字段值的计算结果。
在本例中,试图使用UPDATE覆盖计算字段的值将导致SQLCODE -138错误。

但是,可能希望修改一个计算字段值,以反映对一个(或多个)源字段值的更新。
可以通过使用更新触发器来实现这一点,该更新触发器在您更新了指定的源字段之后重新计算计算过的字段值。
例如,对Salary数据字段的更新可能触发重新计算Bonus computed字段的触发器。
这个更新触发器重新计算Bonus并成功完成,即使Bonus是一个只读字段。

可以使用CREATE TABLE ON UPDATE关键字短语来定义一个字段,当记录被更新时,该字段被设置为文字或系统变量(例如当前时间戳)。

%SerialObject属性

当更新%SerialObject中的数据时,必须更新引用嵌入%SerialObject的表(持久化类);
不能直接更新%SerialObject
从引用表中,可以:

此类型的更新可能不会执行%SerialObject属性值的验证。因此,强烈建议在使用%List结构更新%SerialObject属性值之后,使用$SYSTEM.SQL.Schema.ValidateTable()方法执行表数据验证。

此类型的更新执行%SerialObject属性值的验证。

FROM子句

UPDATE命令可能没有FROM关键字。它可以简单地指定要更新的表(或视图),并使用WHERE子句选择要更新的行。

但是,还可以在value-assignment-语句之后包括一个可选的FROM子句。此FROM子句指定用于确定要更新哪些记录的一个或多个表。FROM子句通常(但并非总是)与涉及多个表的WHERE子句一起使用。FROM子句可以很复杂,并且可以包括ANSI联接语法。UPDATE FROM子句允许SELECT FROM子句中支持的任何语法。此UPDATE FROM子句提供与Transact-SQL的功能兼容性。

以下示例显示如何使用此FROM子句。它更新Employees表中的那些记录,其中也可以在Requirees表中找到相同的EmpId

UPDATE Employees AS Emp
     SET retired='Yes'
     FROM Retirees AS Rt
     WHERE Emp.EmpId = Rt.EmpId

如果UPDATE TABLE-REFFROM子句引用同一个表,则这些引用可能是引用同一个表,也可能是引用该表的两个实例的联接。这取决于如何使用表别名:

  UPDATE table1 value-assignment FROM table1,table2   /* join of 2 tables */
  UPDATE table1 AS x value-assignment FROM table1 AS x,table2   /* join of 2 tables */
  UPDATE table1 AS x value-assignment FROM table1 AS y,table2   /* join of 3 tables */
  UPDATE table1 AS x value-assignment FROM table1,table2   /* join of 3 tables */
  UPDATE table1 value-assignment FROM table1 AS x,table2   /* join of 2 tables */
  UPDATE table1 value-assignment FROM table1,table1 AS x,table2        /* join of 3 tables */
  UPDATE table1 value-assignment FROM table1 AS x,table1 AS y,table2   /* join of 4 tables */

%Keyword 参数

指定%Keyword参数将按如下方式限制处理:

注意:由于使用%NOCHECK可能导致无效数据,因此只有在从可靠的数据源执行批量插入或更新时才应使用此%关键字参数。

用户必须具有当前命名空间的相应%NOCHECK管理权限才能应用此限制。否则将导致SQLCODE-99错误,因为%msg用户‘name’没有%NOCHECK权限。

如果希望在指定%NOCHECK时阻止导致非唯一数据值的更新,请在更新之前执行EXISTS检查。

如果只希望禁用外键引用完整性检查,请使用$SYSTEM.SQL.Util.SetOption(“FilerRefIntegrity”)方法,而不是指定%NOCHECK。或者,可以使用NOCHECK关键字定义外键,这样就永远不会执行外键引用完整性检查。

%PROFILE为主查询模块收集SQLStats
%PROFILE_ALL为主查询模块及其所有子查询模块收集SQLStats

可以以任何顺序指定多个%keyword 参数。
多个参数由空格分隔。

上一篇下一篇

猜你喜欢

热点阅读