文章
姚 鑫 · 十一月 20, 2021 阅读大约需 8 分钟

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

第八十二章 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模式锁定。
    试图更新一个被锁定的表将导致SQLCODE -110错误,并带有%msg,如下所示:
    Person' on row with RowID = '10'
    注意,只有当UPDATE语句定位到要更新的第一条记录,然后不能在超时时间内锁定它时,才会出现SQLCODE -110错误。
  • 如果UPDATE指定了一个不存在的字段,则会发出SQLCODE -29
    要列出为指定表定义的所有字段名。
    如果字段存在,但没有字段值满足UPDATE命令的WHERE子句,则不影响任何行,并发出SQLCODE 100(数据末尾)。
  • 在极少数情况下,使用%NOLOCKUPDATE找到要更新的行,但随后该行立即被另一个进程删除;
    这种情况将导致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错误。
    如果执行的更新数量非常大,以致出现<LOCKTABLEFULL>错误,也会发生此SQLCODE错误。
  • 不能更新整数计数器字段。
    这些字段是不可修改的。
    RowID字段(SQLCODE -107);
    IDENTITY字段(SQLCODE -107);
    SERIAL (%Library.Counter)字段(SQLCODE -105);
    ROWVERSION字段(SQLCODE -138)。
    这些字段的值是系统生成的,用户不能修改。
    即使用户可以为计数器字段插入一个初始值,用户也不能更新该值。

唯一的例外是将SERIAL (%Library.Counter)字段添加到具有现有数据的表时。
对于这个添加的计数器字段,现有的记录将具有NULL值。
在这种情况下,可以使用UPDATENULL更改为整数值。

  • 不能更新shard键字段。
    尝试更新属于分片键一部分的字段会产生SQLCODE -154错误。
  • 如果更新将违反字段的唯一性约束,则不能更新字段值。
    试图更新一个字段(或一组字段)的值,使更新违反惟一性约束或主键约束,将导致SQLCODE -120错误。
    如果字段具有UNIQUE数据约束,或者如果惟一字段约束已应用于一组字段,则返回此错误。
    SQLCODE - 120% msg字符串包括违背唯一性约束的字段和值。
    例如<Table 'Sample.MyTable', Constraint 'MYTABLE_UNIQUE3', Field(s) FullName="Molly Bloom"; failed unique check> or <Table 'Sample.MyTable', Constraint 'MYTABLE_PKEY2', Field(s) FullName="Molly Bloom"; failed unique check>

  • 如果更新指定的值不在其VALUELIST参数中列出,则不能更新字段值。
    VALUELIST参数定义的持久化类的属性只能接受VALUELIST中列出的值中的一个作为有效值,或者不提供值(NULL)。
    VALUELIST有效值区分大小写。
    尝试使用与VALUELIST值不匹配的数据值进行更新会导致SQLCODE -105字段值验证失败错误。

  • 数字以规范形式插入,但可以用前导零和尾随零以及多个前导符号来指定。
    然而,在SQL中,两个连续的负号被解析为单行注释指示符。
    因此,试图指定具有两个连续前导减号的数字将导致SQLCODE -12错误。
  • 当使用WHERE CURRENT OF子句时,不能使用当前字段值更新字段以生成更新的值。
    例如,SET Salary=Salary+100SET Name=UPPER(Name)
    尝试这样做会导致SQLCODE -69错误:SET <field> = <value expression> not allowed with WHERE CURRENT OF <cursor>
  • 如果更新其中一个指定的行会违反外键引用完整性(并且没有指定%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错误。

00
1 0 0 4
登录或注册以继续