我的问题相对简单,但我还没有找到答案。我有一个只包含一行的表。该行有两列,ClientCode和ClientIndex。
我有一个选择查询,如下所示:
SELECT i.ClientCode + FORMAT(i.ClientIndex, "000000") FROM Indexes as I;
现在我运行了选择后我想将ClientIndex增加一个。
UPDATE Indexes SET ClientIndex = ClientIndex + 1;
动机:我希望能够创建连续的报告编号。因此,每次生成报告时,我都希望ClientIndex递增。为此,我需要锁定表格,选择我的号码,增加索引并解锁表格。
这在MS Access 2013中是否可行?使用存储过程在Sql中是微不足道的;但要求声明Access,并没有办法解决这个问题。此外,我正在构建一个客户端应用程序(使用.NET和F#),它将检索报告编号。
编辑:看起来人们并没有真正得到这个问题。我希望两个语句SELECT
和UPDATE
在同一个执行中运行。我 NOT 想要从某个客户端调用select并更新。
普通旧t-sql中的SP看起来像是:
CREATE PROCEDURE something
AS
BEGIN
declare @result as nchar(10);
set @result = <<select query>>;
<<update query>>;
select @result;
END
编辑:我正在构建一个.NET F#应用程序,它将调用Access数据库并检索报告编号。此应用程序将在Windows服务器上的Windows服务中运行。此报告编号可以大间隔同时调用约100次。
答案 0 :(得分:3)
我不希望调用代码必须对数据库进行两次调用才能使其正常工作。换句话说,我希望SELECT语句和UPDATE语句在同一个执行中运行。
Access数据库引擎不支持多语句批处理,因此您无法执行...
SELECT i.ClientCode + FORMAT(i.ClientIndex, "000000") FROM Indexes as I;
UPDATE Indexes SET ClientIndex = ClientIndex + 1;
......一气呵成。每个SQL语句都必须单独执行。
现在,如果在隔离级别为“可序列化”的事务中执行这两个语句,则不会出现问题。遗憾的是,Access ODBC Driver和Access OLEDB Provider都不支持System.Data.IsolationLevel.Serializable
进行事务处理。它们支持的最高隔离级别是ReadCommitted
,这并不足以阻止两个进程获得相同的ClientIndex。
据我所知,模仿可序列化事务的唯一方法是使用具有悲观锁定的Access DAO,如下所示:
// COM Reference required:
// Microsoft Office 14.0 Access Database Engine Object Library
//
var dbe = new DBEngine();
Database db = dbe.OpenDatabase(@"\\DINSDALE\Public\test\locktestBE.accdb");
Recordset rst = db.OpenRecordset("SELECT ClientIndex FROM Indexes",
RecordsetTypeEnum.dbOpenDynaset,
RecordsetOptionEnum.dbFailOnError,
LockTypeEnum.dbPessimistic);
bool keepTrying = true;
while (keepTrying)
{
try
{
rst.Edit();
int nextId = rst.Fields["ClientIndex"].Value; // get next ID,
rst.Fields["ClientIndex"].Value = nextId + 1; // increment value, and
rst.Update(); // write it back
rst.Close();
Console.WriteLine("The assigned ID is {0}", nextId);
keepTrying = false;
}
catch (System.Runtime.InteropServices.COMException e)
{
if (!e.Message.StartsWith("Could not update; currently locked by user"))
{
throw;
}
}
}
db.Close();
但是,在继续使用Access数据库作为服务的数据存储之前,您应该仔细考虑。处理高并发性和执行粒度锁定并不适合Access数据库引擎。 (Microsoft“强烈建议不要在Web应用程序中使用Access”有几个原因 - 参考:here - 听起来很多原因也适用于您的应用程序。)