适用于: SQL Server
Azure SQL 数据库
与其他数据库更新机制一样,updategram 必须处理多用户环境下对数据的并发更新。 Updategram 使用乐观并发控制,该模式将选择字段数据与快照进行比较,以确保要更新的数据自从在数据库中读取后,其他用户应用程序未更改过该数据。 Updategram 在 updategram 块之前>包含这些快照值<。 在更新数据库之前,updategram 会根据数据库中当前的值检查在之前>块中指定的<值,以确保更新有效。
乐观并发控制在 updategram 中提供三种保护级别:低(无)、中间和高。 通过相应指定 updategram,可以确定需要的保护级别。
最低保护级别
此级别为盲目更新,它不参照自上次读取数据库后已进行的其他更新来处理更新。 在这种情况下,只需在块前><指定主键列来标识记录,并在后>块中<指定更新的信息。
例如,无论以前的电话号码是什么,以下 updategram 中的新联系人电话号码都是正确的。 请注意之前>块如何<仅指定主键列 (ContactID)。
<ROOT xmlns:updg="urn:schemas-microsoft-com:xml-updategram">
<updg:sync >
<updg:before>
<Person.Contact ContactID="1" />
</updg:before>
<updg:after>
<Person.Contact ContactID="1" Phone="111-111-1111" />
</updg:after>
</updg:sync>
</ROOT>
中间保护级别
在此保护级别中,updategram 将要更新的数据的当前值与数据库列中的值进行比较,以确保自您的事务读取记录后,这(个)些值未被任何其他事务更改过。
可以通过指定在块中<>更新的主键列和列(s)来获取此级别的保护。
例如,此 updategram 为 ContactID 是 1 的联系人更新 Person.Contact 表的 Phone 列中的值。 <before> 块指定 Phone 属性,以确保在应用更新的值之前,此属性值与数据库中相应列中的值匹配。
<ROOT xmlns:updg="urn:schemas-microsoft-com:xml-updategram">
<updg:sync >
<updg:before>
<Person.Contact ContactID="1" Phone="398-555-0132" />
</updg:before>
<updg:after>
<Person.Contact ContactID="1" Phone="111-111-1111" />
</updg:after>
</updg:sync>
</ROOT>
高保护级别
高保护级别确保自您的应用程序上次读取该记录后该记录没有变化(即自您的应用程序读取记录后,该记录未被任何其他事务更改过)。
可以通过两种方法实现针对并发更新的此类高保护级别:
在块前<>的表中指定其他列。
如果在前>块中<指定其他列,updategram 会将为这些列指定的值与应用更新之前数据库中的值进行比较。 如果自您的事务读取记录后有记录列被更改过,updategram 将不执行更新。
例如,以下 updategram 更新班次名称,但在块前>指定其他列(StartTime,EndTime),<从而请求对并发更新的更高级别的保护。
<ROOT xmlns:updg="urn:schemas-microsoft-com:xml-updategram"> <updg:sync > <updg:before> <HumanResources.Shift ShiftID="1" Name="Day" StartTime="1900-01-01 07:00:00.000" EndTime="1900-01-01 15:00:00.000" /> </updg:before> <updg:after> <HumanResources.Shift Name="Morning" /> </updg:after> </updg:sync> </ROOT>
此示例通过指定前>块中<记录的所有列值来指定最高级别的保护。
在块前<>指定时间戳列(如果可用)。
可以指定时间戳列(如果表有一个),而不是指定前>块中的所有记录列<以及前>一个块中的<主键列。 在每次更新记录后,数据库将时间戳列更新为唯一值。 在这种情况下,updategram 将时间戳的值与数据库中的相应值进行比较。 在数据库中存储的时间戳值为二进制值。 因此,时间戳列必须在架构中指定为 dt:type=“bin.hex”,dt:type=“bin.base64”或 sql:datatype=“timestamp”。 (可以指定 xml 数据类型或Microsoft SQL Server 数据类型。
测试 updategram
在 tempdb 数据库中创建此表:
USE tempdb CREATE TABLE Customer ( CustomerID varchar(5), ContactName varchar(20), LastUpdated timestamp)
添加此示例记录:
INSERT INTO Customer (CustomerID, ContactName) VALUES ('C1', 'Andrew Fuller')
复制以下 XSD 架构并将其粘贴到记事本中。 将其另存为 ConcurrencySampleSchema.xml:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sql="urn:schemas-microsoft-com:mapping-schema"> <xsd:element name="Customer" sql:relation="Customer" > <xsd:complexType> <xsd:attribute name="CustomerID" sql:field="CustomerID" type="xsd:string" /> <xsd:attribute name="ContactName" sql:field="ContactName" type="xsd:string" /> <xsd:attribute name="LastUpdated" sql:field="LastUpdated" type="xsd:hexBinary" sql:datatype="timestamp" /> </xsd:complexType> </xsd:element> </xsd:schema>
将以下 updategram 代码复制到记事本中,然后在保存上一步中创建的架构的相同目录中将其保存为 ConcurrencySampleTemplate.xml。 (请注意下面 LastUpdated 的时间戳值将不同于示例 Customer 表中的值,因此从表中复制 LastUpdated 的实际值并将其粘贴到 updategram。)
<ROOT xmlns:updg="urn:schemas-microsoft-com:xml-updategram"> <updg:sync mapping-schema="SampleSchema.xml" > <updg:before> <Customer CustomerID="C1" LastUpdated = "0x00000000000007D1" /> </updg:before> <updg:after> <Customer ContactName="Robert King" /> </updg:after> </updg:sync> </ROOT>
创建并使用 SQLXML 4.0 测试脚本 (Sqlxml4test.vbs) 执行该模板。
有关详细信息,请参阅使用 ADO 执行 SQLXML 4.0 查询。
这是等效的 XDR 架构:
<?xml version="1.0" ?>
<Schema xmlns="urn:schemas-microsoft-com:xml-data"
xmlns:dt="urn:schemas-microsoft-com:datatypes"
xmlns:sql="urn:schemas-microsoft-com:xml-sql">
<ElementType name="Customer" sql:relation="Customer" >
<AttributeType name="CustomerID" />
<AttributeType name="ContactName" />
<AttributeType name="LastUpdated" dt:type="bin.hex"
sql:datatype="timestamp" />
<attribute type="CustomerID" />
<attribute type="ContactName" />
<attribute type="LastUpdated" />
</ElementType>
</Schema>