数据库
首页 > 数据库> > 第五十四章 SQL命令 INSERT(三)

第五十四章 SQL命令 INSERT(三)

作者:互联网

文章目录

第五十四章 SQL命令 INSERT(三)

SQLCODE错误

默认情况下,INSERT是要么全有要么全无的事件:要么完全插入行,要么根本不插入行。 IRIS返回一个状态变量SQLCODE,指示插入是成功还是失败。要将行插入到表中,插入操作必须满足所有表、字段名和字段值要求,如下所示。

表:

字段名称:

字段值:

如果定义了数据类型为ROWVERSION的字段,则在插入行时会自动为其分配系统生成的计数器值。尝试将值插入ROWVERSION字段会导致SQLCODE-138错误。

可以使IDENTITY字段接受用户指定的值。
通过设置SetOption(“IdentityInsert”)方法,您可以覆盖IDENTITY字段的默认约束,并允许将唯一整数值插入IDENTITY字段。
(可以通过调用GetOption(“IdentityInsert”)方法返回该约束的当前设置。)
插入IDENTITY字段值将更改IDENTITY计数器,以便后续系统生成的值从这个用户指定的值递增。
试图为IDENTITY字段插入NULL将产生SQLCODE -108错误。

IDKey数据有以下限制:
因为索引中的多个IDKey字段是用“||”(双竖条)字符分隔的,所以不能在IDKey字段数据中包含这个字符串。

插入不能包含值违反外键引用完整性的字段,除非指定了%NOCHECK关键字,或者外键是用NOCHECK关键字定义的。
否则,尝试违反外键引用完整性的插入将导致SQLCODE -121错误,并带有%msg,如下所示:<Table 'Sample.MyTable', Foreign Key Constraint 'MYTABLEFKey2', Field(s) FULLNAME failed referential integrity check>

插入操作

Privileges

要将一行或多行数据插入到表中,您必须拥有该表的表级特权或列级特权。

表级权限

如果用户是该表的Owner(创建者),则自动授予该用户对该表的所有特权。
否则,必须向用户授予该表的权限。
如果不这样做,将导致一个带有%msgSQLCODE -99错误。
可以通过调用%CHECKPRIV命令来确定当前用户是否具有适当的特权。
可以使用GRANT命令分配用户表权限。

要插入到分片表,您必须对目标表具有insert权限。
如果没有这些权限会出现SQLCODE -253错误:Sharded INSERT/UPDATE/DELETE run-time error

表级特权相当于(但不完全相同)在表的所有列上拥有列级特权。

列级权限

如果没有表级的INSERT权限,则必须对表中的至少一列具有列级的INSERT权限。
要将指定的值插入到列中,必须对该列具有列级insert权限。
只有具有INSERT权限的列才能接收INSERT命令中指定的值。

如果对指定的列没有列级INSERT权限, SQL将插入列的默认值(如果定义了)或NULL(如果没有定义默认值)。
如果对没有默认值且定义为not NULL的列没有INSERT权限, IRIS会在Prepare时间发出SQLCODE -99 (privilege Violation)错误。

如果INSERT命令指定结果集SELECTWHERE子句中的字段,则如果这些字段不是数据插入字段,则必须具有这些字段的SELECT权限,如果这些字段包含在结果集中,则必须具有这些字段的SELECTINSERT权限。

当属性被定义为ReadOnly时,相应的表字段也被定义为ReadOnly
只读字段只能使用InitialExpressionSqlComputed赋值。
尝试为具有列级ReadOnly (SELECT或REFERENCES)权限的字段插入值将导致SQLCODE -138错误:无法为只读字段插入/更新值。

可以使用%CHECKPRIV来确定是否具有适当的列级特权。

快速插入

当使用JDBC在表中插入行时 IRIS默认情况下会自动执行高效的Fast Insert操作。
Fast Insert将插入的数据的规范化和格式化从服务器转移到客户机。
然后,服务器可以直接将表的整行数据设置为全局数据,而无需对服务器进行操作。
这将这些任务从服务器转移到客户机上,可以显著提高INSERT性能。
由于客户端承担了格式化数据的任务,因此在客户端环境中可能会出现不可预见的使用量增加。
如果有问题,可以使用FeatureOption属性禁用快速插入。

服务器和客户端都必须支持快速插入。
要在客户端中启用或禁用Fast Insert,请在类实例的定义中使用FeatureOption属性,如下所示:

Properties p = new Properties();
p.setProperty("FeatureOption","3");   / 2 is fast Insert, 1 is fast Select, 3 is both

如果Fast Insert是活动的,则使用缓存查询执行的Insert将使用Fast Insert执行。
生成缓存查询的初始INSERT不是使用Fast INSERT执行的。
这使能够比较初始插入与使用缓存查询执行的后续Fast Inserts的性能。
如果不支持快速插入(出于以下原因),则执行普通插入。

快速插入必须在表上执行。
不能在可更新视图上执行。
当表具有以下任何特征时,不执行快速插入:

如果Insert语句具有以下特征之一,则不能执行快速插入:

