NULL を許可する次の組み合わせINSERT
&プロシージャをコーディングするためのより良い SQL Server 2008 R2 手法はありますか?UPDATE
INSERT
私は、他の開発者が NULL 挿入を処理できるINSERT
&UPDATE
プロシージャーをどのように書いているかを見ることに非常に興味があります (ユーザーがエントリを元に戻したいと考えていると想像してください)。私が興味を持っている、またはいくつかのトランザクションロールバック手法を使用した、より洗練されたエレガントなソリューションがあることを感謝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
OrderStatus
ステップ 2:が巻き戻せないことを示しましょう
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
ステップ 3: 最後に、ユーザーが最初の注文の株式を削除したいと仮定しましょう。次に、私の手順での不幸な方法では、他のデフォルト パラメータを渡す@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 から呼び出されます。