我们正在研究将持久层从 Oracle 移植到另一个数据库的各种选项,我们正在研究的一个是 MS SQL。但是,我们在整个代码中使用 Oracle 序列,因此移动似乎会让人头疼。我了解@identity,但这将是对持久性代码的大规模检修。
是否可以在 SQL Server 中创建一个可以处理序列的函数?
我们正在研究将持久层从 Oracle 移植到另一个数据库的各种选项,我们正在研究的一个是 MS SQL。但是,我们在整个代码中使用 Oracle 序列,因此移动似乎会让人头疼。我了解@identity,但这将是对持久性代码的大规模检修。
是否可以在 SQL Server 中创建一个可以处理序列的函数?
这取决于您当前在 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, ...)
我去年在一个项目上做了这个。基本上,我只是创建了一个包含序列名称、当前值和增量数量的表。
然后我创建了一个 4 procs :
但是有一个你可能不理解的限制;函数不能有副作用。因此,您可以为 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
希望有人会告诉我上述限制是不正确的,但我很确定它们是准确的。
祝你好运。
如果你有很多代码,无论如何你都会想要对代码进行大规模的检查;在 Oracle 中运行良好的东西并不总是在 MSSQL 中运行良好。例如,如果您有很多游标,虽然您可以将它们逐行转换为 MSSQL,但您不会获得良好的性能。
简而言之,这不是一件容易的事。