对于SQL xDBC语句审计事件,使用Fast INSERT接口的INSERT语句具有SQL fastINSERT语句的描述。
如果使用Fast Insert接口,则Audit事件不包括任何参数数据,但包括消息参数值对于fastInsert语句不可用。

参照完整性

如果没有指定%NOCHECK关键字, IRIS将使用系统范围的配置设置来确定是否执行外键引用完整性检查;
默认值是执行外键引用完整性检查。
您可以在系统范围内设置此默认值,如外键引用完整性检查中所述。
要确定当前系统范围的设置,调用$SYSTEM.SQL.CurrentSettings()

此设置不适用于用NOCHECK关键字定义的外键。

在INSERT操作期间,对于每个外键引用,都会在引用表中相应的行上获得一个共享锁。
在执行引用完整性检查和插入该行时,此行被锁定。
然后释放锁(直到事务结束才持有锁)。
这确保了引用的行不会在引用完整性检查和插入操作完成之间发生更改。

但是,如果指定了%NOLOCK关键字,则不会对指定的表或引用表中相应的外键行执行锁操作。

子表插入

在对子表执行INSERT操作期间,父表中相应行的共享锁将被获取。
在插入子表行时,此行被锁定。
然后释放锁(直到事务结束才持有锁)。
这确保在插入操作期间不会更改引用的父行。

原子性

默认情况下,INSERTUPDATEDELETETRUNCATE TABLE是原子操作。
INSERT要么成功完成,要么回滚整个操作。
如果不能插入任何指定的行,则不插入任何指定的行,并且数据库恢复到发出INSERT之前的状态。

可以通过调用SET TRANSACTION %COMMITMODE来修改SQL中当前进程的这个默认值。
可以通过调用SetOption()方法在ObjectScript中修改当前进程的这个默认值,如下SET status=$SYSTEM.SQL.Util.SetOption("AutoCommit",intval,.oldval)
以下intval整数选项是可用的:

分片表始终没有自动事务模式,这意味着对分片表的所有插入、更新和删除都是在事务范围之外执行的。

可以使用GetOption(“AutoCommit”)方法确定当前进程的原子性设置,如下面的ObjectScript示例所示:

ClassMethod Insert1()
{
	s stat = $SYSTEM.SQL.SetOption("AutoCommit",$RANDOM(3),.oldval)
	if stat '= 1 {
		w "SetOption 失败:" 
		d $System.Status.DisplayError(stat) 
		q
	}
	s x = $SYSTEM.SQL.GetOption("AutoCommit")
	if x = 1 {
		w "默认的原子性行为r",!
		w "自动提交或回滚" 
	} elseif x = 0 {
		w "没有启动事务,就没有原子性:",!
		w "DELETE失败会导致数据库不一致",!
		w "不支持回滚" 
	} else { 
		w "需要显式提交或回滚" 
	}
}

事务锁

如果没有指定%NOLOCK关键字,系统将自动对INSERTUPDATEDELETE操作执行标准的记录锁定。
在当前事务期间,每个受影响的记录(行)都被锁定。

默认的锁阈值是每个表1000个锁。
这意味着,如果在事务期间从表中插入超过1000条记录,就会达到锁阈值 IRIS会自动将锁级别从记录锁升级为表锁。
这允许在事务期间进行大规模插入,而不会溢出锁表。

IRIS应用以下两种锁升级策略之一:

对于这两种锁升级策略,您可以使用$SYSTEM.SQL.Util.GetOption(“LockThreshold”)方法确定当前系统范围的锁阈值。
默认值是1000
这个系统范围的锁阈值是可配置的:

需要在“%Admin Manage Resource”中具有“USE”权限才能修改锁定阈值。
IRIS会立即将对锁阈值的任何更改应用到所有当前进程。

自动锁升级的潜在后果是,当试图升级到表锁的进程与持有该表中记录锁的另一个进程冲突时,可能发生死锁情况。
有几种可能的策略可以避免这种情况:(1)增加锁升级阈值,以便锁升级不太可能在事务中发生。
(2)大幅降低锁升级阈值,以便锁升级几乎立即发生,从而减少其他进程锁定同一表中的记录的机会。
(3)在事务期间应用表锁,不执行记录锁。
这可以在事务开始时指定LOCK TABLE,然后指定UNLOCK TABLE(不带IMMEDIATE关键字,以便表锁一直持续到事务结束),然后使用%NOLOCK选项执行插入操作。

自动锁升级旨在防止锁表溢出。
但是,如果执行大量插入操作导致出现<LOCKTABLEFULL>错误,INSERT将发出SQLCODE -110错误。

行级安全性

IRIS行级安全性允许INSERT添加行,即使定义了行安全性,也不允许随后访问该行。为确保INSERT不会阻止随后对该行进行SELECT访问,建议通过具有WITH CHECK选项的视图执行INSERT

Microsoft Access

要使用INSERT通过Microsoft Access将数据添加到 IRIS表格中,请将表格RowID字段标记为专用,或者在一个或多个附加字段上定义唯一索引。

标签:INSERT,错误,指定,插入,字段,SQLCODE,SQL,第五十四章
来源: https://blog.csdn.net/yaoxin521123/article/details/120929811