是否有更好的 SQL Server 2008 R2 技术来编码以下允许 NULL的组合INSERT
&过程?UPDATE
INSERT
我很想看看其他开发人员如何编写INSERT
和UPDATE
处理 NULL 插入的程序(想象一个用户想要撤消一个条目)。我很欣赏将有更复杂和优雅的解决方案使用MERGE
或我有兴趣看到的一些事务回滚技术,但是,我确实要求您从第一原则建立您的示例,因为这可能会导致帖子具有更广泛的吸引力什么读者的T-SQL水平。
这个简单示例的基础是Orders
跟踪股票购买的表格。该程序应仅在 相同或增加UPDATES
时允许..OrderStatus
OrderStatus Explanation
-------------------------
0 Creation
1 Checking
2 Placement
3 Execution
...
8 Settlement
表结构:
CREATE TABLE Orders(
OrderID INT IDENTITY,
Ticker VARCHAR(20) NOT NULL,
Size DECIMAL(31,15) NULL,
Price DECIMAL(31,15) NULL,
OrderStatus TINYINT NOT NULL)
此外,假设我们有以下数据,以便我们可以测试修改数据:
SET IDENTITY_INSERT [dbo].[Orders] ON
INSERT INTO [dbo].[Orders] ([OrderID], [Ticker], [Size], [Price], [OrderStatus])
VALUES (1, N'MSFT', CAST(1 AS Decimal(31, 15)), NULL, 0)
,(2, N'GOOG', CAST(2 AS Decimal(31, 15)), CAST(523 AS Decimal(31, 15)), 5)
,(3, N'AAPL', CAST(1 AS Decimal(31, 15)), NULL, 0)
SET IDENTITY_INSERT [dbo].[Orders] OFF
你应该有以下数据:
OrderID Ticker Size Price OrderStatus
-----------------------------------------------
1 MSFT 1.000 NULL 0
2 GOOG 2.000 523.000 5
3 AAPL 1.000 NULL 0
现在是有趣的部分。这是我设计一个可以处理 NULL 插入(即允许用户撤消条目)的组合INSERT
&过程的最大努力。UPDATE
请注意,我需要一个输入参数来区分 NULL 的输入值是否是有意的,是否需要写入表中,而 NULL 显示为缺少的输入参数。希望很清楚我为什么要问这个问题,因为我发现我的技术非常冗长。
CREATE PROCEDURE [dbo].[Upsert_Orders] @isNullInsert BIT = 0
,@OrderID INT = NULL
,@Ticker VARCHAR(20) = NULL
,@Size VARCHAR(100) = NULL
,@Price VARCHAR(100) = NULL
,@OrderStatus TINYINT = NULL
AS
BEGIN
IF (@OrderID IS NOT NULL)
-- First check if @OrderID exists
IF (
SELECT OrderID
FROM dbo.Orders
WHERE OrderID = @OrderID
) IS NULL
BEGIN
-- @OrderID does not exist therefore replace with NULL
SET @OrderID = NULL
PRINT 'spUO. Replaced OrderID ' + CAST(@OrderID AS VARCHAR) + ' input parameter with NULL.'
END
IF @OrderID IS NULL
BEGIN
-- @OrderID IS NULL so INSERT a new record
PRINT 'spUO Inserting a new record into the Orders'
INSERT INTO Orders (
-- OrderID not needed as IDENTITY new record.
Ticker
,Size
,Price
,OrderStatus
)
VALUES (
-- @OrderID not needed as IDENTITY new record
@Ticker
,@Size
,@Price
,@OrderStatus
)
END
ELSE
BEGIN
-- @OrderID IS NOT NULL therefore UPDATE the record @OrderID
PRINT 'spUO Modifying existing record with OrderID ' + CAST(@OrderID AS VARCHAR)
-- Declare CurrentVariables for @OrderID
DECLARE -- @CurrentOrderID INT not needed as @OrderID Found
@CurrentTicker VARCHAR(20)
,@CurrentSize DECIMAL(31, 15)
,@CurrentPrice DECIMAL(31, 15)
,@CurrentOrderStatus TINYINT
-- Populate Current Variables from Table Orders
SELECT -- @CurrentOrderID = OrderID not needed as @OrderID Found
@CurrentTicker = Ticker
,@CurrentSize = Size
,@CurrentPrice = Price
,@CurrentOrderStatus = OrderStatus
FROM Orders
WHERE OrderID = @OrderID
IF ISNULL(@OrderStatus, @CurrentOrderStatus) >= @CurrentOrderStatus
BEGIN
-- Update @OrderID if not moving backwards
IF @isNullInsert = 0
BEGIN
-- We are not updating the record with NULL
PRINT 'spUO NULL Parameter Input Values get replaced with the existing entries'
UPDATE Orders
SET -- OrderID = ISNULL(@OrderID, @CurrentOrderID) not needed as @OrderID Found
Ticker = ISNULL(@Ticker, @CurrentTicker)
,Size = ISNULL(@Size, @CurrentSize)
,Price = ISNULL(@Price, @CurrentPrice)
,OrderStatus = ISNULL(@OrderStatus, @CurrentOrderStatus)
WHERE OrderID = @OrderID
END
ELSE
BEGIN
-- We are potentially overwritting the record with NULL
PRINT 'spUO Old entries may be overwritten with NULL'
UPDATE Orders
SET -- OrderID = ISNULL(@OrderID, @CurrentOrderID) not needed as @OrderID Found
Ticker = @Ticker
,Size = @Size
,Price = @Price
,OrderStatus = @OrderStatus
WHERE OrderID = @OrderID
END
END
ELSE
-- User is trying to re-write hostory. Do Nothing
PRINT 'spUO You do not have permissions to roll back the OrderStatus.'
END
END
现在我们有了一个 UPSERT 过程,让我来说明它的用法:
第 1 步:插入新行以显示购买部分福特股票的意向:
EXEC dbo.Upsert_Orders @Ticker = 'F',
@Size = 1,
@Price = 10,
@OrderStatus = 2
第 2 步:让我们证明OrderStatus
无法回卷
EXEC dbo.Upsert_Orders @OrderID = 4,
@Ticker = 'F',
@Size = 1,
@Price = 10,
@OrderStatus = 1
这会产生所需的输出:
spUO Modifying existing record with OrderID 4
spUO You do not have permissions to roll back the OrderStatus.
数据现在看起来像:
OrderID Ticker Size Price OrderStatus
-----------------------------------------------
1 MSFT 1.000 NULL 0
2 GOOG 2.000 523.000 5
3 AAPL 1.000 NULL 0
4 F 1.000 10.000 2
第三步:最后,假设用户要删除第一笔订单的股份,那么我的程序下的不幸方法需要传递其他默认参数,并且@isNULLInsert BIT
需要设置为1。
EXEC dbo.Upsert_Orders @isNullInsert = 1,
@OrderID = 1,
@Ticker = 'MSFT',
@Size = NULL,
@Price = NULL,
@OrderStatus = 0
希望这个完整的示例说明了添加新记录、更新现有记录和删除记录字段的概念。为这篇文章的长度道歉,但这是我能够产生的最简洁的代码!
最终数据:
OrderID Ticker Size Price OrderStatus
------------------------------------------------
1 MSFT NULL NULL 0
2 GOOG 2.000 523.000 5
3 AAPL 1.000 NULL 0
4 F 1.000 10.000 2
谢谢大家,
伯蒂。
ps 这将从 Excel VBA 中调用。