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

为指定表中的指定列设置新值。

大纲
UPDATE [%keyword] table-ref [[AS] t-alias]
value-assignment-statement
[FROM [optimize-option] select-table [[AS] t-alias]
{, select-table2 [[AS] t-alias]} ]
[WHERE condition-expression]


UPDATE [%keyword] table-ref [[AS] t-alias]
value-assignment-statement
[WHERE CURRENT OF cursor]


value-assignment-statement ::=
SET column1 = scalar-expression1 {,column2 = scalar-expression2} ... |
[ (column1 {,column2} ...) ] VALUES (scalar-expression1 {,scalar-expression2} ...) |
VALUES :array()

参数

  • ​%keyword​​ - 可选参数:​​%NOCHECK​​, ​​%NOFPLAN​​, ​​%NOINDEX​​, ​​%NOJOURN​​, ​​%NOLOCK​​, ​​%NOTRIGGER​​, ​​%PROFILE​​, ​​%PROFILE_ALL​​。
  • ​table-ref​​ - 要更新数据的现有表的名称。

还可以指定一个视图,通过该视图对表执行更新。 不能在此参数中指定表值函数或​​JOIN​​语法。表名(或视图名)可以是限定的(​


​schema.table​​)或非限定的(​​table​​)。 使用模式搜索路径(如果提供的话)或默认模式名将非限定名称匹配到其模式。

  • ​AS t-alias​​ - 可选- ​​table-ref​​(表或视图)名称的别名。

别名必须是有效的标识符。 AS关键字是可选的。

  • ​FROM select-table​​ - 可选的——FROM子句,用于指定用于确定要更新哪些行的表。

多个表可以指定为逗号分隔的列表或与ANSI连接关键字关联。 可以指定任何表或视图的组合。 如果在这里在两个选择表之间指定逗号, IRIS将对表执行​​CROSS JOIN​​,并从​​JOIN​​操作的结果表中检索数据。如果在这里指定两个选择表之间的​


​ANSI​​连接关键字, IRIS将执行指定的连接操作。可以选择指定一个或多个优化选项关键字来优化查询执行。 可用的选项有:​


​%ALLINDEX​​、​​%FIRSTTABLE select-table​​、​​%FULL​​、​​%INORDER​​、​​%IGNOREINDICES​​、​​%NOFLATTEN​​、​​%NOMERGE​​、​​%NOSVSO​​、​​%NOTOPOPT​​、​​% nounoropt​​、​​%PARALLEL​​、​​%STARTTABLE​​。

  • ​WHERE condition-expression​​ - 可选-指定一个或多个布尔谓词,用于确定要更新哪些行。

如果没有提供​​WHERE​​子句(或​​WHERE CURRENT OF​​子句),​​UPDATE​​将更新表中的所有行。

  • ​WHERE CURRENT OF cursor​​ - 可选:仅嵌入SQL—指定​​UPDATE​​操作更新游标当前位置的记录。

可以指定​​WHERE CURRENT OF​​子句或​​WHERE​​子句,但不能同时指定两者。

  • ​column​​ - 可选—现有列的名称。

多个列名指定为逗号分隔的列表。 如果省略,则更新所有列。

  • ​scalar-expression​​ - 用标量表达式表示的列数据值。

多个数据值指定为逗号分隔的列表,其中每个数据值依次对应于一个列。

  • ​:array()​​ - 仅嵌入式SQL—指定为主机变量的值数组。

数组的最低下标级别必须是未指定的。 因此​​::myupdates()​​, ​​:myupdates(5,)​​和 ​​:myupdates(1,1,)​​都是有效的规范。

描述

​UPDATE​​命令更改表中列的现有值。可以直接更新表中的数据,也可以通过视图进行更新,或者使用括在括号中的子查询进行更新。 通过视图进行更新受制于需求和限制,如​


​CREATE view​​中所述。​


​UPDATE​​命令为包含这些列的一个或多个现有基表行提供一个或多个新列值。将数据值赋给列是使用值赋值语句完成的。 默认情况下,值赋值语句更新表中的所有行。 更常见的是,​


​UPDATE​​根据条件表达式指定对特定的行(或行)进行更新。默认情况下,​


