第八十二章 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(数据末尾)。 - 在极少数情况下,使用
%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错误。 如果执行的更新数量非常大,以致出现<LOCKTABLEFULL>错误,也会发生此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字符串包括违背唯一性约束的字段和值。 例如<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+100或SET 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错误。