㈠ 如何使用sqlserver 2012 Always on技术
一、启用FileTable1、修改数据库引擎的属性打开“SQLServer配置管理器”,修改SQLServer数据库引擎的属性。使用此页可针对此MicrosoftSQLServer2012安装启用FILESTREAM。(1)针对Transact-SQL访问启用FILESTREAM选中此项可针对Transact-SQL访问启用FILESTREAM。必须选中此控制选项,才能使用其他控制选项。如果不启用此选项,就不能添加FileStream文件组。(2)针对文件I/O流访问启用FILESTREAM选中此项可针对FILESTREAM启用Win32流访问。(3)Windows共享名使用此控制选项可输入将用来存储FILESTREAM数据的Windows共享的名称。默认为该SQLServer实例的名称。(4)允许远程客户端针对FILESTREAM数据启用流访问选中此控制选项可允许远程客户端访问此服务器上的此FILESTREAM数据。2、修改服务器的属性打开“SQLServerManagementStudio”,修改该实例的配置。默认配置如下:上述选项解释如下:(1)“FILESTREAM访问级别”显示SQLServer实例上支持的FILESTREAM的当前级别。若要更改访问级别,请选择以下值之一:已禁用无法将二进制大型对象(BLOB)数据存储在文件系统中。此为默认值。即filestreamaccesslevel=0已启用Transact-SQL访问可使用Transact-SQL访问FILESTREAM数据,但不能通过文件系统进行访问。即filestreamaccesslevel=1已启用完全访问FILESTREAM数据可使用Transact-SQL以及通过文件系统进行访问。即filestreamaccesslevel=0注意:在首次启用FILESTREAM时,您可能需要重新启动计算机才能配置驱动程序。(2)“FILESTREAM共享名称”显示在安装过程中选择的FILESTREAM共享的只读名称。在本次实验中,我们将“FILESTREAM访问级别”设定为:已启用完全访问。如果是通过T-SQL脚本执行,则运行以下脚本:EXECsys.sp_configureN'filestreamaccesslevel',N'2'RECONFIGUREWITHOVERRIDE注意:设置完成之后,重启实例。3、配置防火墙若要在防火墙保护的环境中使用FILESTREAM,客户端和服务器都必须能够将DNS名称解析为包含FILESTREAM文件的服务器。FILESTREAM要求Windows文件共享端口139和445处于打开状态。二、配置文件组1、添加文件组完成上述操作之后,就可以为该数据库添加专用于FileStream的文件组。如果是通过脚本操作,请运行以下脚本:ALTERDATABASE[db01]ADDFILEGROUP[FileStreamFileGroup]CONTAINSFILESTREAM2、添加文件完成上述操作之后,就可以为该数据库添加FilStream类型的数据库文件。在本例中,系统并没有为“FileStream数据”的文件类型创建mdf或ndf文件,而是在文件夹C:\SqlData下面自动创建以逻辑名称命名的文件夹,即C:\SqlData\FileData。其中filestream.hdr文件是FILESTREAM容器的头文件。当这个数据库被删除时,mdf、ndf、log连同这个文件夹都会被删除。如果是通过脚本操作,请运行以下脚本:ALTERDATABASE[db01]ADDFILE(NAME=N'FileData',FILENAME=N'C:\SqlData\FileData')TOFILEGROUP[FileStreamFileGroup]注意:在上例中,在运行脚本之前,必须存在C:\SqlData,建议使用右侧的选择按钮选择路径。如果路径不存在,就会报错:同时不能存在重复的文件夹,即不能存在C:\SqlData\FileData。否则也会报错:3、启动非事务访问FileTable使Windows应用程序可以获取FILESTREAM数据的Windows文件句柄而不需要SQLServer事务。为了允许对SQLServer中存储的文件进行此非事务性访问,必须为要包含FileTable的每个数据库在数据库级别上指定所需的非事务性访问级别。选项解释如下:(1)FILESTREAM非事务访问为从文件系统到FileTables中存储的FILESTREAM数据的非事务性访问指定以下选项之一:OFF、READ_ONLY或FULL。如果在服务器上未启用FILESTREAM,则该值将设置为OFF并且被禁用。在本次实验中,将其设置为FULL。(2)FILESTREAM目录名称为与所选数据库相关联的FILESTREAM数据指定目录名称。在FileTable文件夹层次结构中,此数据库级目录将成为在实例级别为FILESTREAM指定的共享名称的子级以及在数据库中创建的FileTable的父级。如果启用非事务性访问时没有提供目录名称,则在以后必须提供它,这样才能在数据库中创建FileTable。如果是通过脚本执行,如下:(NON_TRANSACTED_ACCESS=FULL,DIRECTORY_NAME=N'ImageFiles')注意:更改现有数据库时,调用带DIRECTORY_NAMEFILESTREAM选项的ALTERDATABASE(Transact-SQL)语句。使用这些选项更改目录名称时,数据库必须以独占方式锁定,没有打开的文件句柄。说明:为检查是否在数据库上启用了非事务性访问,可以查询目录视图,脚本如下:SELECTDB_NAME(database_id),non_transacted_access,non_transacted_access_descFROMsys.database_filestream_options三、创建FileTable1、创建第一个FileTable“SQLServerManagementStudio”只提供一个脚本模板,要想创建FileTable还是得用脚本完成:官方的范本为:USE[db01]CREATETABLE[dbo].[ImageTable1]ASFILETABLEON[PRIMARY]FILESTREAM_ON[FileStreamFileGroup]WITH(FILETABLE_DIRECTORY=N'ImageTable1',FILETABLE_COLLATE_FILENAME=Chinese_PRC_CI_AS)2、创建第二个、获取共享路径文件表创建之后,就会相应的产生一个文件表共享目录,该目录路径可以通过内建函数获取:SELECTFileTableRootPath('ImageTable1')本次实验所返回的结果为:\\SQL1\SqlFile\ImageFiles\ImageTable14、查看通过Windows资源管理器,可见已经创建了以GUID命名的文件夹。通过SQLServerManagementStudio,查看表的结构。四、操作1、向文件夹中添加文件通过“Windows资源管理器”,向文件夹\\SQL1\SqlFile\ImageFiles\ImageTable1中添加一个文件A01.GIF。然后运行脚本:select*fromImageTable1结果如下:可见,SQLServer自动在Table中添加了记录。2、文件改名运行以下脚本:updateImageTable1setname='Cup.GIF'wherename='A01.GIF'通过“Windows资源管理器”,查看文件夹\\SQL1\SqlFile\ImageFiles\ImageTable1,可见文件A01.GIF已经被改名为Cup.GIF。3、查看共享文件夹我们可以继续复制其他文件,然后通过“Windows资源管理器”,查看文件夹。4、删除文件可以使用脚本删除,例如:DeleteImageTable1wherename='Cup.GIF'或者,通过“Windows资源管理器”直接删除该文件。五、备份和还原1、备份数据库使用SQLServer备份数据库时,FILESTREAM数据将与数据库中的结构化数据一起备份。2、部分备份如果不想将FILESTREAM数据与关系数据一起备份,则可以使用部分备份将FILESTREAM文件组排除在外。六、相关说明详见/zh-cn/library/gg492086.aspx1、AlwaysOn在包含FILESTREAM或FileTable数据的数据库属于某一AlwaysOn可用性组时:FILESTREAM和FileTable函数接受或返回虚拟网络名称(VNN),而非计算机名称。有关这些函数的详细信息,请参阅Filestream和FileTable函数(Transact-SQL)。通过文件系统API对FILESTREAM或FileTable数据进行的所有访问都应该使用VNN,而非计算机名称。2、表分区FileTable不支持分区。通过对多个FILESTREAM文件组的支持,在大多数方案中可以解决纯向上扩展问题,而不必使用分区(不像SQL2008FILESTREAM)。3、复制FileTable不支持复制和相关功能(包括事务性复制、合并复制、更改数据捕获和更改跟踪)。4、视图可以像为任何其他表一样为FileTable创建视图。但是对于为FileTable创建的视图有以下注意事项:视图将不具有任何FileTable语义,也就是说,视图中的列(包括“文件属性”列)的行为与常规视图列一样,不具有任何特殊语义,对于表示文件/目录的行也是如此。可以基于“可更新视图”语义更新视图,但是基础表约束可能拒绝更新,就像在表中一样。可以通过将文件的路径添加为视图中的显式列,在视图中显示该路径。例如:,column2,…,GetFileNamespacePath()ASPATH,column3,…FROMDocuments
㈡ sql数据库怎么跟踪密码登录错误的进程
首先禁用服务器密码策略
使用sa账户登录SQL server,打开安全性-登录名-右键-输入登录名test,选择SQL server身份验证,输入密码“123”(此时勾选了强制实时密码策略),点击确定
可成功创建了test账户,并且设置了弱口令“123”,然后右键test账户看一下属性。
下图中显示test账户勾选了强制实施密码策略,密码位置:显示15个圈,是看不出弱口令的。
用弱口令登录test账户也是没有问题的
然后开启服务器密码策略,使用管理员sa新建一个弱口令账户
依然使用sa账户登录SQL server,打开安全性-登录名-右键-输入登录名test1,选择SQL server身份验证,输入密码“123”(此时勾选了强制实施密码策略),点击确定
此时数据库报错提示“密码有效性验证失败,该密码不够复杂,不符合Windows策略要求”,证明了开启服务器密码策略并勾选账户强制实施密码策略,是有效果的。
但我看了一下Windows操作系统的密码策略也是挺下饭-..-最少六个字符长!!
就是说即使开了密码策略,还可以将密码设置为Qwe!23的六位数
如果想要设置密码最小长度的话,在服务器密码策略上修改就可以了
最后试一下开启Windows操作系统密码策略,不勾选数据库账户的强制实施密码策略,看看能不能,设置弱口令
果然结果是可以的。
总结一下就是SQL server密码策略要同时满足开启Windows密码策略并且勾选SQL server账户的强制实施密码策略才算是符合,但即使这样的话一样可以设置6位长度的口令,所以还要设置服务器的密码最小长度值。
㈢ oracle跟踪表结构,查看哪些表被更新的SQL
我首先想到的是触发器(after类型),不过细琢磨了一下,似乎不那么靠谱,如果你要关注的表有几百张,那么难道建立几百个出发器么?
可能,仅仅是可能啊,这个不常用,因为比较消耗资源,你试试oracle的审计功能,大概这个能实现你的要求。不过我用审计的次数有限,而且也没这么大规模的应用过,所以这部分只能你自己查了。
㈣ sql server:如何设置自动执行的存储过程
--方法1:作业里定时执行存储过程定时作业的制定 企业管理器 --管理 --SQL Server代理 --右键作业 --新建作业 --"常规"项中输入作业名称 --"步骤"项 --新建 --"步骤名"中输入步骤名 --"类型"中选择"Transact-SQL 脚本(TSQL)" --"数据库"选择执行命令的数据库 --"命令"中输入要执行的语句: EXEC 存储过程名 ... --该存储过程用于创建表 --确定 --"调度"项 --新建调度 --"名称"中输入调度名称 --"调度类型"中选择你的作业执行安排 --如果选择"反复出现" --点"更改"来设置你的时间安排 然后将SQL Agent服务启动,并设置为自动启动,否则你的作业不会被执行 设置方法: 我的电脑--控制面板--管理工具--服务--右键 SQLSERVERAGENT--属性--启动类型--选择"自动启动"--确定. --方法2:将存储过程创建在master数据库中,然后企业管理器中找到这个存储过程--右键--属性--勾选"每当sql server启动时执行"。 或在master中创建存储过程后,执行语句配置为自动启动 use master exec sp_procoption '存储过程名','startup','on' 自动执行存储过程 SQL Server 启动时能够自动执行一个或多个存储过程。这些存储过程必须由系统管理员创建,并在 sysadmin 固定服务器角色下作为后台过程执行。这些过程不能有任何输入参数。 对启动过程的数目没有限制,但是要注意,每个启动过程在执行时都会占用一个连接。假如必须在启动时执行多个过程,但无需并行执行,则能够指定一个过程作为启动过程,让该过程调用其他过程。这样就只占用一个连接。 在启动时恢复了最后一个数据库后,即开始执行存储过程。若要跳过这些存储过程的执行,请将启动参数指定为跟踪标记 4022。假如以最低配置启动 SQL Server(使用 -f 标记),则启动存储过程也不会执行。有关更多信息,请参见跟踪标记。 若要创建启动存储过程,必须作为 sysadmin 固定服务器角色的成员登录,并在 master 数据库中创建存储过程。 使用 sp_procoption 能够: 将现有存储过程指定为启动过程。
㈤ 如何使用 SQL Server 变更跟踪
如果服务器正在运行 SQL Server 2008,则建议您使用 SQL Server 变更跟踪。如果服务器运行的是其他数据库,请参见如何使用自定义变更跟踪系统。SQL Server 变更跟踪概述本文档中的许多示例都使用一组添加到基表中的列和触发器来处理变更跟踪,使用其他表来跟踪删除操作。有关更多信息,请参见跟踪服务器数据库中的变更。这种类型的跟踪对于非 SQL Server 2008 数据库非常有用。但是,它还是具有以下缺点:在服务器数据库中要求架构变更。架构变更可能会影响虚蠢虚其他应用程序,或者可能根本无法实现。对一行中执行的每个变更都会激发触发器。这会影响性能。用于维护正确的行版本和删除的逻辑将变得复杂。如果某一服务器数据库具有长时间运行的事务,则除非这些事务得到正确处理,否则,在同步期间可能会失去数据变更。这可能导致数据不一致。 SQL Server 变更跟踪可解决这些问题,并提供一种简明的方法来跟踪变更。当对某一表启用了变更跟踪时,SQL Server 数据库引擎 将维护有关对表所做变更的信息。然后,应用程序使用相应变更跟踪函数来确定哪些行发生了变更并获取有关这些变更的信息。SQL Server 变更跟踪的主要优点差燃如下:对于使用 Sync Services 的脱机同步方案,您不必创建触发器、时间戳列、其他附加列或附加表。在提交时跟踪变更,而不是在发生 DML 操作时跟踪。函数将返回对表所做的增量变更和版本信息。即使档樱存在重叠和未提交的事务,这些函数也能提供可靠且易于使用的结果。对性能的影响非常小。可以自动清除变更跟踪数据。本主题的其余部分将演示如何在 Sync Services for ADO.NET 应用程序中使用 SQL Server 变更跟踪。有关变更跟踪的更多信息,请参见 SQL Server 2008 联机丛书。将SQL Server 变更跟踪与 Sync Services for ADO.NET 一起使用本节介绍如何启用变更跟踪,以及如何使用变更跟踪查询来确定要下载到客户端的数据变更。本节中的信息介绍如何使用手动创建的命令选择来自服务器的变更。有关如何使用同步适配器生成器为您创建命令的信息,请参见入门:客户端与服务器同步。启用SQL Server 变更跟踪对服务器数据库启用变更跟踪,然后对每个需要跟踪的表启用变更跟踪。下面的代码示例演示一个 Sync Services 示例数据库中的 Sales.Customer 表的架构以及为该表启用变更跟踪所需的代码。每个表都必须有一个主键。主键在所有节点上必须是唯一的,而且不得重复使用:即使删除了某一行,也不得将该行的主键用于其他行。对于分布式环境,标识列通常不是适宜的选择。有关主键的更多信息,请参见为分布式环境选择适宜的主键 (Sync Services)。通过运行以下代码指定的变更跟踪选项包括保留跟踪元数据的时间以及是否自动清除这些元数据。有关跟踪选项的更多信息,请参见 SQL Server 2008 联机丛书中的“变更跟踪”、“ALTER DATABASE”和“ALTER TABLE”主题。 CREATE TABLE SyncSamplesDb_ChangeTracking.Sales.Customer( CustomerId uniqueidentifier NOT NULL PRIMARY KEY DEFAULT NEWID(), CustomerName nvarchar(100) NOT NULL, SalesPerson nvarchar(100) NOT NULL, CustomerType nvarchar(100) NOT NULL) ALTER DATABASE SyncSamplesDb_ChangeTracking SET ALLOW_SNAPSHOT_ISOLATION ON ALTER DATABASE SyncSamplesDb_ChangeTracking SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON) ALTER TABLE SyncSamplesDb_ChangeTracking.Sales.Customer ENABLE CHANGE_TRACKING 注意强烈建议您在查询变更信息时使用快照事务。这有助于确保变更信息的一致性并避免出现与后台清除任务相关的争用情况。有关快照隔离的更多信息,请参见 SQL Server 2008 联机丛书中的“数据库引擎中的隔离级别”。确定要下载到客户端的数据变更启用变更跟踪后,Sync Services 应用程序使用变更跟踪函数和“定位点”来确定要下载的插入、更新和删除。定位点仅仅是用来定义一组要同步的变更的一个时间点。请考虑以下查询:为 属性指定的查询。以下查询从服务器上的 Sales.Customer 表选择要应用于客户端的增量插入: IF @sync_initialized = 0 SELECT Sales.Customer.[CustomerId], [CustomerName], [SalesPerson], [CustomerType] FROM Sales.Customer LEFT OUTER JOIN CHANGETABLE(CHANGES Sales.Customer, @sync_last_received_anchor) CT ON CT.[CustomerId] = Sales.Customer.[CustomerId] ELSE BEGIN SELECT Sales.Customer.[CustomerId], [CustomerName], [SalesPerson], [CustomerType] FROM Sales.Customer JOIN CHANGETABLE(CHANGES Sales.Customer, @sync_last_received_anchor) CT ON CT.[CustomerId] = Sales.Customer.[CustomerId] WHERE (CT.SYS_CHANGE_OPERATION = 'I' AND CT.SYS_CHANGE_CREATION_VERSION <= @sync_new_received_anchor) END 如果这是某个客户端的第一个同步会话 (@sync_initialized = 0),则会从 Sales.Customer 基表直接选择架构和所有行。在以后的同步期间,通过执行基表与其变更跟踪表的内部联接来选择新插入的行。变更跟踪表中的元数据由 CHANGETABLE() 函数公开。该函数将基表名称和前一同步操作所存储的变更跟踪版本作为参数。SYS_CHANGE_OPERATION 列定义存储在变更跟踪表行中的变更的类型。注意查询还应检查所需的所有变更是否都已从跟踪表中清除。有关示例,请参见本主题后面的“指定一条从服务器上选择要应用于客户端的增量插入的命令”。为SelectNewAnchorCommand 属性指定的查询。此查询检索一个时间点值。以下查询通过使用 change_tracking_current_version() 函数从服务器中检索新的定位点值。这一内置的 SQL Server 函数返回一个版本整数,它与通过变更跟踪进行跟踪的上次提交的事务相关联。 SELECT @sync_new_received_anchor = change_tracking_current_version() 该整数值存储在客户端数据库中,并且由同步变更的命令使用。在每次同步会话期间,将使用新的定位点值以及来自先前同步会话的上一个定位点值:这意味着将对在这两个作为上下限的定位点值之间做出的变更集进行同步。在某些情况下,应用程序只要求每个客户端上的一部分数据。可以在 WHERE 子句中包括附加的条件,以便筛选数据。有关更多信息,请参见如何筛选行和列。“基于非键列的筛选器”一节中包括与使用 SQL Server 变更跟踪进行筛选有关的重要信息。在同步过程中执行的查询如果是首次同步 Sales.Customer 表,则会执行以下过程:执行新的定位点命令。该命令返回一个整数值,如 372。此值存储在客户端数据库中。该表从未进行过同步。因此,客户端数据库中原本没有存储任何从先前同步操作所得到的定位点值。在这种情况下,Sync Services 使用值 0。Sync Services 执行的查询如下所示: exec sp_executesql N'IF @sync_initialized = 0 SELECT Sales.Customer.[CustomerId], [CustomerName], [SalesPerson], [CustomerType] FROM Sales.Customer LEFT OUTER JOIN CHANGETABLE(CHANGES Sales.Customer, @sync_last_received_anchor) CT ON CT.[CustomerId] = Sales.Customer.[CustomerId] ELSE BEGIN SELECT Sales.Customer.[CustomerId], [CustomerName], [SalesPerson], [CustomerType] FROM Sales.Customer JOIN CHANGETABLE(CHANGES Sales.Customer, @sync_last_received_anchor) CT ON CT.[CustomerId] = Sales.Customer.[CustomerId] WHERE (CT.SYS_CHANGE_OPERATION = ''I'' AND CT.SYS_CHANGE_CREATION_VERSION <= @sync_new_received_anchor) END', N'@sync_initialized int, @sync_last_received_anchor bigint, @sync_new_received_anchor bigint', @sync_initialized=0, @sync_last_received_anchor=0, @sync_new_received_anchor=372 在第二次同步会话期间,执行新的定位点命令。自上一会话以来已经插入了一些行。因此,该命令返回值 375。该表以前已进行过同步。因此,Sync Services 可检索先前同步操作所得到的客户端数据库中存储的 372 的定位点值。执行的查询如下所示。该查询只从表中下载在两个定位点值之间插入的行。 exec sp_executesql N'IF @sync_initialized = 0 SELECT Sales.Customer.[CustomerId], [CustomerName], [SalesPerson], [CustomerType] FROM Sales.Customer LEFT OUTER JOIN CHANGETABLE(CHANGES Sales.Customer, @sync_last_received_anchor) CT ON CT.[CustomerId] = Sales.Customer.[CustomerId] ELSE BEGIN SELECT Sales.Customer.[CustomerId], [CustomerName], [SalesPerson], [CustomerType] FROM Sales.Customer JOIN CHANGETABLE(CHANGES Sales.Customer, @sync_last_received_anchor) CT ON CT.[CustomerId] = Sales.Customer.[CustomerId] WHERE (CT.SYS_CHANGE_OPERATION = ''I'' AND CT.SYS_CHANGE_CREATION_VERSION <= @sync_new_received_anchor) END', N'@sync_initialized int, @sync_last_received_anchor bigint, @sync_new_received_anchor bigint', @sync_initialized=1, @sync_last_received_anchor=372, @sync_new_received_anchor=375 有关更新和删除命令的示例,请参见本主题后面的完整代码示例。标识执行数据变更的客户端之所以要标识执行数据变更的客户端,主要有两个原因:在仅进行上载的同步和双向同步中为冲突检测和冲突解决提供支持。如果服务器和某个客户端(或多个客户端)可以变更某个给定行,您可能希望标识出变更的执行者。此信息有助于您编写代码,例如,编写确定哪一个变更具有更高的优先级的代码。如果没有此信息,将保留对该行的最近一次变更。在双向同步期间,防止将变更回送给客户端。 Sync Services 首先将变更上载到服务器,然后将变更下载到客户端。如果不跟踪执行变更的客户端的标识,该变更将上载到服务器,然后在同一个同步会话中下载回到该客户端。某些情况下,回送变更是必需的,但是在另一些情况下并非如此。变更跟踪提供一个机制,可以将应用程序数据与变更行时的变更信息一起存储。这些应用程序数据可用于标识正在进行变更的客户端。然后,在您查询变更时可返回进行了变更的客户端的这一标识。SYS_CHANGE_CONTEXT 列可与 ClientId 属性一起使用,以确定每个插入、更新或删除操作是由哪个客户端执行的。在任何表使用除快照同步以外的方法进行第一次同步时,Sync Services 会在客户端上存储一个 GUID 值以标识该客户端。然后将此 ID 传递给 DbServerSyncProvider,以便能够由每个 SyncAdapter 对象的命令使用。可以通过 ClientId 属性以及 @sync_client_id 和@sync_client_id_binary 会话变量获得该 ID 值。请考虑以下 Transact-SQL 查询: IF @sync_initialized = 0 SELECT Sales.Customer.[CustomerId], [CustomerName], [SalesPerson], [CustomerType] FROM Sales.Customer LEFT OUTER JOIN CHANGETABLE(CHANGES Sales.Customer, @sync_last_received_anchor) CT ON CT.[CustomerId] = Sales.Customer.[CustomerId] WHERE (CT.SYS_CHANGE_CONTEXT IS NULL OR CT.SYS_CHANGE_CONTEXT <> @sync_client_id_binary) ELSE BEGIN SELECT Sales.Customer.[CustomerId], [CustomerName], [SalesPerson], [CustomerType] FROM Sales.Customer JOIN CHANGETABLE(CHANGES Sales.Customer, @sync_last_received_anchor) CT ON CT.[CustomerId] = Sales.Customer.[CustomerId] WHERE (CT.SYS_CHANGE_OPERATION = 'I' AND CT.SYS_CHANGE_CREATION_VERSION <= @sync_new_received_anchor AND (CT.SYS_CHANGE_CONTEXT IS NULL OR CT.SYS_CHANGE_CONTEXT <> @sync_client_id_binary)); 此查询类似于前面用来跟踪在服务器上所做插入操作的查询。每个 WHERE 子句中的附加语句可确保只下载那些不是由当前进行同步的客户端所做的插入。Sync Services 还允许应用程序通过在服务器上使用一个整数而不是 GUID 值来标识客户端。有关更多信息,请参见如何使用会话变量。若要跟踪哪一客户端进行了在服务器上应用的数据变更,请使用 WITH CHANGE_TRACKING_CONTEXT 子句。在执行 INSERT、UPDATE 或 DELETE 语句前,将 CHANGE_TRACKING_CONTEXT 设置为 @sync_client_id 或@sync_client_id_binary 会话变量的值。此信息存储在变更跟踪表中,以便应用程序可以跟踪变更所处的上下文。对于 Sync Services 来说,这通常是客户端 ID;但是,您可以存储适合 varbinary(128) 列的任何值。 WITH CHANGE_TRACKING_CONTEXT (@sync_client_id_binary) INSERT INTO Sales.Customer (CustomerId, CustomerName, SalesPerson, CustomerType) VALUES (@CustomerId, @CustomerName, @SalesPerson, @CustomerType) SET @sync_row_count = @@rowcount 了解和运行示例应用程序本节包含配置和执行同步所需的应用程序代码。只通过阅读示例代码,就可以学习到很多相关知识。但是,运行示例并查看其运行情况则更加直观。在运行代码前,请确保安装了以下产品: Sync Services 该应用程序需要参考 Microsoft.Synchronization.Data.dll、Microsoft.Synchronization.dll、Microsoft.Synchronization.Data.Server.dll 和 Microsoft.Synchronization.Data.SqlServerCe.dll。 SQL Server 2008 示例代码在连接字符串中使用 localhost。若要使用远程服务器,请将 localhost 变更为适当的服务器名称。Sync Services 示例数据库。有关更多信息,请参见用于Sync Services 帮助主题的安装脚本。如果您曾经阅读过用于客户端与服务器同步的体系结构和类主题,应该已经对该应用程序中使用的主要类有所了解。该应用程序由以下类组成:SampleSyncAgent此类派生自 SyncAgent。SampleServerSyncProvider。此类派生自 DbServerSyncProvider 并包含 SyncAdapter 和一组查询变更跟踪表的命令。SampleClientSyncProvider此类派生自 SqlCeClientSyncProvider 并包含 SyncTable。SampleStats此类使用 SyncAgent 返回的统计信息。Program。此类设置同步并调用 Utility 类的方法。Utility. 此类负责处理所有不与同步直接相关的功能,例如保存连接字符串信息以及更改服务器和客户端数据库等。有关更多信息,请参见 用于Sync Services 帮助主题的 Utility 类。API 的要点在您查看完整代码示例之前,建议您首先查看以下示例。这些示例阐释在本应用程序中使用的 API 的若干要点。所演示的所有示例代码都包含在 SampleServerSyncProvider 类中。除了在本节中演示的命令外,该完整代码示例还包含可将插入应用于服务器的命令以及选择和应用删除的命令。第一个示例直接应用于 DbServerSyncProvider 属性SelectNewAnchorCommand。其他示例应用于 Sales.Customer 表的SyncAdapter 对象。从服务器中检索新的定位点值以下代码示例指定从服务器中检索新定位点值的命令。SyncSession 类包含几个可在同步命令中使用的字符串常量。SyncNewReceivedAnchor 是这些常量之一。此外,还可以在查询中直接使用 @sync_new_received_anchor 文本。C#VB SqlCommand selectNewAnchorCommand = new SqlCommand(); string newAnchorVariable = "@" + SyncSession.SyncNewReceivedAnchor; selectNewAnchorCommand.CommandText = "SELECT " + newAnchorVariable + " = change_tracking_current_version()"; selectNewAnchorCommand.Parameters.Add(newAnchorVariable, SqlDbType.BigInt); selectNewAnchorCommand.Parameters[newAnchorVariable].Direction = ParameterDirection.Output; selectNewAnchorCommand.Connection = serverConn; this.SelectNewAnchorCommand = selectNewAnchorCommand; 指定一条从服务器上选择要应用于客户端的增量插入的命令下面的代码示例指定一条从服务器上选择要应用于客户端的增量插入的命令。用于增量变更的所有查询都将检查所需的变更是否已从变更跟踪表中清除。此检查从以下子句开始,并且在已清除变更后将引发错误:IF CHANGE_TRACKING_MIN_VALID_VERSION (object_id (@sync_table_name)) > @sync_last_received_anchorC#VB SqlCommand customerIncrInserts = new SqlCommand(); customerIncrInserts.CommandText = "IF @sync_initialized = 0 " + "SELECT Sales.Customer.[CustomerId], [CustomerName], [SalesPerson], [CustomerType] " + "FROM Sales.Customer LEFT OUTER JOIN " + "CHANGETABLE(CHANGES Sales.Customer, @sync_last_received_anchor) CT " + "ON CT.[CustomerId] = Sales.Customer.[CustomerId] " + "WHERE (CT.SYS_CHANGE_CONTEXT IS NULL OR CT.SYS_CHANGE_CONTEXT <> @sync_client_id_binary) " + "ELSE " + "BEGIN " + "SELECT Sales.Customer.[CustomerId], [CustomerName], [SalesPerson], [CustomerType] " + "FROM Sales.Customer JOIN CHANGETABLE(CHANGES Sales.Customer, @sync_last_received_anchor) CT " + "ON CT.[CustomerId] = Sales.Customer.[CustomerId] " + "WHERE (CT.SYS_CHANGE_OPERATION = 'I' AND CT.SYS_CHANGE_CREATION_VERSION " + "<= @sync_new_received_anchor " + "AND (CT.SYS_CHANGE_CONTEXT IS NULL OR CT.SYS_CHANGE_CONTEXT <> @sync_client_id_binary)); " + "IF CHANGE_TRACKING_MIN_VALID_VERSION(object_id(@sync_table_name)) " + "> @sync_last_received_anchor " + "RAISERROR (N'SQL Server Change Tracking has cleaned up tracking information for table ''%s''. " + "To recover from this error, the client must reinitialize its local database and try again' " + ",16,3,@sync_table_name) " + "END"; customerIncrInserts.Parameters.Add("@" + SyncSession.SyncInitialized, SqlDbType.Int); customerIncrInserts.Parameters.Add("@" + SyncSession.SyncLastReceivedAnchor, SqlDbType.BigInt); customerIncrInserts.Parameters.Add("@" + SyncSession.SyncClientIdBinary, SqlDbType.Binary); customerIncrInserts.Parameters.Add("@" + SyncSession.SyncNewReceivedAnchor, SqlDbType.BigInt); customerIncrInserts.Parameters.Add("@" + SyncSession.SyncTableName, SqlDbType.NVarChar); customerIncrInserts.Connection = serverConn; customerSyncAdapter. = customerIncrInserts; 指定一条从服务器上选择要应用于客户端的增量更新的命令下面的代码示例指定一条从服务器上选择要应用于客户端的增量更新的命令。C#VB SqlCommand customerIncrUpdates = new SqlCommand(); customerIncrUpdates.CommandText = "IF @sync_initialized > 0 " + "BEGIN " + "SELECT Sales.Customer.[CustomerId], [CustomerName], [SalesPerson], [CustomerType] " + "FROM Sales.Customer JOIN " + "CHANGETABLE(CHANGES Sales.Customer, @sync_last_received_anchor) CT " + "ON CT.[CustomerId] = Sales.Customer.[CustomerId] " + "WHERE (CT.SYS_CHANGE_OPERATION = 'U' AND CT.SYS_CHANGE_VERSION " + "<= @sync_new_received_anchor " + "AND (CT.SYS_CHANGE_CONTEXT IS NULL OR CT.SYS_CHANGE_CONTEXT <> @sync_client_id_binary)); " + "IF CHANGE_TRACKING_MIN_VALID_VERSION(object_id(@sync_table_name)) " + "> @sync_last_received_anchor " + "RAISERROR (N'SQL Server Change Tracking has cleaned up tracking information for table ''%s''. " + "To recover from this error, the client must reinitialize its local database and try again'" + ",16,3,@sync_table_name) " + "END"; customerIncrUpdates.Parameters.Add("@" + SyncSession.SyncInitialized, SqlDbType.Int); customerIncrUpdates.Parameters.Add("@" + SyncSession.SyncLastReceivedAnchor, SqlDbType.BigInt); customerIncrUpdates.Parameters.Add("@" + SyncSession.SyncNewReceivedAnchor, SqlDbType.BigInt); customerIncrUpdates.Parameters.Add("@" + SyncSession.SyncClientIdBinary, SqlDbType.Binary); customerIncrUpdates.Parameters.Add("@" + SyncSession.SyncTableName, SqlDbType.NVarChar); customerIncrUpdates.Connection = serverConn; customerSyncAdapter. = customerIncrUpdates; 指定一条将增量更新从客户端应用于服务器的命令在以下代码示例中,UPDATE 语句更新基表,并返回受影响的行的计数。如果行计数为 0,则表示发生了错误或冲突。有关更多信息,请参见如何处理数据冲突和错误。C#VB SqlCommand customerUpdates = new SqlCommand(); customerUpdates.CommandText = ";WITH CHANGE_TRACKING_CONTEXT (@sync_client_id_binary) " + "UPDATE Sales.Customer " + "SET [CustomerName] = @CustomerName, [SalesPerson] = @SalesPerson, [CustomerType] = @CustomerType " + "FROM Sales.Customer " + "JOIN CHANGETABLE(VERSION Sales.Customer, ([CustomerId]), (@CustomerId)) CT " + "ON CT.[CustomerId] = Sales.Customer.[CustomerId] " + "WHERE (@sync_force_write = 1 " + "OR CT.SYS_CHANGE_VERSION IS NULL OR CT.SYS_CHANGE_VERSION <= @sync_last_received_anchor " + "OR (CT.SYS_CHANGE_CONTEXT IS NOT NULL AND CT.SYS_CHANGE_CONTEXT = @sync_client_id_binary)) " + "SET @sync_row_count = @@rowcount; " + "IF CHANGE_TRACKING_MIN_VALID_VERSION(object_id(@sync_table_name)) > @sync_last_received_anchor " + "RAISERROR (N'SQL Server Change Tracking has cleaned up tracking information for table ''%s''. " + "To recover from this error, the client must reinitialize its local database and try again'" + ",16,3,@sync_table_name)"; customerUpdates.Parameters.Add("@" + SyncSession.SyncClientIdBinary, SqlDbType.Binary); customerUpdates.Parameters.Add("@CustomerName", SqlDbType.NVarChar); customerUpdates.Parameters.Add("@SalesPerson", SqlDbType.NVarChar); customerUpdates.Parameters.Add("@CustomerType", SqlDbType.NVarChar); customerUpdates.Parameters.Add("@CustomerId", SqlDbType.UniqueIdentifier); customerUpdates.Parameters.Add("@" + SyncSession.SyncForceWrite, SqlDbType.Bit); customerUpdates.Parameters.Add("@" + SyncSession.SyncLastReceivedAnchor, SqlDbType.BigInt); customerUpdates.Parameters.Add("@" + SyncSession.SyncRowCount, SqlDbType.Int); customerUpdates.Parameters["@" + SyncSession.SyncRowCount].Direction = ParameterDirection.Output; customerUpdates.Parameters.Add("@" + SyncSession.SyncTableName, SqlDbType.NVarChar); customerUpdates.Connection = serverConn; customerSyncAdapter.UpdateCommand = customerUpdates; 选择冲突行下面的命令从服务器数据库中选择冲突行(如果这些行仍存在于基表中)。C#VB SqlCommand customerUpdateConflicts = new SqlCommand(); customerUpdateConflicts.CommandText = "SELECT Sales.Customer.[CustomerId], [CustomerName], [SalesPerson], [CustomerType], " + "CT.SYS_CHANGE_CONTEXT, CT.SYS_CHANGE_VERSION " + "FROM Sales.Customer JOIN CHANGETABLE(VERSION Sales.Customer, ([CustomerId]), (@CustomerId)) CT " + "ON CT.[CustomerId] = Sales.Customer.[CustomerId]"; customerUpdateConflicts.Parameters.Add("@CustomerId", SqlDbType.UniqueIdentifier); customerUpdateConflicts.Connection = serverConn; customerSyncAdapter. = customerUpdateConflicts; 下面的命令从服务器数据库中选择冲突行(如果这些行已从基表中删除)。C#VB SqlCommand customerDeleteConflicts = new SqlCommand(); customerDeleteConflicts.CommandText = "SELECT CT.[CustomerId], " + "CT.SYS_CHANGE_CONTEXT, CT.SYS_CHANGE_VERSION " + "FROM CHANGETABLE(CHANGES Sales.Customer, @sync_last_received_anchor) CT " + "WHERE (CT.[CustomerId] = @CustomerId AND CT.SYS_CHANGE_OPERATION = 'D')"; customerDeleteConflicts.Parameters.Add("@" + SyncSession.SyncLastReceivedAnchor, SqlDbType.BigInt); customerDeleteConflicts.Parameters.Add("@CustomerId", SqlDbType.UniqueIdentifier); customerDeleteConflicts.Connection = serverConn; customerSyncAdapter. = customerDeleteConflicts; 有关如何处理数据冲突的更多信息,请参见如何处理数据冲突和错误。完整的代码示例下面的完整代码示例包括了上面介绍的代码示例以及用于执行同步的其他代码。C#VBusing System; using System.IO; using System.Text; using System.Data; using System.Data.SqlC