​UPDATE​​操作遍历表中的所有行,并更新满足条件表达式的所有行。如果没有行满足条件表达式,​


​UPDATE​​将成功完成并设置​​SQLCODE=100​​(不再有数据)。可以指定​


​WHERE​​子句或​​WHERE CURRENT OF​​子句(但不能同时指定两者)。如果使用了​


​WHERE CURRENT OF​​子句,​​UPDATE​​将更新游标当前位置的记录。定位操作请参见​


​WHERE CURRENT OF​​。​


​UPDATE​​操作将​​%ROWCOUNT​​局部变量设置为更新的行数,将​​%ROWID​​局部变量设置为更新的最后一行的​​ROWID​​值。默认情况下,​


​UPDATE​​操作是一个全有或全无事件。 要么更新所有指定的行和列,要么不更新。

INSERT OR UPDATE

​INSERT OR UPDATE​​语句是​​INSERT​​语句的变体,执行插入和更新操作。首先,它尝试执行一个插入操作。 如果插入请求失败由于违反唯一键(字段(​


​s​​)的一些独特的关键,存在这一行已经有相同的值(​​s​​)为插入指定的行),然后它会自动变成一个更新请求这一行,并插入或更新使用指定的字段值来更新现有的行。

SQLCODE错误

默认情况下,多行UPDATE是一个原子操作。 如果不能更新一行或多行,则​​UPDATE​​操作失败,不会更新任何行。IRIS设置​


​SQLCODE​​变量,该变量指示​​UPDATE​​的成功或失败,如果操作失败,还设置​​%msg​​。 要更新表,更新必须满足所有表、列名和值要求,如下所示。 表:

  • 表必须存在于当前(或指定)命名空间中。

如果无法找到指定的表,IRIS将发出​​SQLCODE -30​​错误。

  • 该表不能定义为​​READONLY​​。

试图编译引用只读表的​​UPDATE​​会导致​​SQLCODE -115​​错误。注意,此错误是在编译时发出的,而不是在执行时发生的。 请参阅定义和使用类的其他持久化类选项章节中​


​READONLY​​对象的描述。

  • 该表不能被其他进程以​​EXCLUSIVE​​模式锁定。

试图更新一个被锁定的表将导致S​​QLCODE -110​​错误,并带有​​%msg​​,如下所示:​


​Person' on row with RowID = '10'​​。注意,只有当​


​UPDATE​​语句定位到要更新的第一条记录,然后不能在超时时间内锁定它时,才会出现​​SQLCODE -110​​错误。

  • 如果UPDATE指定了一个不存在的字段,则会发出​​SQLCODE -29​​。

要列出为指定表定义的所有字段名。 如果字段存在,但没有字段值满足​​UPDATE​​命令的​​WHERE​​子句,则不影响任何行,并发出​​SQLCODE 100​​(数据末尾)。

  • 在极少数情况下,使用​​%NOLOCK​​的​​UPDATE​​找到要更新的行,但随后该行立即被另一个进程删除;

这种情况将导致​​SQLCODE -109​​错误:无法找到为​​UPDATE​​指定的行。这个错误的​


​%msg​​列出了表名和​​RowID​​。

  • 如果通过视图更新表,则视图不能定义为​​WITH READ ONLY​​。

尝试这样做会导致​​SQLCODE -35​​错误。如果视图基于分片表,则不能通过定义​


​WITH CHECK OPTION​​的视图进行​​UPDATE​​。尝试这样做会导致一个​


​SQLCODE -35​​,其中​​%msg INSERT/UPDATE/DELETE​​不允许查看(​​sample.myview​​)基于带有检查选项条件的分片表。 列名和值:

  • 更新不能包含重复的字段名。

尝试指定两个具有相同名称的字段的更新将导致​​SQLCODE -377​​错误。

  • 不能更新已被另一个并发进程锁定的字段。

尝试这样做会导致​​SQLCODE -110​​错误。如果执行的更新数量非常大,以致出现


错误,也会发生此​​SQLCODE​​错误。

  • 不能更新整数计数器字段。

这些字段是不可修改的。 ​​RowID​​字段(​​SQLCODE -107​​);​


​IDENTITY​​字段(​​SQLCODE -107​​);​


