将基于游标的复制过程转换为SQL

时间:2012-01-10 03:36:27

标签: sql sql-server set

我正在尝试使用一个存储过程将父/子/孙子行复制到具有新唯一标识符的相同表中。这样做的目的是使用“订单行”和“订单行属性”生成重复的“订单”。当前的过程是使用游标完成的,我想尝试创建基于集合的版本。

我早期遇到的一个问题是,人工友好格式的自动编号是在存储过程中完成的。

DECLARE @sales_order_id nvarchar(50)
EXEC GetAutoNumber 'Order',  @sales_order_id output

执行在光标内完成,因为它循环遍历单个订单的订单行。有没有办法在飞行中调用它?我想过使用表值函数但不能,因为存储过程会更新自动编号表以创建新值。

理想情况下,我想制作一个插入语句,自动检索/更新可以在多个行中同时完成的自动编号,例如:

INSERT INTO ORDER (
    OrderId, -- Guid
    OrderNumber, -- Human Friendly value that needs Autoincremented
    ...
)
SELECT
    NEWID(),
    ???
FROM ORDER
WHERE OrderId = @OrderToBeCopied

我正在使用SQL Server 2008,有什么建议吗?

编辑:标识列不起作用的一个原因是这些自动编号存储的表服务于多个实体及其前缀。例如,这是自动编号表的DDL:

CREATE TABLE [dbo].[pt_autonumber_settings](
    [autonumber_id] [uniqueidentifier] NULL,
    [autonumber_prefix] [nvarchar](10) NULL,
    [autonumber_type] [nvarchar](50) NULL,
    [changed_by] [nvarchar](30) NOT NULL,
    [change_date] [datetime] NOT NULL,
    [origin_by] [nvarchar](30) NOT NULL,
    [origin_date] [datetime] NOT NULL,
    [autonumber_currentvalue] [nvarchar](50) NULL
) ON [PRIMARY]

因此,存储过程的最终结果是某个autonumber_type的最新autonumber_id,它还检索autonumber_prefix并将两者连接在一起。

2 个答案:

答案 0 :(得分:2)

是否有某些原因您无法使用IDENTITY列?

答案 1 :(得分:0)

请阅读以下编辑,因为我的原始答案不满意

我不完全确定您的OrderNumber如何递增,但您当然可以使用ROW_NUMBER()。查看the MSDN doco on it

假设您只想为每个订单ID分配一个号码,那么您将拥有类似的内容;

SELECT NEWID(),
       ROW_NUMBER() OVER (ORDER BY <whatever column you need to order by to make the row number meaningful>) As MyFriendlyId
FROM ORDER
WHERE OrderId = @OrderToBeCopied

如果需要某种初始种子值,那么您可以随时使用

ROW_NUMBER() OVER (ORDER BY <whatever column you need to order by to make the row number meaningful>) + 1000 As MyFriendlyId -- or whatever your seed value should be

修改:

我刚刚重新阅读了您的问题,我怀疑您希望OrderNumber在所有记录中都是唯一的。我最初误读它是一个增量行号来详细说明OrderId的行项目。

我在这种情况下的解决方案不会有任何好处,而且我更倾向于提出有关拥有标识列的其他答案。

您可以在开头选择MAX(OrderNumber),然后将其与ROW_NUMBER结合使用,但这很危险,因为它可能是脏读并且不保证单一性(如果有人执行并发插入)。如果你确实有一个独特的约束,并且在读取相同的MAX(OrderNumber)时有并发插入,那么你可能会遇到唯一的约束违规...所以是的...为什么你不能使用标识列:)