0

我们正在研究将持久层从 Oracle 移植到另一个数据库的各种选项,我们正在研究的一个是 MS SQL。但是,我们在整个代码中使用 Oracle 序列,因此移动似乎会让人头疼。我了解@identity,但这将是对持久性代码的大规模检修。

是否可以在 SQL Server 中创建一个可以处理序列的函数?

4

3 回答 3

1

这取决于您当前在 Oracle 中使用的序列。通常在插入触发器中读取一个序列。

从你的问题我猜是持久层在插入数据库之前生成序列(包括新的pk)

在 MSSQL 中,您可以将 SQL 语句与 ';' 组合在一起,因此要检索新创建记录的标识列,请使用 INSERT INTO ... ; 选择范围标识()

因此,插入记录的命令返回一个记录集,其中包含单行和单列,其中包含标识列的值。

您当然可以改变这种方法,并创建序列表(类似于 Oracle 中的双表),如下所示:

INSERT INTO SequenceTable (dummy) VALUES ('X');
SELECT @ID = SCOPE_IDENTITY();
INSERT INTO RealTable (ID, datacolumns) VALUES (@ID, @data1, @data2, ...)
于 2008-11-27T16:38:47.010 回答
1

我去年在一个项目上做了这个。基本上,我只是创建了一个包含序列名称、当前值和增量数量的表。

然后我创建了一个 4 procs :

  • GetCurrentSequence(sequenceName)
  • GetNextSequence(sequenceName)
  • CreateSequence(sequenceName, startValue, incrementAmount)
  • 删除序列(序列名称)

但是有一个你可能不理解的限制;函数不能有副作用。因此,您可以为 GetCurrentSequence(...) 创建一个函数,但 GetNextSequence(...) 需要是一个 proc,因为您可能希望增加当前序列值。但是,如果它是一个过程,您将无法直接在插入语句中使用它。

所以而不是

insert into mytable(id, ....) values( GetNextSequence('MySequence'), ....);

相反,您需要将其分成 2 行;

declare @newID int;
exec @newID = GetNextSequence 'MySequence';
insert into mytable(id, ....) values(@newID, ....);

此外,SQL Server 没有任何机制可以执行类似的操作

MySequence.Current

或者

MySequence.Next

希望有人会告诉我上述限制是不正确的,但我很确定它们是准确的。

祝你好运。

于 2008-11-29T06:47:12.510 回答
0

如果你有很多代码,无论如何你都会想要对代码进行大规模的检查;在 Oracle 中运行良好的东西并不总是在 MSSQL 中运行良好。例如,如果您有很多游标,虽然您可以将它们逐行转换为 MSSQL,但您不会获得良好的性能。

简而言之,这不是一件容易的事。

于 2008-11-28T17:09:41.223 回答