​SERIAL (%Library.Counter)​​字段(​​SQLCODE -105​​);​


​ROWVERSION​​字段(​​SQLCODE -138​​)。这些字段的值是系统生成的,用户不能修改。 即使用户可以为计数器字段插入一个初始值,用户也不能更新该值。 唯一的例外是将​


​SERIAL (%Library.Counter)​​字段添加到具有现有数据的表时。对于这个添加的计数器字段,现有的记录将具有NULL值。 在这种情况下,可以使用​


​UPDATE​​将​​NULL​​更改为整数值。

  • 不能更新​​shard​​键字段。

尝试更新属于分片键一部分的字段会产生​​SQLCODE -154​​错误。

  • 如果更新将违反字段的唯一性约束,则不能更新字段值。

试图更新一个字段(或一组字段)的值,使更新违反惟一性约束或主键约束,将导致​​SQLCODE -120​​错误。如果字段具有UNIQUE数据约束,或者如果惟一字段约束已应用于一组字段,则返回此错误。 ​


​SQLCODE - 120% msg​​字符串包括违背唯一性约束的字段和值。例如​


​ or ​​。

  • 如果更新指定的值不在其​​VALUELIST​​参数中列出,则不能更新字段值。

用​​VALUELIST​​参数定义的持久化类的属性只能接受​​VALUELIST​​中列出的值中的一个作为有效值,或者不提供值(​​NULL​​)。​


​VALUELIST​​有效值区分大小写。尝试使用与​


​VALUELIST​​值不匹配的数据值进行更新会导致​​SQLCODE -105​​字段值验证失败错误。

  • 数字以规范形式插入,但可以用前导零和尾随零以及多个前导符号来指定。

然而,在SQL中,两个连续的负号被解析为单行注释指示符。 因此,试图指定具有两个连续前导减号的数字将导致​​SQLCODE -12​​错误。

  • 当使用​​WHERE CURRENT OF​​子句时,不能使用当前字段值更新字段以生成更新的值。

例如,​​SET Salary=Salary+100​​或​​SET Name=UPPER(Name)​​。尝试这样做会导致​


​SQLCODE -69​​错误:​​SET = not allowed with WHERE CURRENT OF ​​。

  • 如果更新其中一个指定的行会违反外键引用完整性(并且没有指定​​%NOCHECK​​), ​​UPDATE​​将无法更新任何行,并发出​​SQLCODE -124​​错误。

如果外键是用​​NOCHECK​​关键字定义的,则不适用。

  • 不能用流数据更新非流字段。

这将导致​​SQLCODE -303​​错误,如下所述。

赋值

可以通过多种方式为指定的列分配新值。

  • 使用​​SET​​关键字,将一个或多个列=标量表达式对指定为逗号分隔的列表。

例如:

SET StatusDate='05/12/06',Status='Purged'
  • 使用​​VALUES​​关键字,指定与相应的标量表达式列表相等的列列表。

例如:

(StatusDate,Status) VALUES ('05/12/06','Purged')

当将标量表达式值赋给列列表时,每个指定的列必须有一个标量表达式。

  • 使用不带列列表的​​VALUES​​关键字,指定一个按列顺序隐式对应于行的列的标量表达式列表。

下面的示例指定了表中的所有列,指定了一个文本值来更新Address列:

VALUES (Name,DOB,'22 Main St. Anytown MA 12345',SSN)

在为隐式列列表赋值时,必须按照​​DDL​​中定义的列的顺序为每个可更新字段提供一个值。(没有指定不可更新的​


​RowID​​列。) 这些值可以是指定新值的文字,也可以是指定现有值的字段名。 不能指定占位符逗号或省略尾随字段。

  • 使用不带列列表的​​VALUES​​关键字,指定下标数组,其中数字下标对应列号,包括在列计数中不可更新的​​RowID​​作为列号1。

例如:

VALUES :myarray()

只能使用主机变量在嵌入式​​SQL​​中执行此值赋值。与所有其他值赋值不同,这种用法允您延迟指定哪些列要更新到运行时(通过在运行时填充数组)。 所有其他类型的更新都要求必须在编译时指定要更新的列。 此语法不能用于链接表; 尝试这样做会导致​


​SQLCODE=-155​​错误。